MainActivity containing Navigation drawer. Clicking on navigation drawer item,opening a fragment with viewpager. Clicking on tabs fragment item, another fragment is coming but when pressing back button the viewpager fragment coming blank. How to maintain backstack?
ViewPagerAdapter
public class ViewPagerAdapterProfile extends FragmentStatePagerAdapter{
int mNumOfTabs;
public ViewPagerAdapterProfile(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
#Override
public Fragment getItem(int position) {
if (position ==0) {
return new PersonalDetailsFragment();
} else if (position == 1)
{
return new ProfessionalDetailsFragment();
} else return new EmploymentDetailsFragment();
}
#Override
public int getCount() {
return mNumOfTabs;
}
#Override
public int getItemPosition(#NonNull Object object)
{
return PagerAdapter.POSITION_NONE;
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void setListViewHeight(ExpandableListView listView, int group) {
if ((listAdapter.getChildrenCount(i) == 0) && (i == group)) {
Fragment fragment = null;
switch (group) {
case 0:
fragment = new DashboardFragment();
tv_name.clearComposingText();
tv_name.setText("Dashboard");
break;
case 1:
fragment = new MyProfileFrament();
tv_name.clearComposingText();
tv_name.setText("My Profile");
break;
default:
break;
}
//replacing the fragment
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
mDrawerLayout.closeDrawer(Gravity.LEFT);
}
}
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
int height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getGroupCount() - 1));
params.height = height;
listView.setLayoutParams(params);
listView.requestLayout();
}
#Override
public void onBackPressed() {
FragmentManager fm = getSupportFragmentManager();
for (Fragment frag : fm.getFragments()) {
if (frag.isVisible()) {
FragmentManager childFm = frag.getChildFragmentManager();
if (childFm.getBackStackEntryCount() > 0) {
childFm.popBackStack();
return;
}
}
}
super.onBackPressed();
}
}
MyProfileFrament
public class MyProfileFrament extends Fragment{
private ViewPager viewPager;
private TabLayout tabLayout;
private String[] pageTitle = {"Personal Details", "Education/Professional Details", "Employement Details"};
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_myprofile, container, false);
viewPager = (ViewPager) view.findViewById(R.id.view_pager);
tabLayout = (TabLayout) view.findViewById(R.id.tab_layout);
for (int i = 0; i < 3; i++) {
tabLayout.addTab(tabLayout.newTab().setText(pageTitle[i]));
}
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
ViewPagerAdapterProfile pagerAdapter = new ViewPagerAdapterProfile(requireFragmentManager(), pageTitle.length);
viewPager.setAdapter(pagerAdapter);
//change Tab selection when swipe ViewPager
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
//change Tab selection when swipe ViewPager
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
//change ViewPager page when tab selected
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
return view;
}
}
you can maintain the backstack of fragment using :
Fragment fragment=new YourFragmentClass();
FragmentManager fragmentManager = getFragmentManager();
android.app.FragmentTransaction ft=fragmentManager.beginTransaction();
ft.add(R.id.content_frame, fragment);
ft.hide(SourceFragment.this);
ft.addToBackStack(SourceFragment.class.getName());
ft.commit();
Related
I have a main activity which has a tab layout in which there are two framgents.Following is the code for same.
public void setViewPager(){
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
viewPager = (ViewPager) findViewById(R.id.pager);
final PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
chipGroup.removeAllViews();
utils.createChip(getLayoutInflater(),R.layout.chipview,chipGroup,arrayListFilter);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
Log.d("hgfdgf","+"+tab.getPosition());
if(tab.getPosition()==0){
fragment=new StudyNotes_fragment();
chipGroup.removeAllViews();
utils.createChip(getLayoutInflater(),R.layout.chipview,chipGroup,arrayListFilter);
//filter_iv_booklet.setVisibility(GONE);
}
else if (tab.getPosition()==1){
fragment2=new Specialbooklet_fragment();
chipGroup.removeAllViews();
utils.createChip(getLayoutInflater(),R.layout.chipview,chipGroup,arrayListFilter2);
//filter_iv_booklet.setVisibility(VISIBLE);
}
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onClick(View v) {
}
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:
for (int i=0;i<=studyM.size()-1;i++){
arrayListFilter.add(studyM.get(i).get(i).getCSubjectName());
}
LayoutInflater li = LayoutInflater.from(context);
HashSet<String> hashSet = new HashSet<String>();
hashSet.addAll(arrayListFilter);
arrayListFilter.clear();
arrayListFilter.addAll(hashSet);
Bundle args = new Bundle();
args.putStringArrayList("array2",arrayListFilter);
args.putSerializable("array4",studyM);
args.putSerializable("tag",makeFragmentName(viewPager.getId(), 1));
fragment.setArguments(args);
return fragment;
case 1:
for (int i=0;i<=specialB.size()-1;i++){
arrayListFilter2.add(specialB.get(i).get(i).getCSubjectName());
}
LayoutInflater li1 = LayoutInflater.from(context);
HashSet<String> hashSet1 = new HashSet<String>();
hashSet1.addAll(arrayListFilter2);
arrayListFilter2.clear();
arrayListFilter2.addAll(hashSet1);
String fragmentTag2 = makeFragmentName(viewPager.getId(), 2);
Bundle args1 = new Bundle();
args1.putSerializable("array", specialB);
args1.putStringArrayList("array2",arrayListFilter2);
args1.putStringArrayList("array3",videosubtitlelist);
args1.putString("tag",fragmentTag2);
fragment2.setArguments(args1);
return fragment2;
//return Specialbooklet_fragment.newInstance(specialB,arrayListFilter2,videosubtitlelist,fragmentTag2);
default:
return null;
}
}
#Override
public int getCount() {
return mNumOfTabs;
}
}
I am using a button which is in toolbar of activity in fragment.I am accessing it in fragment by using getactivity. Below is my code.
rl_filter = activity.findViewById(R.id.rl_filter);
filter_iv = activity.findViewById(R.id.filter_iv);
chipGroup = activity.findViewById(R.id.chipgroup);
applyfilter_tv = activity.findViewById(R.id.applyfilter_tv);
clearfilter_tv = activity.findViewById(R.id.clearfilter_tv);
filter_iv.setOnClickListener(this::onClick);
rl_filter.setOnClickListener(this::onClick);
clearfilter_tv.setOnClickListener(this::onClick);
applyfilter_tv.setOnClickListener(this::onClick);
I am doing same thing in second fragment.My problem is that clicks of only second framgent is working when i am defining the views in both fragments. If i am removing listener and initialisation of buttons from second fragment then first fragment clicks are working. Is there any way i can use the view of activity in both the fragments.
Once my application is Login I start ActivityTwo. In ActivityTwo I am immediately calling TabView Fragment which hold my three Tabs.This is code in ActivityTwo to call TabView Fragment
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
fm = getSupportFragmentManager();
final Bundle bundle = new Bundle();
bundle.putInt("TARGET_FRAGMENT_ID", fragId);
ChooseTab chooseTab = new ChooseTab();
chooseTab.setArguments(bundle);
ft = fm.beginTransaction();
ft.replace(R.id.frame, chooseTab, add);
ft.commit();
});
This is code for ChooseTab Fragment which is responsible for setting TabView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.choose_tab, container, false);
//-----------------------------------------------------------------------------------
int position=getArguments().getInt("TARGET_FRAGMENT_ID");
tabLayout = (TabLayout) v.findViewById(R.id.simpleTabLayout);
tabLayout.addTab(tabLayout.newTab().setText("Tab1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab2"));
tabLayout.addTab(tabLayout.newTab().setText("Tab3"));
viewPager = (ViewPager) v.findViewById(R.id.simpleViewPager);
viewPager.setOffscreenPageLimit(3);
final PagerAdapter adapter = new PagerAdapter(getActivity().getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
viewPager.setCurrentItem(position);
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
adapter.notifyDataSetChanged();
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
adapter.notifyDataSetChanged();
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
adapter.notifyDataSetChanged();
}
});
return v;
}
This is code for PagerAdapter
public class PagerAdapter extends FragmentStatePagerAdapter {
private int mNumOfTabs;
public PagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new Tab1();
case 1:
return new Tab2();
case 2:
return new Tab3();
default:
return null;
}
}
#Override
public int getCount() {
return mNumOfTabs;
}
}
This is code for Tab1 onCreateView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.current_status, container, false);
fm = getFragmentManager();
LoadData();
});
return v;
}
But when I run the app and I print some Log when LoadData() is called it is seen loadData is called. How to resolve this ?
I have a MainActivity and a HomeTabs with three tabs(A B C) all of them are Fragment. I set a onRefresh on tab C. When I trigger onRefresh that its view is gone. Why is that? I couldn't solve it.
Any help would be appreciated. Thanks in advance.
Here's my HomeTabs:
public class HomeTabs extends Fragment {
private Context context;
private TabLayout tabLayout;
private int[] imageResId = {R.drawable.input_icon_color,
R.drawable.note_icon_color,
R.drawable.analytics_icon_color};
public HomeTabs() {
// Required empty public constructor
}
public static HomeTabs newInstance() {
return new HomeTabs();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home_tabs, container, false);
tabLayout = (TabLayout) view.findViewById(R.id.tabLayout);
tabLayout.addTab(tabLayout.newTab().setText(getResources().getString(R.string.tab1)));
tabLayout.addTab(tabLayout.newTab().setText(getResources().getString(R.string.tab2)));
tabLayout.addTab(tabLayout.newTab().setText(getResources().getString(R.string.tab3)));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = (ViewPager) view.findViewById(R.id.viewPagerDataReport);
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(viewPagerAdapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.getTabAt(0).setIcon(R.drawable.input_icon);
tabLayout.getTabAt(1).setIcon(imageResId[1]);
tabLayout.getTabAt(2).setIcon(imageResId[2]);
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());/
int id = tab.getPosition();
if (id == 0) {
tabLayout.getTabAt(0).setIcon(R.drawable.input_icon);
tabLayout.getTabAt(1).setIcon(imageResId[1]);
tabLayout.getTabAt(2).setIcon(imageResId[2]);
}
if (id == 1) {
tabLayout.getTabAt(0).setIcon(imageResId[0]);
tabLayout.getTabAt(1).setIcon(R.drawable.note_icon);
tabLayout.getTabAt(2).setIcon(imageResId[2]);
}
if (id == 2) {
tabLayout.getTabAt(0).setIcon(imageResId[0]);
tabLayout.getTabAt(1).setIcon(imageResId[1]);
tabLayout.getTabAt(2).setIcon(R.drawable.analytics_icon);
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
// My tab C position is 2 , when i refresh that i want to show tab C
if (getActivity().getIntent().hasExtra("refresh")){
tabLayout.getTabAt(2).select();
}
return view;
}
}
Here is my tab C Fragment about refresh:
#Override
public void onRefresh() {
refreshLayout.setRefreshing(false);
MainActivity mainActivity = (MainActivity) getActivity();
mainActivity.refreshFragment();
}
And the MainActivity:
public class MainActivity extends AppCompatActivity {
private FrameLayout frameLayout;
private Toolbar toolBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolBar = (Toolbar) findViewById(R.id.toolBar);
setSupportActionBar(toolBar);
getSupportActionBar().setTitle("");
toolBar.setTitle(R.string.myAppName);
toolBar.setNavigationIcon(R.drawable.medical_history32);
toolBar.setTitleTextColor(Color.WHITE);
frameLayout = (FrameLayout) findViewById(R.id.frameLayout);
if (savedInstanceState == null) {
switchFragment(HomeTabs.newInstance());
}
}
public void switchFragment(Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.frameLayout, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
public void setTitle(String title) {
getSupportActionBar().setTitle(title);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
new DialogHandler(this).quickDialog(
getResources().getString(R.string.quick),
getResources().getString(R.string.confirm),
getResources().getString(R.string.cancel),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
}, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
}
return super.onKeyDown(keyCode, event);
}
public void refreshFragment() {
//switchFragment(HomeTabs.newInstance());
Intent intent = new Intent(this,MainActivity.class);
intent.putExtra("refresh",true);
startActivity(intent);
}
}
Here's my tab C:
public class MyLineChart extends Fragment implements SwipeRefreshLayout.OnRefreshListener{
private View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_my_line_chart, container, false);
//................set my data
return view;
}
#Override
public void onRefresh() {
refreshLayout.setRefreshing(false);
}
There are many ways to do it.
If you are using ViewPager the best solution is found here.
You must implement (override) getItemPosition method in your page adapter to return (no position changed)
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
Then to update from anywhere, you just notify the adapter of a change
mPagerAdapter.notifyDataSetChanged();
Your below code for reload your fragment:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(YourFragmentName.this).attach(YourFragmentName.this).commit();
first set tag to your fragment as "fragment"
#Override
public void onRefresh()
{
Fragment currentFragment = getFragmentManager().findFragmentByTag("FRAGMENT");
FragmentTransaction fragTransaction = getFragmentManager().beginTransaction();
fragTransaction.detach(currentFragment);
fragTransaction.attach(currentFragment);
fragTransaction.commit();
}
Hi I have a TabLayout and ViewPager inside a fragment. But I can not slide beetween tab to come to child fragment (Working normally when in Activity but not work in fragment).
Here is my code for Tablayout inside fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View inflateView = inflater.inflate(R.layout.fragment_assign_beacon_to_event, container, false);
//Viewpager and TabLayout
viewPager = (ViewPager)inflateView.findViewById(R.id.viewPager);
viewPager.setAdapter(new CustomAdapter(getFragmentManager(), getContext()));
tabLayout = (TabLayout)inflateView.findViewById(R.id.tabLayout);
// Inflate the layout for this fragment
return inflateView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
});
Any here is my Custom Adapter class
private class CustomAdapter extends FragmentPagerAdapter {
private String fragments[] = {"Assign Event", "Manage Event"};
public CustomAdapter(FragmentManager supportFragmentManager, Context applicationContext) {
super(supportFragmentManager);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
// return new AssignEventToBeacon();
return new Test1();
case 1:
return new ManageEventAssigned();
default:
return null;
}
}
#Override
public int getCount() {
return fragments.length;
}
#Override
public CharSequence getPageTitle(int position) {
return fragments[position];
}
}
I doubt i have problem with this line:
viewPager.setAdapter(new CustomAdapter(getFragmentManager(), getContext()));
Anyhelp is much appreciate, thanks
I have done a similar project and here is my code for the fragment :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.outer_fragment, container, false);
setHasOptionsMenu(true);
ViewPager viewPager = (ViewPager) view.findViewById(R.id.viewpager);
if (viewPager != null) {
setupViewPager(viewPager);
}
Log.v("Layout","Tabs");
TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tabs);
tabLayout.setSelectedTabIndicatorColor(Color.parseColor("#FFFFFF"));
tabLayout.setTabTextColors(Color.parseColor("#707070"), Color.parseColor("#FFFFFF"));
assert viewPager != null;
tabLayout.setupWithViewPager(viewPager);
return view;
}
private void setupViewPager(ViewPager viewPager) {
Adapter adapter = new Adapter(getChildFragmentManager());
adapter.addFragment(new Tab1Fragment(), "PHOTOS");
adapter.addFragment(new Tab2Fragment(), "HI-FIVES");
viewPager.setAdapter(adapter);
}
static class Adapter extends FragmentPagerAdapter {
private final List<Fragment> mFragments = new ArrayList<>();
private final List<String> mFragmentTitles = new ArrayList<>();
public Adapter(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);
}
}
You need to use getChildFragmentManager() in Fragment instead of getFragmentManager().
From getChildFragmentManager() documentation
Return a private FragmentManager for placing and managing Fragments
inside of this Fragment.
From getFragmentManager() documentation
Return the FragmentManager for interacting with fragments associated
with this fragment's activity.
In simple words,
Use getChildFragmentManager() for Child Fragments
Use getFragmentManager() for Fragments inside Activity
One can see #this answer for complete code.
I have a parent SherlockFragmentActivity class that contains ViewPager with 4 Fragments inside.
One of them extends from SherlockListFragment and I want to scroll it to top by click on it's tab.
MainActivity class:
public class MainActivity extends SherlockFragmentActivity {
ViewPager viewPager;
TabAdapter tabAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
setTheme(Constants.THEME);
viewPager = new ViewPager(this);
viewPager.setId(R.id.pager);
viewPager.setBackgroundResource(R.color.background_color);
tabAdapter = new TabAdapter(this,viewPager);
super.onCreate(savedInstanceState);
setContentView(viewPager);
// Action bar setup
setupTabs(savedInstanceState);
}
private void setupTabs(Bundle savedInstanceState) {
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for (int i = 1; i <= 4; i++) {
ActionBar.Tab tab = getSupportActionBar().newTab();
switch (i) {
case 1:
tab.setText(R.string.feed).setTabListener(tabAdapter);
tabAdapter.addTab(EventListFragment.class);
break;
case 2:
tab.setText(R.string.downloads).setTabListener(tabAdapter);
tabAdapter.addTab(LocalEventListFragment.class);
break;
case 3:
tab.setText(R.string.tags).setTabListener(tabAdapter);
tabAdapter.addTab(TagsFragment.class);
break;
case 4:
tab.setText(R.string.settings).setTabListener(tabAdapter);
tabAdapter.addTab(SettingsFragment.class);
break;
}
getSupportActionBar().addTab(tab);
}
}
TabAdapter class:
public static class TabAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener, ActionBar.TabListener {
private final Context mContext;
private final ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
private final ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
private final ActionBar mActionBar;
private final ViewPager mViewPager;
public TabAdapter(SherlockFragmentActivity activity, ViewPager pager){
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(Class<?> clss){
classes.add(clss);
mFragments.add(Fragment.instantiate(mContext, clss.getName(),
null));
}
#Override
public Fragment getItem(int i) {
return mFragments.get(i);
}
public int getId(int index){
return mFragments.get(index).getId();
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
// fixed double call onTabReselected
if (mActionBar.getSelectedNavigationIndex() != position)
mActionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrollStateChanged(int i) {
}
#Override
public int getCount() {
return 4;
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
final int position = tab.getPosition();
final Fragment fragment = mFragments.get(position);
if (fragment != null) {
switch (position) {
case 0:
// call tab's ListFragment scroll to top item
((EventListFragment) fragment).scrollToTop();
break;
case 1:
// do something
break;
}
}
}
onTabReselected called, then user press current tab, so I try to do EventListFragment scrolling:
EventListFragment class:
public class EventListFragment extends SherlockListFragment {
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
mAdapter = new EventListAdapter(getSherlockActivity());
setListAdapter(mAdapter);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
}
#Override
public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View eventListLayout = inflater.inflate(R.layout.eventlist_fragment,null);
ListView lv = (ListView) eventListLayout.findViewById(android.R.id.list);
ViewGroup parent = (ViewGroup) lv.getParent();
//Remove ListView and add PullToRefreshListView in its place
int lvIndex = parent.indexOfChild(lv);
parent.removeViewAt(lvIndex);
mPullToRefreshListView = onCreatePullToRefreshListView(inflater, savedInstanceState);
parent.addView(mPullToRefreshListView, lvIndex, lv.getLayoutParams());
return eventListLayout;
}
public void scrollToTop() {
if (getSherlockActivity() != null) { // null after screen rotation
final ListView listView = getListView();
listView.post(new Runnable(){
public void run() {
listView.smoothScrollToPosition(0);
}});
}
}
It works on application start, but after screen rotation scrollToTop - getSherlockActivity() returns null.
If remove this condition check, have an exception:
java.lang.IllegalStateException: Content view not yet created
at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328)
at android.support.v4.app.ListFragment.getListView(ListFragment.java:222)
at com.project.fragment.EventListFragment.scrollToTop(EventListFragment.java:337)
at com.project.MainActivity$TabAdapter.onTabReselected(MainActivity.java:411)
at com.actionbarsherlock.internal.app.ActionBarWrapper$TabWrapper.onTabReselected(ActionBarWrapper.java:327)
I haven't totally understatinding how to ViewPager and its FragmentPagerAdapter works. So can't find a problem, that occurs.
Use this FragmentPageAdapter:
public class TestFragmentAdapter extends FragmentPagerAdapter implements IconPagerAdapter {
protected static final String[] CONTENT = new String[] { "CATEGORIAS", "PRINCIPAL", "AS MELHORES", };
protected static final int[] ICONS = new int[] {
R.drawable.perm_group_calendar,
R.drawable.perm_group_camera,
R.drawable.perm_group_device_alarms,
};
private int mCount = CONTENT.length;
public TestFragmentAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {Fragment f = null;
switch(position){
case 0:
{
f = new ArrayListFragment();//YourFragment
// set arguments here, if required
Bundle args = new Bundle();
f.setArguments(args);
break;
}
case 1:
{
f = new HomeFragment();//YourFragment
// set arguments here, if required
Bundle args = new Bundle();
f.setArguments(args);
break;
}
case 2:
{
f = new EndlessCustomView();//YourFragment
// set arguments here, if required
Bundle args = new Bundle();
f.setArguments(args);
break;
}
default:
throw new IllegalArgumentException("not this many fragments: " + position);
}
return f;
}
#Override
public int getCount() {
return mCount;
}
#Override
public CharSequence getPageTitle(int position) {
return TestFragmentAdapter.CONTENT[position % CONTENT.length];
}
#Override
public int getIconResId(int index) {
return ICONS[index % ICONS.length];
}
public void setCount(int count) {
if (count > 0 && count <= 10) {
mCount = count;
notifyDataSetChanged();
}
}
}
This Activity:
public class BaseSampleActivity extends SlidingFragmentActivity {
private static final Random RANDOM = new Random();
TestFragmentAdapter mAdapter;
ViewPager mPager;
PageIndicator mIndicator;
protected ListFragment mFrag;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.themed_titles);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mAdapter = new TestFragmentAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mPager.setCurrentItem(1);
mIndicator = (TitlePageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
}
Applied solution according to this post:
MainActivity class:
//...
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
FragmentManager manager = getSupportFragmentManager();
for (int i = 0; i < tabAdapter.getClasses().size(); i++) {
String className = tabAdapter.getClasses().get(i).getName();
if (manager.findFragmentByTag(className) != null) {
manager.putFragment(outState, className, manager.findFragmentByTag(className));
}
}
}
//...
TabAdapter class:
//...
public void addTab(Class<?> clss, FragmentManager manager, Bundle savedInstanceState) {
classes.add(clss);
String className = clss.getName();
tags.add(className);
Fragment fragment;
if (savedInstanceState != null) {
fragment = manager.getFragment(savedInstanceState, className);
if (fragment == null) {
fragment = createFragment(className);
manager.beginTransaction().add(fragment, className);
}
} else {
fragment = createFragment(className);
manager.beginTransaction().add(fragment, className);
}
mFragments.add(fragment);
}
//...
where createFragment is a simple method, that creates needed fragment by passed class name.