How to communicate from Mainactivity to Fragment using callback interface?

时间:2016-07-11 19:41:00

标签: android android-layout android-fragments android-viewpager navigation-drawer

I'm having navigation drawer with four menu's and each menu has own fragments , Inside first fragment has view pager sliding tab with 2 fragments,

Activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/drawer_layout"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:fitsSystemWindows="true">

    <android.support.design.widget.CoordinatorLayout  
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/main_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:animateLayoutChanges="true"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

            <android.support.design.widget.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:tabIndicatorColor="@color/white"
                app:tabIndicatorHeight="4dp" />

        </android.support.design.widget.AppBarLayout>

////////////// Here I'm replacing each fragments ////////////////
        <FrameLayout   
            android:id="@+id/main_content_framelayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end|bottom"
            android:layout_margin="@dimen/fab_margin"
            android:src="@drawable/ic_done"
            android:visibility="gone"/>

    </android.support.design.widget.CoordinatorLayout>


        <android.support.design.widget.NavigationView
            android:id="@+id/nav_view"
            android:layout_height="match_parent"
            android:layout_width="wrap_content"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/nav_header"
            app:menu="@menu/drawer_view"/>

    </android.support.v4.widget.DrawerLayout>

ManinActivity- DrawerSelection

 public void selectDrawerItem(MenuItem menuItem) {
        // Create a new fragment and specify the fragment to show based on nav item clicked
        Fragment fragment = null;
        Class fragmentClass = null;

        switch (menuItem.getItemId()) {
            case R.id.nav_home:
                fragmentClass = Home_Tab_Fragment.class;
                break;
            case R.id.nav_myorders:
                fragmentClass = SecondFragment.class;
                break;
            case R.id.nav_myoffers:
                fragmentClass = ThirdFragment.class;
                break;
            case R.id.nav_notification:
                fragmentClass = FourthFragment.class;
                break;

        }

                fragment = (Fragment) fragmentClass.newInstance();
                FragmentManager fragmentManager = getSupportFragmentManager();
                fragmentManager.beginTransaction().replace(R.id.main_content_framelayout, fragment).commit();
                mDrawerLayout.closeDrawers();

}

HomeTabFragment

public class Home_Tab_Fragment extends Fragment {

    private FragmentActivity myContext;
    ViewPager viewPager;
    TabLayout tabLayout;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView =  inflater.inflate(R.layout.layout_viewpager, container, false);
          viewPager = (ViewPager) rootView.findViewById(R.id.view_pager);
        return rootView;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        SlidingTabAdapter adapter = new SlidingTabAdapter(getChildFragmentManager());
        adapter.addFragment(new FirstTabFragment(), "First TAB");
        adapter.addFragment(new SecondTabFragment(), "Second Tab");
        viewPager.setAdapter(adapter);
        tabLayout = (TabLayout) getActivity().findViewById(R.id.tabs);
        tabLayout.setVisibility(View.VISIBLE);
        tabLayout.setupWithViewPager(viewPager);
    }

}

SlidingTabAdapter

public class SlidingTabAdapter extends FragmentPagerAdapter {

    private final List<Fragment> mFragments = new ArrayList<>();
    private final List<String> mFragmentTitles = new ArrayList<>();

    public SlidingTabAdapter(FragmentManager fm) {
        super(fm);
    }

    public void addFragment(Fragment fragment, String title) {
        mFragments.add(fragment);
        mFragmentTitles.add(title);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

    @Override
    public int getCount() {
        return mFragments.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitles.get(position);
    }
}

layout_viewpager.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

FirstFragment

public class FirstTabFragment extends Fragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     View rootView = inflater.inflate(R.layout.fragment_first, container, false);
        getActivity().setTitle("Foodies");
        return rootView ;
    }

  public void updateFirstFragmentValues(){
      //Doing some operations
  }

}

Inside MainActivity , I want to call FirstTabFragment method [updateFirstFragmentValues()]

I tried adding TAG in FirstTabFragment ,

public static final String TAG ="FirstTabFragment.TAG";

Then I invoked in MainActivity like below , but Fragment always null.

 public void invokeMethodFromFirstTabFragment() {
        FragmentManager fm = this.getSupportFragmentManager();
        FirstTabFragment fb=(FirstTabFragment)fm.findFragmentByTag(FirstTabFragment.TAG);
        if (null != fb) {
            fb.updateFirstFragmentValues();
        }else{
            L.m("Fragment is null===========");
        }
    }

Kindly advise , How to call "FirstTabFragment" method from inside "MainActivity"

Please note FirstTabFragment is not added directly to MainActivity , its added through "Home_Tab_Fragment".

3 个答案:

答案 0 :(得分:0)

编辑:

您无法直接从MainActivity访问FirstTabFragment方法。首先,您必须从活动中调用Home_Tab_Fragment方法。然后,从该方法,您可以调用FirstTabFragment方法。

这是策略:

第1步:Home_Tab_FragmentFirstTabFragment通讯

定义一个像这样的界面

public interface IHomeToFirstFragmentController{
          void firstFragmentMethod();
    } 

现在实现IHomeToFirstFragmentController中的FirstTabFragment。那么你必须实现firstFragmentMethod()

@overrride
    void firstFragmentMethod(){

    }

使用此方式从firstFragmentMethod调用此Home_Tab_Fragment方法

YOUR_fragmentInstance.firstFragmentMethod();

第2步:活动Home_Tab_Fragment

定义一个像这样的界面

public interface IActivityToHomeTabController{
          void callFirstFragment();
    }

现在实现IFragmentController中的Home_Tab_Fragment。那么你必须实现callFirstFragment()

@overrride
void callFirstFragment(){
  YOUR_fragmentInstance.firstFragmentMethod();
}

编辑2:

使用这种方式调用片段

((IFragmentController)YOUR_fragmentInstance).firstFragmentMethod();

希望这会让您对这个主题有所了解。有关详细信息,请访问this answer

答案 1 :(得分:0)

好的,阅读你的所有回复,我知道你只需要在创建时将数据传递给片段并且能够执行Fragment的一些方法。好的,足够简单:

IMessageFragment接口

public interface IMessageFragment {
  /**
   * Method to receive new message text
   * @param text Message text to receive
   */
   void updateMessageText(String text);
}

MessageFragment

public class MessageFragment extends Fragment implements IMessageFragment {
  /**
   * Bind views using ButterKnife
   */
  @BindView(R.id.textView) TextView mTextView;

  /**
   * Bundle data
   */
  private String mMessageText;

  /**
   * Unique id of bundle data
   */
  private static final String MESSAGE_EXTRA_KEY = "f_message";

  /**
   * New fragment pattern. This is pretty much all the magic PLUS this
   * looks by far better than `new Fragment()` upon instatiation
   */
  public static MessageFragment newFragment(String message) {
      // 1. Create new fragment
      MessageFragment auctionFragment = new MessageFragment();
      // 2. Create bundle for fragment params
      Bundle args = new Bundle();
      // 3. Put position
      args.putString(MESSAGE_EXTRA_KEY, message);
      // 4. Set arguments
      auctionFragment.setArguments(args);
      return auctionFragment;
  }


  @Nullable
  @Override
  public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
      View view = inflater.inflate(R.layout.tutorial_fragment, container, false);

      /**
       * Bind views
       */
      ButterKnife.bind(this, view);

      // Update UI
      updateUI();

      return view;
  }

  /**
   * Method to update value of mTextView
   */
  private void updateUI() {
      if(!mMessageText.equals("")) {
          mTextView.setText(mMessageText);
      }
  }

  @Override
  public void updateMessageText(String text) {
      mMessageText = text;
      updateUI();
  }
}

Stuff非常简单,界面只存在于良好的代码风格和支持设计模式。

答案 2 :(得分:-1)

首先,您创建界面:

public interface CallBackListener{
      void onCallBack();
}

在片段中

public MyFragment extends Fragment{
    private CallBackListener mCallBack;

    @Override
    public void onAttach(Context context) {
        AppCompatActivity activity;
        if (context instanceof AppCompatActivity) {
            activity = (AppCompatActivity) context;
            try {
                mCallBack= (CallBackListener ) activity;
            } catch (ClassCastException e) {
                throw new ClassCastException(activity.toString() + " class must be implement" +
                        " OnBackFragmentListener");
            }
        }
        super.onAttach(context);
    }
}

使用:

mCallBack.onCallBack();

在Activity中,您必须实现interface:

public MyActivity extends AppCompatActivity implements CallBackListener{

   @Override
   public void onCallBack(){
   // Do somethings here...
   }
}