I have one Activity and two Fragments for a tablayout
containing a viewpager
.
Now I can communicate from the fragment to the Activity by implementing the google's guide callback interface. But how can I communicate the other way from activity to fragment? If something happens in the Activity (external events) I want to update the Fragment. I managed to get the Frag1 fragment with
MyFragmentPagerAdapter a = (MyFragmentPagerAdapter) viewPager.getAdapter();
Frag1 frag = (Frag1) a.getItem(0);
but when I call public methods on frag I get a IllegalStateException: Fragment not attached to Activity probably because getItem(0) returns a new instance of Frag1 and this is not attached yet... is there anyone who can provide a clean solution for this whole Viewpager -> Activity to Fragment communication?
Some code for you:
in Activity:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
if (viewPager != null) {
viewPager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager()));
}
TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
if (tabLayout != null) {
tabLayout.setupWithViewPager(viewPager);
}
}
activity layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:context="com.MainActivity">
<android.support.design.widget.TabLayout
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"/>
</LinearLayout>
MyFragmentPagerAdapter:
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 2;
private String tabTitles[] = new String[] { "tab1", "tab2" };
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return Frag1.newInstance(position + 1);
case 1:
return Frag2.newInstance(position + 1);
default:
return null;
}
}
@Override
public int getCount() {
return PAGE_COUNT;
}
@Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
}
Frag1:
public class Frag1 extends Fragment {
public static final String ARG_PAGE = "ARG_PAGE";
private int mPage;
private onFrag1InteractionListener mListener;
public Frag1() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @return A new instance of fragment Frag1.
*/
public static Frag1 newInstance(int page) {
Frag1 fragment = new Frag1();
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mPage = getArguments().getInt(ARG_PAGE);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_1, container, false);
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof onFrag1InteractionListener) {
mListener = (onFrag1InteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement onFrag1InteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface onFrag1InteractionListener {
// TODO: Update argument type and name
void onFrag1Interaction(Action action);
}
You need to set up some event listener logic where the fragment registers with the activity for the event it wants. The fragment should register on creation and unregister on destruction.
Then when the event occurs, the activity goes through the list of registered listeners and notifies them of the event.
I give a detailed example in this answer.
You can use an event bus library to simplify some of the wiring between the activity and the fragments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With