Android ViewPager, switching from fragment to another fragment - android

I have a viewpager with 2 pages, on each fragment i put a button to switching fragment,
but if i change orientation switching doesn't work.
For switching fragment I using my OnChangePageButtonClick interface
Why is this happening?
ViewPager Activity:
public class ViewPagerMusic extends FragmentActivity implements OnChangePageButtonClick {
private ViewPager vp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_pager_music);
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(super.getSupportFragmentManager(), fragments);
vp = (ViewPager)findViewById(R.id.viewpager);
vp.setAdapter(viewPagerAdapter);
}
private class ViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
MainPage mainPage = new MainPage();
mainPage.setOnChengeButtonListener(ViewPagerMusic.this);
return mainPage;
case 1:
PlaylistPage playlistPage = new PlaylistPage();
playlistPage.setOnChengeButtonListener(ViewPagerMusic.this);
return playlistPage;
}
return null;
}
#Override
public int getCount() {
return 2;
}
}
#Override
public void selectPage(int page) {
vp.setCurrentItem(page);
}
}
my Frgamnets:
public class MainPage extends Fragment {
public MainPage() {
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.music_main_page, container, false);
ImageButton btnPlaylist = (ImageButton)v.findViewById(R.id.btnGoPlaylist2);
btnPlaylist.setOnClickListener(onButtonListener);
return v;
}
private OnClickListener onButtonListener = new OnClickListener() {
#Override
public void onClick(View view) {
onChangePageButtonClick.selectPage(1);
}
};
public void setOnBackButtonListener(OnChangePageButtonClick onChangePageButtonClick) {
this.onChangePageButtonClick = onChangePageButtonClick;
}
private OnChangePageButtonClick onChangePageButtonClick;
}
Playlist fragment is similar to MainPage fragment.

Your fragments are storing a reference to the ViewPagerMusic activity. However, after rotation, the activity is destroyed and recreated, so the fragments now contain a reference to the old activity.
Instead of storing a reference to the activity, you can call the activity's method from the fragment like this:
((ViewPagerMusic) getActivity()).selectPage(1);

just create this method in your view pager
#Override
public void selectPage(int page) {
vp.setCurrentItem(page);
}
and then call this in your onclick method
((ViewPagerMusic) getActivity()).selectPage(1);

Related

Retrive data from activity every time oncreateViwe of fragments

Activity
public class GroupesActivity extends BaseActivity {
SelectedBundle selectedBundle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_groupes);
sectionsPagerAdapter = new GroupPagerAdapter(this, getSupportFragmentManager());
viewPager.setAdapter(sectionsPagerAdapter);
tabs.setupWithViewPager(viewPager);
}
private void getAllGroup() {
// api call retrive data
// send data using interface on response
// set data selectedBundle.onBundleSelect(isVisible,calanderModelList,groupModelList,eventModelList);
}
public void setOnBundleSelected(SelectedBundle selectedBundle) {
this.selectedBundle = selectedBundle;
}
public interface SelectedBundle {
void onBundleSelect(boolean isVisible, List<CalanderModel> calanderModelList, List<GroupModel> groupModelList, List<EventModel> eventModelList);
}
}
Frgment
public class FragmentOne extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_all_groups_fragments, container, false);
// get data only once on oncreateview
((GroupesActivity) getActivity()).setOnBundleSelected(new GroupesActivity.SelectedBundle() {
#Override
public void onBundleSelect(boolean isVisible, List<CalanderModel> calanderModelListtt, List<GroupModel> groupModelList, List<EventModel> eventModelList) {
Log.e("retrive data","data")
}
});
return root;
}
}
GroupPagerAdapter
public class GroupPagerAdapter extends FragmentPagerAdapter {
#StringRes
private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2, R.string.tab_text_3};
private final Context mContext;
public GroupPagerAdapter(Context context, FragmentManager fm) {
super( fm);
this.mContext=context;
}
#NonNull
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new AllGroupsFragments();
case 1:
return new HostFragments();
case 2:
return new GuestFragments();
}
return null;
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return mContext.getResources().getString(TAB_TITLES[position]);
}
#Override
public int getCount() {
return 3;
}
}
problem
i have three fragments in tabview when i swipe this obove fragment
and then come again in this fragmnet that interface not called and i'm
not getting data from activity
How to get that data again from its parent activity, i need to only
retrive that data from activity on each time of fragments oncreateView
Thanks in adavance ;)
Use setMenuVisibility() method in Fragment to fix the issue.
//In fragments
#Override
public void setMenuVisibility(final boolean isVisible) {
super.setMenuVisibility(isVisible);
if (isVisible) {
//visible to user- do ur stuff
((GroupesActivity) getActivity()).setOnBundleSelected(new
GroupesActivity.SelectedBundle() {
#Override
public void onBundleSelect(boolean isVisible, List<CalanderModel>
calanderModelListtt, List<GroupModel> groupModelList, List<EventModel>
eventModelList) {
Log.e("retrive data","data")
}
});
}
}
the following link may help if you face any issues:
How to determine when Fragment becomes visible in ViewPager

Clear data of fragments in ViewPager with each swipe

#Override
public void onViewDetachedFromWindow(#NonNull FragmentViewHolder holder) {
super.onViewDetachedFromWindow(holder);
}
I have many independent EditText with different id in each fragments of viewpager. For each swipe I want to clear these EditText and make them default.
I can clear text using:
holder.itemview.findViewById(R.id.first).setText("something");
but it won't a clear text.
What should I do?
Edit: whole testing Code:
I prepare a test fragment. When I click button,it changes text in current fragment. When I swipe to second fragment, It should be cleared or changed into its default value at xml.
TestFragment
public class TestFragment extends Fragment {
private TestViewModel mViewModel;
private ViewPager2 mViewPager;
private Button btnTest;
public static TestFragment newInstance() {
return new TestFragment();
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.test_fragment, container, false);
btnTest=(Button)view.findViewById(R.id.etTest);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(TestViewModel.class);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mViewPager = view.findViewById(R.id.myPager);
mViewPager.setSaveFromParentEnabled(false);
mViewPager.setOffscreenPageLimit(1);
mViewPager.setAdapter(new ViewPagerAdapter(getChildFragmentManager(),getLifecycle()));
TabLayout tabLayout = view.findViewById(R.id.tabs);
new TabLayoutMediator(tabLayout, mViewPager,
new TabLayoutMediator.TabConfigurationStrategy() {
#Override
public void onConfigureTab(#NonNull TabLayout.Tab tab, int position) {
tab.setText(((ViewPagerAdapter)(mViewPager.getAdapter())).mFragmentNames[position]);//Sets tabs names as mentioned in ViewPagerAdapter fragmentNames array, this can be implemented in many different ways.
}
}
).attach();
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
Fragment current=((ViewPagerAdapter)(mViewPager.getAdapter())).createFragment(tab.getPosition());//clear data here or below
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}});
btnTest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int cur=((ViewPagerAdapter)(mViewPager.getAdapter())).getCurrentPos();
switch (cur){
case 0:
Fragment current=((ViewPagerAdapter)(mViewPager.getAdapter())).createFragment(0);
TextView tF= current.getView().findViewById(R.id.first);
tF.setText("Clicked while 1");
break;
case 1:
Fragment current2=((ViewPagerAdapter)(mViewPager.getAdapter())).createFragment(1);
TextView tF2= current2.getView().findViewById(R.id.second);
tF2.setText("Clicked while 2");
break;
}
}
});
}
public class ViewPagerAdapter extends FragmentStateAdapter {
private int currentPos;
private final Fragment[] mFragments = new Fragment[] {
new FirstFragment(),
new SecondFragment(),
};
public final String[] mFragmentNames = new String[] {
"First",
"Second"
};
public ViewPagerAdapter(#NonNull FragmentManager fragmentManager, #NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
}
#Override
public void onViewDetachedFromWindow(#NonNull FragmentViewHolder holder) {
super.onViewDetachedFromWindow(holder);
if(currentPos!=0){
TextView textView =(TextView)holder.itemView.findViewById(R.id.first);//clear data here or up
}
}
#Override
public int getItemCount() {
return mFragments.length;
}
#Override
public long getItemId(int position) {
this.setCurrentPos(position);
return super.getItemId(position);
}
public int getCurrentPos() {
return currentPos;
}
public void setCurrentPos(int currentPos) {
this.currentPos = currentPos;
}
#NonNull
#Override
public Fragment createFragment(int position) {
return mFragments[position];
}
}}
I can handle on onViewDetachedFromWindow or onTabUnselected. Both can change view.
First Fragment
public class FirstFragment extends Fragment {
private View mLeak;
private TextView tvTest;
public FirstFragment() {
}
public static FirstFragment newInstance(String param1, String param2) {
FirstFragment fragment = new FirstFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mLeak = inflater.inflate(R.layout.fragment_first, container, false);
tvTest=mLeak.findViewById(R.id.first);
return mLeak;
}
#Override
public void onDetach() {
super.onDetach();
mLeak=null;
}}
Approach 1:
Set this line on your viewpager :
viewPager.setOffscreenPageLimit(1);
This will simply refresh each fragment again when it's loaded.
Approach 2:
Create an interface and implement it on each fragment. In your activity/fragment where viewpager is defined, use "addOnPageChangeListener" on viewpager, and when the different page is selected, simply use the interface to get back the fragment instance and call the required methods in the fragment, to clear/change the text.
Code :
//Your Activity
class HomeActivity extends Activity{
...Methods...
public void setUpViewpager(){
//setup your viewpager
viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
#Override
public void onPageSelected(int position) {
ChangeText fragment = (ChangeText) viewpager.getFragment(position);
fragment.changeText();
}
#Override
public void onPageScrollStateChanged(int state) {}
});
}
interface ChangeText{
void changeText();
}
}
//Your fragment
class FirstFragment extends Fragment implements HomeActivity.ChangeText{
...Methods...
public void changeText(){
//change the textview text here
}
}
class SecondFragment extends Fragment implements HomeActivity.ChangeText{
...Methods...
public void changeText(){
//change the textview text here
}
}

Refresh Fragment in FragmentActivity

My app have a fragmentActivity with tabBar which control over the view pager and contain 3 fragments ,when i update my class User in fragmentB,i need to display him in fragmentC.
my question is how to refresh fragmentC every time when i add new User.
before i wrote this question i tried all the solution from this questions:
1.Update ViewPager dynamically?
2.refresh fragment at reload
3.Update Fragment from ViewPager
4.ViewPager PagerAdapter not updating the View
5.How to update fragment content from activity (viewpager)?
here is my code
FragmentActivity:
public class MainActivityTab extends FragmentActivity {
public SectionsPagerAdapter mSectionsPagerAdapter;
public ViewPager mViewPager;
public static MainActivityTab instance = null;
public static MainActivityTab getInstance(){
return instance;
}
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_tab);
getWindow().setStatusBarColor(Color.rgb(191,76,12));
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.getTabAt(0).setIcon(R.drawable.icon_A);
tabLayout.getTabAt(1).setIcon(R.drawable.icon_B);
tabLayout.getTabAt(2).setIcon(R.drawable.icon_C);
mViewPager.setCurrentItem(1,false);
}
FragmentStatePagerAdapter:
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return FragmentA.newInstance();
case 1:
return FragmentA.newInstance();
case 2:
return FragmentC.newInstance();
default:
return null;
}
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
return null;
}
}
FragmentB:
public class FragmentB extends Fragment {
EditText name;
EditText age;
Button btnSave;
public static FragmentB newInstance() {
FragmentB fragment = new FragmentB();
return fragment;
}
public FragmentB() {}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_new2, container, false);
name = (EditText) rootView.findViewById(R.id.name);
age = (EditText) rootView.findViewById(R.id.age);
btnSave = (Button) rootView.findViewById(R.id.btnSave);
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
UserManager.getInstance().creteUser(name.getText().toString(),age.getText().toString());
}
});
return rootView;
}
}
FragmentC:
public class FragmentC extends Fragment {
TextView nameTxt;
TextView ageTxt;
public static FragmentC newInstance(){
FragmentC instance = new FragmentC();
return instance;
}
public FragmentC(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_new3, container, false);
nameTxt = (TextView) rootView.findViewById(R.id.nameTxt);
ageTxt = (TextView) rootView.findViewById(R.id.ageTxt);
showUser();
return rootView;
}
public void showUser(){
if(UserManager.getInstance().getUser().getName()!=null){
nameTxt.setText(UserManager.getInstance().getUser().getName().toString());
ageTxt.setText(UserManager.getInstance().getUser().getAge().toString());
}
}
}
You could create a callback like:
public interface UserChangedCallback{
void onUserChanged();
}
and implement this callback on every view/fragment where you want to access the user:
#Override
public void onUserChanged() {
adapter.notifyDataSetChanged();
// or if you don't have an adapter refresh your textfields or whatever you want
}
Register the callback on the usermanager via UserManager.getInstance().registerCallback(this). Internally the usermanager have to add the callback to an internal list.
Create a private function inside your usermanager:
private void notifyCallbacks() {
for(UserChangedCallback callback : registeredCallbacks) {
callback.onUserChanged();
}
}
If you add/modify/delete a user you always have to call this function at the end. For example:
public void addUser(User user) {
users.add(user);
notifiCallbacks();
}
Now every view will be notified and refreshed.
Important!
Don't forget to unregister the callback from the usermanager on onDestroy() to avoid memory leaks.
Found solution:
i used in the method onPageSelected,when position is 2 my fragment detach and afterwards attach the fragment.
working perfectly!
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if(position==2){
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction().add(R.id.fragmant_new3, FragmentC.newInstance());
fragmentTransaction.detach(FragmentC.newInstance());
fragmentTransaction.attach(FragmentC.newInstance());
fragmentTransaction.commit();
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});

View pager skipping to irregular position when I click button in second fragment android?

I am using view pager in activity and the sequence is - when I click the next button in first page, it should go to the second page. If I click the button in second page, it should go to third and so on. But my current app is behaving weird, i.e, When I click next button in second page, it goes to fourth page. Once again when I click first button in first page, it jumps to third page and so on..
Here is code.
public class ViewPagerActivity extends AppCompatActivity {
private ViewPager pager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewpager_act);
setViewPager();
/*pager.setPageTransformer(true, new ZoomPageTransformer());
pager.setAdapter(new MyViewPagerAdapter(getSupportFragmentManager()));
pager.post(new Runnable() {
#Override
public void run() {
pager.setCurrentItem(position); //don't know how to use this from fragment
}
});*/
}
private void setViewPager() {
pager = (ViewPager) findViewById(R.id.viewPager);
FragmentManager fm = getSupportFragmentManager();
ViewPagerAdapter adapter = new ViewPagerAdapter(fm);
pager.setAdapter(adapter);
}
public void setCurrentItem(int selectedPosition) {
pager.setCurrentItem(selectedPosition, true);
}
private class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return FirstPager.newInstance();
case 1:
return SecondPager.newInstance();
case 2:
return ThirdPager.newInstance();
case 3:
return FourthPager.newInstance();
case 4:
return FifthPager.newInstance();
case 5:
return SixthPager.newInstance();
default:
return null;
}
}
#Override
public int getCount() {
return 6;
}
}
FirstPager:
public class FirstPager extends Fragment {
private ImageView slideArrow;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.first_pager, container, false);
return v;
}
public static FirstPager newInstance() {
FirstPager fragment = new FirstPager ();
return fragment;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initUI();
}
private void initUI() {
slideArrow = (ImageView) getActivity().findViewById(R.id.next_arrow);
slideArrow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((ViewPagerActivity)getActivity()).setCurrentItem (1);
}
});
}
}
Similarly in other fragments, I gave currentItem as 2,3,4,5 and 6. But it’s position behavior is not correct.
I referred some post but how in my case, how I will apply for a method to pass from fragment to make the position to work correctly?
I think the best approach would be this:
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
slideArrow = (ImageView) getActivity().findViewById(R.id.next_arrow);
Are you sure, you're calling this correctly? You're not.
You're calling findViewById of the arrow inside your activity. A ViewPager works by loading this page, and pre-loading next and previous pages for smooth swipe. And when you click the button on your 1st page, the last loaded page's (in your case 2nd page's) button click event gets called.
You must use the arrow button in each of your fragments
You can do something like this:
public class FirstPager extends Fragment {
private ImageView slideArrow;
View v;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
v = inflater.inflate(R.layout.first_pager, container, false);
return v;
}
public static FirstPager newInstance() {
FirstPager fragment = new FirstPager ();
return fragment;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initUI();
}
private void initUI() {
slideArrow = (ImageView) v.findViewById(R.id.next_arrow); // Note the difference in this line.
slideArrow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((ViewPagerActivity)getActivity()).setCurrentItem (1);
}
});
}
}
You can do two things here:
Firstly,Your viewpager has a override method onPageSelected() which return the select page positon. using this poistion element get the view and bind your button there and write listener there itself and write viewpager.setCurrentItem(i++); //if i is ur current position,but be sure to check if it is the last item.
secondly,you hold the position of the current fragment and
((ViewPagerActivity)getActivity()).setCurrentItem (next_frag_pos);
This code try working perfect.
public class ViewPagerActivity extends FragmentActivity {
private ViewPager pager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewpager_act);
setViewPager();
/*pager.setPageTransformer(true, new ZoomPageTransformer());
pager.setAdapter(new MyViewPagerAdapter(getSupportFragmentManager()));
pager.post(new Runnable() {
#Override
public void run() {
pager.setCurrentItem(position); //don't know how to use this from fragment
}
});*/
}
private void setViewPager() {
pager = (ViewPager) findViewById(R.id.viewPager);
FragmentManager fm = getSupportFragmentManager();
ViewPagerAdapter adapter = new ViewPagerAdapter(fm);
pager.setAdapter(adapter);
}
public void setCurrentItem(int selectedPosition) {
pager.setCurrentItem(selectedPosition, true);
}
private class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new FirstPager();
case 1:
return new SecondPager();
case 2:
return new ThirdPager();
case 3:
return new FourthPager();
case 4:
return new FifthPager();
case 5:
return new SixthPager();
default:
return null;
}
}
#Override
public int getCount() {
return 6;
}
}
}

Refresh fragment view when button is clicked

I have a fragment activity that uses a ViewPager to display a set of fragments. On the fragment activity I have a button that when clicked, it sends a message to the current fragment to refresh its contents. Everything works ok (activity / current fragment communication) except the fact that I cannot refresh the fragment's view. Accessing the current view by getView() does not work as this function returns null; it seems that after the fragment is created (on ViewCreated is called) getView gets destroyed. Am I missing something here? How to I cause a fragment to redraw its contents programmatically? It seems that the only way this works is when the fragment is created from the parent activity. Do I have to remove and re-add the fragment again to do this?
Here is the code:
The main activity:
public class MainActivity extends FragmentActivity {
private MyAdapter mAdapter;
private static ViewPager mPager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupViewPager();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_test:
updateFragment();
return true;
default: return true;
}
}
private void updateFragment() {
for (int i=0; i< mAdapter.getCount(); i++) {
SampleFragment fragment = (SampleFragment) mAdapter.getItem(i);
fragment.update();
}
}
private void setupViewPager() {
try {
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(this.mAdapter);
} catch (Exception e) {
e.printStackTrace();
}
}
public class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
SampleFragment fragment = new SampleFragment(position);
return fragment;
}
#Override
public int getCount() {
return 5;
}
}
}
and the fragment class:
public class SampleFragment extends Fragment{
private int myPosition = -1;
public SampleFragment(int position) {
this.myPosition = position;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, container, false);
update(view, "Updated from onCreateView");
return view;
}
#Override
public void onActivityCreated(Bundle bundle) {
super.onActivityCreated(bundle);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.textTitle).setOnClickListener(myClickListener);
}
private OnClickListener myClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.textTitle:
break;
}
}
};
public void update() {
update(getView(), "Updated from main");
}
private void update(View view, String subtitleText) {
TextView title = (TextView) view.findViewById(R.id.textTitle);
TextView subtitle = (TextView) view.findViewById(R.id.textSubtitle);
title.setText("Fragment " + myPosition);
subtitle.setText(subtitleText);
}
}
The error happens on view.FindViewById (view is null) when called from the menu item in the main activity.
You can take a look at this article which explains how to keep references to the fragments in your ViewPager.
There are two methods described on the page. The first one involves setting a tag when you add the fragment using the FragmentManager. Then you can retrieve the fragment using findFragmentByTag(). However, I did not see how to make this work using FragmentPagerAdapter or FragmentStatePagerAdapter, since these implementations add the fragments for you. If you are using your own custom PagerAdapter, this may work for you.
The other method, which does work for FragmentPagerAdapter or FragmentStatePagerAdapter, involves keeping a map of all your fragments, updating inside your getItem() and destroyItem() implementations. This method has worked for me.
Once you have a reference to the current fragment, you can just call a method in your fragment to refresh its view.

Categories

Resources