Viewpager with Tablayout not working proper - android

Here i am getting result like...
Activity start..
at at that time these two fragments calls
-> Fragment 1 load
-> Fragment 2 load in background
swapping right (means going from frag 1 to fragment 2)
at that time I am in fragment two and same time
-> Fragment 3 load in background
swapping in right (means going from Frag 2 to 3 then)
--> there is nothing issue.
HERE IS MY CODE
Main Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new OneFragment(), "ONE");
adapter.addFragment(new TwoFragment(), "TWO");
adapter.addFragment(new ThreeFragment(), "THREE");
viewPager.setAdapter(adapter);
}
This is my adapter class
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();
}
// add fragment
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
// for title
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
And there is 3 fragment right now there is nothing into that fragment .....

ViewPager setOffscreenPageLimit default is 1
Please view this link
Visit Documentation
Update
Please Override this method of fragment
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
// load data here
}else{
// fragment is no longer visible
}
}

Use this tutorial..this may helps you
http://www.androidhive.info/2015/09/android-material-design-working-with-tabs/
you need not include this lines in your onCreate Method (Remove this lines)
viewPager.setCurrentItem(0);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
By default,Viewpager will set '0' for starting index..

Replace your code with this. This runs well on my app :
#Override
protected void onCreate(Bundle savedInstanceState) {
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
assert tabLayout != null;
tabLayout.setupWithViewPager(viewPager);
tabLayout.setSelected(true);
}
And no need to add viewPager.setCurrentItem(0);
Because by default ViewPager will be set to the Starting index of 0. As already told by Ajay Jayendran.
Hope this will works. (:

Related

ViewPager Fragement OncreateView called multiple times based on number of tabs switched

I am having trouble with below code, i have 5 tabs in my application and when i am trying to switch through them i just noticed that onCreateView is called multiple times. Now first i did saw multiple post about similar issue where multiple times onCreateView is called, but mine is lit bit different, in my application onCreateView is called based on number of tabs i am switching. For example if i am DOWNLOAD tab and i switch to FAVORITE, onCreateView will be called 3 times. If i do same action from settings it will be called 4 times. Same thing happens with CANDIDATE and other tab.
Similar Posts -
1 - OnCreateView called multiple times / Working with ActionBar and Fragments
2 - Android fragment OnCreateView called twice
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
private Boolean exit = false;
private static final int REQUEST = 112;
private Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
TextView mTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);
setSupportActionBar(toolbar);
mTitle.setText(toolbar.getTitle());
getSupportActionBar().setDisplayShowTitleEnabled(false);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
mContext = MainActivity.this;
setupTabIcons();
}
#Override
protected void onResume()
{
super.onResume();
}
private void setupTabIcons() {
tabLayout.getTabAt(0).setIcon(getResources().getDrawable(R.drawable.settings));
tabLayout.getTabAt(1).setIcon(getResources().getDrawable(R.drawable.download));
tabLayout.getTabAt(2).setIcon(getResources().getDrawable(R.drawable.register));
tabLayout.getTabAt(3).setIcon(getResources().getDrawable(R.drawable.profile));
tabLayout.getTabAt(4).setIcon(getResources().getDrawable(R.drawable.favwhite));
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new SettingsFragment(), getResources().getString(R.string.settings_tab));
adapter.addFragment(new DownloadFragment(), getResources().getString(R.string.download_tab));
adapter.addFragment(new RegisterFragment(), getResources().getString(R.string.register_tab));
adapter.addFragment(new ProfileFragment(), getResources().getString(R.string.profile_tab));
adapter.addFragment(new ProfileFragment(), getResources().getString(R.string.favorites_tab));
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(0);
}
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);
}
}
}
Update -
To add more when it is run 4 times the data on screen is 4 times which is duplicate.
Fragement Code -
public class RegisterFragment extends Fragment{
public RegisterFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_register, container, false);
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
getFragmentManager().beginTransaction().detach(this).attach(this).commit();
}
}
}
By default view pager load the fragment in the following order.
Currently selected position fragment. Visible
Cache for the (selected position - 1) fragment, if any. Not visible
Cache for the (selected position + 1) fragment, if any. Not visible
Reason for this is, to make smooth animation from one fragment to another without lagging, view pager caches the previous and the next fragment. To confirm this log the position in the getItem() method in the view pager adapter.
As a result of above. When launching activity your viewpager is loading position 0 and 1. ie loading 2 fragment. There is no fragment in -1 position.

Error when trying to set a TAG to a Fragment in Android

I have an activity named: ShoppingListActivity in which i have added 3 fragments. For this example i will use only one fragment. In onCreate method i have declared a ViewPager that looks like this:
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
and a setupViewPager(viewPager); method that looks like this:
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
Fragment shoppingListFragment = new ShoppingListFragment();
getSupportFragmentManager().beginTransaction().add(shoppingListFragment, "ShoppingListFragmentTag").commit();
adapter.addFragment(shoppingListFragment, "SHOPPING LIST");
viewPager.setAdapter(adapter);
}
My ViewPagerAdapter class lookslike this:
private class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragmentList = new ArrayList<>();
private final List<String> fragmentTitleList = new ArrayList<>();
ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public int getCount() {
return fragmentList.size();
}
void addFragment(Fragment fragment, String title) {
fragmentList.add(fragment);
fragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return fragmentTitleList.get(position);
}
}
My problem is when i go from ShoppingListActivity to another activity and than come back, my fragments are not refreshed. This is my code from onResume method in which i try to find the fragment to detach and attach the fragment like this:
FragmentManager fragmentManager = getSupportFragmentManager();
ShoppingListFragment shoppingListFragment = (ShoppingListFragment) fragmentManager.findFragmentByTag("ShoppingListFragmentTag");
fragmentManager.beginTransaction().detach(shoppingListFragment).attach(shoppingListFragment).commit();
The problem is that i get this error: java.lang.IllegalStateException: Can't change tag of fragment ShoppingListFragment{528673f4 #0 ShoppingListFragmentTag}: was ShoppingListFragmentTag now android:switcher:2131558559:0
How can i set the Tag correctly to the fragment?
Thanks in advance!
from the code what I understand is, There is a ViewPager implemented in ShoppingListActivity along with tabs.
In viewpager each fragment contains the list of something which come from server right? Now you want to refresh whole viewpager when user back from the ShoppingListInfoActivity right?
Do below changes in you ShoppinglistActivity.
1) Declare ViewPagerAdapter adapter; at class level global.
2)change private class ViewPagerAdapter extends FragmentPagerAdapter
replace FragmentPagerAdapter to FragmentStatePagerAdapter
3) change in onresume()
#Override
protected void onResume() {
super.onResume();
if(adapter!=null){
adapter.notifyDataSetChanged();
}
}

FragmentPagerAdapter always load the next fragment instead the current

#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_dictionary);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
setupNavMenu();
}
private void setupViewPager(ViewPager viewPager) {
adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new A(), "A");
adapter.addFragment(new B(), "B");
adapter.addFragment(new C(), "C");
adapter.addFragment(new D(), "D");
viewPager.setAdapter(adapter);
}
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);
}
}
The problem is:
When I starts the activity, i get the first fragment's view(A), BUT the next fragment(B) loads without the view, so when I slide to the next view(B), i get the view that i'v been loaded at the previous fragment, so now It's load fragment C...
the problem is that fragment B's content depends on the input in fragment A (data saved is sharedpreferences) so I allways get the default value at fragment B because it was loaded in fragment A.
The bug works the same way when I'm in the fragment D, so when I'll slide left to fragment C, it will show fragment C AND loads fragment B also.
its not a bug its the default functionality of a viewpager. for each nth page (n-1)th and (n+1)th page loads automatically with the nth page. I don't think there is any straight forward way to achieve what you want.
The best way would be to use a custom onSwipeListener instead of ViewPager and load the fragment yourself..
But for ViewPager you can use a hack:
After saving data in fragment A,
viewPager.setAdapter(adapter);
which will reload all fragments.
Don't forget to first save the current pager position.
after reset, set pager position so you don't go back to the first position every time.
not good coding but it should work.
on your ViewPagerAdapter. override method : getItemPosition : return POSITION_NONE

Call fragment function over activity

I have a TabLayout with 3 tab.They are a fragment.
Test.java->PagerAdapter.java->TabFragment1+TabFragment2+TabFragment3
I want to call TabFragment1.helloworld() function. How can i call this function? Thanks.
Test.java created 3 tabs in below
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("tab1"));
tabLayout.addTab(tabLayout.newTab().setText("tab2"));
tabLayout.addTab(tabLayout.newTab().setText("tab3"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setOffscreenPageLimit(3);
final PagerAdapter adapter = new PagerAdapter
(getSupportFragmentManager(),
tabLayout.getTabCount());
viewPager.setAdapter(adapter);
PagerAdapter.java
public class PagerAdapter extends FragmentStatePagerAdapter {
int mNumOfTabs;
public PagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabFragment1 tab1 = new TabFragment1();
return tab1;
case 1:
TabFragment2 tab2 = new TabFragment2();
return tab2;
case 2:
TabFragment3 tab3 = new TabFragment3();
return tab3;
default:
return null;
}
}
#Override
public int getCount() {
return mNumOfTabs;
}
}
You can access the desired fragment's method through your PagerAdapter:
((TabFragment1)adapter.getItem(0)).helloworld();
It's a bit trickier than usual with ViewPagers, because you can't use the preferred findFragmentByTag() method. Here's something you could try - it's untested, but should be ok:
Create an interface, which all Fragments in your ViewPager implement:
public interface ViewPagerFragmentBase {
void callCommonMethod(int code);
}
Implement it in all your ViewPager Fragments:
public FragmentOne implements ViewPagerFragmentBase {
#Override
public void callCommonMethod(int code) {
if (code == 1) {
//Run code in this Fragment
}
}
public FragmentTwo implements ViewPagerFragmentBase {
#Override
public void callCommonMethod(int code) {
if (code == 2) {
//Run code in this Fragment
}
}
Inside your Activity class, grab all Fragments currently in your Adapter, then cycle through each one, calling the callCommonMethod() along with a code which indicates the Fragment you are trying to reach:
public class MainActivity extends AppCompatActivity {
private void callCommonMethodInFragments(int code) {
for (int i = 0; i < viewPagerAdapter.getCount(); i++) {
((ViewPagerFragmentBase)viewPagerAdapter.getItem(i)).callCommonMethod(code);
}
}
//To call it...
callCommonMethodInFragments(1); //This will run the method in FragmentOne only
}
If the code matches the one in the Fragment you are trying to reach, then the method will run.
Something else you could also try though is an EventBus - this would allow you to achieve your goal more directly, and with less typing: https://github.com/greenrobot/EventBus
To call fragment method from parent activity:
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
fragment.callFunction();
I had the same issue, and this worked for me:
You have to add the fragments via your adapter and then you can access the fragment functions:
myViewPager = (ViewPager) findViewById(R.id.viewpager);
MyAdapterClass adapter = new MyAdapterClass(getSupportFragmentManager());
adapter.addFragment(new TabOneFragment(), "");
adapter.addFragment(new TabTwoFragment(), "");
adapter.addFragment(new TabThreeFragment(), "");
myViewPager.setAdapter(adapter);
myTabLayout = (TabLayout) findViewById(R.id.tab_layout);
myTabLayout.setupWithViewPager(myViewPager);
// to access fragment functions:
TabOneFragment tabOneFragment = (TabOneFragment) adapter.getItem(0);
tabOneFragment.functionWhatSoEver();

swiping issues in a tablayout which is inside a tab view of parent tablayout

I have added a Android support library TabLayout(Parent) with 4 tabs. I have added another TabLayout(Child) inside one of the tab views of parent tablayout. Swipe inside tabs of child tablayout is not happening correctly (Mostly due to conflict in swipe b/w parent and child tab layouts). How can I disable swipe inside child tablayout?
I have used separate viewpager for both the tablayouts.
This Simple code can help you. Use this sample code in your parent fragment to add child tabs:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_index_markets, container, false);
viewPager = (ViewPager) view.findViewById(R.id.markets_viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) view.findViewById(R.id.markets_tabs);
tabLayout.setupWithViewPager(viewPager);
return view;
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager()/*getActivity().getSupportFragmentManager()*/);
adapter.addFrag(new yourInnerFragment(), "tab1");
adapter.addFrag(new yourSecondInnerFragment, "tab2");
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(1);
}
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);
}
}
Note that sometimes it is better to use getActivity().getSupportFragmentManager() instead of getChildFragmentManager().
Also check this link: https://code.google.com/p/android/issues/detail?id=180462

Categories

Resources