i used view pager inside tab view i had 3 tabs in my activity. each tab having a fragment. i called asyncTask in OnCreateView of all tabs. everything is working fine. but the problem is comes when i come on first tab asynctask from all others 2nd tab or 3rd tab also gets called in first tab.here is my code snippet.
TabActivity :
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
FirstTab:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view=inflater.inflate(R.layout.fragment_current, container, false);
RequestNetworkcall();
return view;}
i am stuck on this problem from last 2 days lease help me guys.
Viewpager always initializes it's three pages, like it's visible.
So that means all your pages have already called their onResume() method.
You need to call your asynctask when that page is selected.
UPDATE:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if (position == 3) {
//Call your asynctask here
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Related
Need a help with dynamic ViewPager with EditText (straggling to do a multiple tabbed editor).
Here are problems I faced:
e. g. I create 3 pages and put some text, so I have
page0 - "a"
page1 - "b"
page2 - "c"
Adding works normally here, removing page0 leads not to "a" "c" but to "a" "b" left, removing page0 leads to "a" "b" instead of "b" "c" as well, removing page2 is ok. So it seems like pager remembers text of removed page n and moves it to page n+1, text from page n+1 to n+2 and so on
same pages with the same text, but now I remove page1 and page2 (the order doesn't matter) so text "a" left. Adding two new pages will recreate "b" and "c", next pages would be blank as they should be.
if I remove just page1 and add new page, text "c" will appear.
I've been here, here and here, no help.
Tried to follow getItem(int position) calls
Also searched ViewPager and FragmentStatePagerAdapter sources, it looks like it has smth to do with instantiateItem and/or destroyItem but I have no clue what exactly.
Here is my code:
Adapter
public class PagerAdapter extends FragmentStatePagerAdapter {
private ArrayList<Fragment> fragmentsList = new ArrayList<>();
private ArrayList<String> titlesList = new ArrayList<>();
private TabLayout layout;
public PagerAdapter(FragmentManager manager, Context context, ViewPager pager, TabLayout layout) {
super(manager);
this.layout = layout;
}
#Override
public Fragment getItem(int position) {
return fragmentsList.get(position);
}
#Override
public int getItemPosition(#NonNull Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return fragmentsList.size();
}
#Override
public CharSequence getPageTitle(int position) {
return titlesList.get(position);
}
public void addFrag(Fragment f, String s) {
fragmentsList.add(f);
titlesList.add(s);
}
public void removeFragment(int position) {
if (layout.getChildCount() > 0)
layout.removeTabAt(position);
Fragment fragment = fragmentsList.get(position);
fragmentsList.remove(fragment);
titlesList.remove(position);
FragmentManager manager = fragment.getFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove(fragment);
trans.commit();
notifyDataSetChanged();
}
}
RootFragment
public class RootFragment extends Fragment {
private TabLayout layout;
private ViewPager pager;
private PagerAdapter adapter;
private int currentTab;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.root_fragment, container, false);
pager = view.findViewById(R.id.viewpager);
layout = view.findViewById(R.id.sliding_tabs);
adapter = new PagerAdapter(getFragmentManager(), getActivity(), pager, layout);
pager.setAdapter(adapter);
layout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
currentTab = tab.getPosition();
pager.setCurrentItem(currentTab);
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
return view;
}
public void addTab(String title) {
Bundle bundle = new Bundle();
bundle.putString("data", title);
LeafFragment leafFragment = new LeafFragment();
leafFragment.setArguments(bundle);
adapter.addFrag(leafFragment, title);
adapter.notifyDataSetChanged();
layout.setupWithViewPager(pager);
currentTab = adapter.getCount() - 1;
pager.setCurrentItem(currentTab);
}
public void deleteTab(int position) {
adapter.removeFragment(position);
}
}
Thanks and sorry for my English.
FragmentStatePagerAdapter already stores a list of Fragments, you don't need (and potentially, you should not) implement your own list while using it. Simply:
public class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 3;
}
#Override
public Fragment getItem(int position) {
//Simply create a fragment based on position here
}
}
Second, the unfortunate truth is, removing/reordering fragments in a FragmentStatePagerAdapter appears to have still open bugs as here:
https://issuetracker.google.com/issues/36956111
My suggestion is to simply re-create the adapter if you need to delete fragments from the adapter.
I have to refresh the fragment when I swipe to another fragment from the Tab.
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
mBinding = DataBindingUtil.inflate(inflater, R.layout.manage_work_shop_act, container, false);
mBinding.layout.title.setText(getString(R.string.d_manage_my_staff));
mBinding.tabs.setupWithViewPager(mBinding.viewpager);
setupViewPager(mBinding.viewpager);
mBinding.layout.nav.setVisibility(View.GONE);
mBinding.layout.navMenu.setVisibility(View.VISIBLE);
mBinding.layout.navMenu.setOnClickListener(view -> openDrawer());
return mBinding.getRoot();
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
int limit = (adapter.getCount() > 1 ? adapter.getCount() - 1 : 1);
adapter.addFragment(new MechanicListFragment(), getString(R.string.d_manage_my_staff));
adapter.addFragment(new MechanicNewFragment(), getString(R.string.new_frag));
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(limit);
adapter.notifyDataSetChanged();
}
My Adapter is like this
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
I tried all the ways to refresh my fragment.
If I swipe the tab or click the another tab then I need to refresh the visible tab again.
In my current fragment did not refresh.
please help me to override from this issue.
Try using Fragment state pager adapter than fragment adapter when you have to refresh tabs in your adapdter.
FragmentPagerAdapter stores the previous data which is fetched from the adapter while FragmentStatePagerAdapter takes the new value from the adapter everytime it is executed.
There's onHiddenChanged method in the fragment.
Called when the hidden state (as returned by isHidden() of the
fragment has changed. Fragments start out not hidden; this will be
called whenever the fragment changes state from that.
override the onHiddenChanged method in each of your tab fragment and if is not hidden do the refreshing. For example:
class YourFragment extends Fragment {
#Override public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
//you can refresh here now
}
}
}
For example, I have
MainActivity (contain a ViewPager)
Fragment0
Fragment1 (contain a ViewPager)
Fragment1a
Fragment1b
Fragment2
I want to refresh Fragment1a every time it visible so I use setUserVisibleHint inside Fragment1a but not working well.
When I switch between fragment Fragment1a and Fragment1b, setUserVisibleHint of Fragment1a called
However when I go from fragment Fragment0 to Fragment1 or Fragment2 to Fragment1 setUserVisibleHint of Fragment1a (and Fragment1b) not called
How can I detect Fragment1a (and Fragment1b) visible? Any help or suggestion would be great appreciated.
setUserVisibleHint also not working me I used another way to update data in fragment when view pager change fragment, Below is The way,
viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
try {
if(viewPagerAdapter.getItem(position) instanceof Fragment1a){
Fragment1a frag1 = (Fragment1a) viewPagerAdapter.getItem(position);
frag1.updateData(data); // here is the public method of fragment which declared for udpate data in fragment
}else if(viewPagerAdapter.getItem(position) instanceof Fragment1b){
Fragment1b frag2 = (Fragment1b) viewPagerAdapter.getItem(position);
frag2.updateData(data); // here is the public method of fragment which declared for udpate data in fragment
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
viewpager.setCurrentItem(0);
This way you can update data directly Just you need to create one public method in your fragment.
Here is the Adapter
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<TabModel> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, TabModel title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position).getTabName();
}
}
I came across a strange issue in my project.
I have implemented infinite viewpager adapter using FragmentStatePagerAdapter
Code for same is:
public class DashBoardAdapter extends FragmentStatePagerAdapter {
ArrayList<AbstractFragment> fragments;
private int MAXFRAGMENTS=0;
public DashBoardAdapter(FragmentManager fm, ArrayList<AbstractFragment> fragments) {
super(fm);
this.fragments = fragments;
MAXFRAGMENTS=fragments.size();
}
#Override
public AbstractFragment getItem(int position) {
return fragments.get(position%MAXFRAGMENTS);
}
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
#Override
public CharSequence getPageTitle(int position) {
return fragments.get(position%MAXFRAGMENTS).getTitle();
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
int virtualPosition = position % MAXFRAGMENTS;
return super.instantiateItem(container, virtualPosition);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
int virtualPosition = position % MAXFRAGMENTS;
super.destroyItem(container, virtualPosition, object);
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
MAXFRAGMENTS = fragments.size();
}
}
And the Main Activitycode(Function only) is something like this:
public void initializeViewPager()
{
verticalViewPager = (VerticalViewPager) findViewById(R.id.verticalviewpager);
enabledPages=new ArrayList<>();
enabledPages.addAll(getEnabledPages(false));
adapter=new DashBoardAdapter(getSupportFragmentManager(),enabledPages);
verticalViewPager.setAdapter(adapter);
verticalViewPager.setPageTransformer(true, new PageTransformer());
verticalViewPager.setCurrentItem(999+position);
verticalViewPager.setOffscreenPageLimit(1);
verticalViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(adapter!=null)
title.setText(adapter.getPageTitle(position));
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
private ArrayList<AbstractFragment> getEnabledPages(boolean a)
{
ArrayList<AbstractFragment> fragments=new ArrayList<>();
fragments.add(FragmentAttendance.newInstance(fragments.size()));
fragments.add(FragmentCompensation.newInstance(fragments.size()));
if(a)
fragments.add(FragmentTimeOff.newInstance(fragments.size()));
if(a)
fragments.add(FragmentCalendar.newInstance(fragments.size()));
if(a)
fragments.add(FragmentPeople.newInstance(fragments.size()));
if(a)
fragments.add(FragmentProvisions.newInstance(fragments.size()));
position = fragments.size()-(999+position)%fragments.size();
return fragments;
}
Layout of activity contains just a Viewpager.
And the Fragments, I have used is just copy of below fragment with different names
public class FragmentAttendance extends AbstractFragment {
public static final String ARG_SECTION_NUMBER = "section_number";
String title ="Testing";
public static FragmentAttendance newInstance(int sectionNumber) {
FragmentAttendance fragment = new FragmentAttendance();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public FragmentAttendance() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.card_attendance, container, false);
return rootView;
}
#Override
public String getTitle() {
return title;
}
}
Layout of fragment has just LinearLayout with a TextView.
The code is running superb if I am adding fragments more than three fragments. Howsoever as soon as the number of added fragments gets below four. My code Works in strange behavior.
Some of errors are Fragment already initialised
Other are Forward scrolling shows fragement View Howsoever when I scroll backward No view appears.
The working code can be tested by passing true to getEnabledPages(true);
And the non working code can be tested by passing false to getEnabledPages(false);
Please someone help me in this strange behaviour.
I want to get the hidden value which is set in Fragment Page in order to work on it. I am setting the hidden value in Fragment Page and want to get that hidden value in the activity page's Viewpager onPageSelected value in oreder to update the fragment with detail information. Is this possible?
My Fragment page
public class CountryFragment extends Fragment {
public static final String STARTUP_ID = "startupID";
private String st_id;
public CountryFragment() {
// emtpy
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String st_id = getArguments().getString(STARTUP_ID);
this.st_id = st_id;
View v = inflater.inflate(R.layout.country_fragment, container, false);
TextView hiddenstatupid= (TextView) v.findViewById(R.id.hiddenstatuptextview);
hiddenstatupid.setText(st_id);
return v;
}
}
Activity Page
public class IndividualPage extends ActionBarActivity{
ViewPager pager;
#Override
public void onCreate (Bundle savedInstanceState)
{
pager = (ViewPager)findViewById(R.id.viewpager);
pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
//here is where i need to get the hidden id of startup which is in the countryfragment
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
My CountryPageAdapter
public class CountryPageAdapter extends FragmentPagerAdapter {
public CountryPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
mFragmentTags = new HashMap<Integer, String>();
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
}
Iy your CountryFragment part of the viewpager? If so, then you can have a local store of your fragments in your pager adapter and then get the fragment from the viewpager adapter using the position.
If your adapter extends FragmentStatePagerAdapter you have to implement the getItem() method.
You will have something like this:
#Override
public void onPageSelected(int position) {
CountryFragment frag = pager.getAdapter().getItem(position);
}
Hope this helps.