I'm using a FragmentPagerAdapter to create a layout with 2 fragments, where user can swipe between them:
mTabsAdapter = new TabsAdapter(this, mPager);
mTabsAdapter.addTab(bar.newTab().setText("Tab 1"), FirstFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText("Tab 2"), SecondFragment.class, null);
Right after that, i want to get the added fragment to call its methods:
FirstFragment firstFragment = (FirstFragment) mTabsAdapter.findFragmentByPosition(pos);
The problem is at this time the tabs aren't ready yet, and findFragmentByPosition returns null. If I do this inside a Handler().postDelayed(new Runnable(){..., it does the trick when testing, but I still get this error from some users.
Is there a way to know if fragments are ready?
Below is the TabsAdapter class:
public static class TabsAdapter extends FragmentPagerAdapter implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final SherlockFragmentActivity mActivity;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i=0; i<mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
}
public void selectTabByPosition(int position){
mViewPager.setCurrentItem(position);
}
public Fragment findFragmentByPosition(int position) {
FragmentPagerAdapter fragmentPagerAdapter = this;
return mActivity.getSupportFragmentManager().findFragmentByTag(
"android:switcher:" + mViewPager.getId() + ":"
+ fragmentPagerAdapter.getItemId(position));
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
//
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
//
}
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(SherlockFragmentActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActivity = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
#Override
public int getCount() {
return mTabs.size();
}
#Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
}
MainActivity.java
// Fragments and ViewPager Initialization
List<Fragment> fragments = getFragments();
pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
mViewPager.setAdapter(pageAdapter);
mViewPager.setOnPageChangeListener(MainActivity.this);
MyPageAdapter.java
public class MyPageAdapter extends FragmentPagerAdapter
{
private List<Fragment> fragments;
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}}
Related
I have a view pager with 2 tabs, the thing is, as soon as I open the Activity, both the tabs(i.e fragments) start(try to load data). Is there a way I can start the fragment only when the tab is selected.
PagerAdapter adapter = new PagerAdapter((MFragmentActivity ) this,
mViewPager);
adapter.addTab(actionBar.newTab().setText("TAB-1"),
TabOneFragment.class, null);
adapter.addTab(actionBar.newTab().setText("TAB-2"),
TabTwoFragment.class, null);
public static class PagerAdapter extends FragmentPagerAdapter implements
ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public PagerAdapter(MFragmentActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
public int getCount() {
return mTabs.size();
}
public SherlockFragment getItem(int position) {
TabInfo info = mTabs.get(position);
return (SherlockFragment) Fragment.instantiate(mContext,
info.clss.getName(), info.args);
}
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
}
public void onPageScrollStateChanged(int state) {
}
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mViewPager.setCurrentItem(tab.getPosition());
Object tag = tab.getTag();
for (int i = 0; i < mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
}
I want to handle one fragment within tabsadapter which is a static class in my Activity. The problem is how can i get the getfragmentbytag in the onTabSelected?
From the onCreate i have this code:
Tab tab1 = actionBar.newTab().setText("ABOUT");
tabsAdapter.addTab(tab1, PoiAboutFragment.class, null);
and my tabs adapter class is the following which works with no problem.
public static class TabsAdapter extends FragmentPagerAdapter implements
ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
private Object gridTag;
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(SherlockFragmentActivity activity, ViewPager pager,
ActionBar actionBar) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = actionBar;
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
if(clss.equals(GridFragment.class))
gridTag = tab.getTag();
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
#Override
public int getCount() {
return mTabs.size();
}
#Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(),
info.args);
}
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
}
public void onPageScrollStateChanged(int state) {
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
Log.i(TAG, "onTabSelected has been called");
if(tag.equals(gridTag))
Log.i(TAG, "gridtab has been called");
for (int i = 0; i < mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
}
the problem is that i want to handle one of my fragments in both the oncreate method and in the tabsAdapter but i don't have neither a fragment tag neither an fragment Id. How can i handle their methods from my Activity?
The FragmentPagerAdapter source's makeFragmentName methods shows that fragments are created with the following tags:
"android:switcher:" + viewId + ":" + id
Where viewId is the id of the ViewPager, i.e., use
activity.getSupportFragmentManager().findFragmentByTag(
"android:switcher:" + pager.getId() + ":0"
to get the first Fragment.
I found the answer I was looking for in this site android-er.blogasppot
This is my pager adapter.
public static class PagerAdapter extends FragmentPagerAdapter implements
ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public PagerAdapter(SherlockFragmentActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
public int getCount() {
return mTabs.size();
}
public SherlockFragment getItem(int position) {
TabInfo info = mTabs.get(position);
return (SherlockFragment) Fragment.instantiate(mContext,
info.clss.getName(), info.args);
}
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
}
public void onPageScrollStateChanged(int state) {
}
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mViewPager.setCurrentItem(tab.getPosition());
Log.d("Tab position selected = ", "" + tab.getPosition());
// Log.v(TAG, "clicked");
Object tag = tab.getTag();
for (int i = 0; i < mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
}
How can i add a tag or an id to the fragments in each tab. So that i can access them later.
Thank You
You can use override for this method and apply your custom fragment,
#Override
public Fragment getItem(int position) {
if (position == 0)
fragment = new Fragment1();
else (position == 1)
fragment = new Fragment2();
return fragment;
}
and so on if else what ever your require implements and override for this method,
#SuppressLint("DefaultLocale")
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return ;
case 1:
return ;
}
return null;
}
try it out.
I have a working state pager project using actionbarsherlock but I'm having trouble with getting the current fragment that was displayed. Is it possible to get the position of the current fragment?
Yes it is possible. If you are using a ViewPager you can do that :
_viewPager.getCurrentItem();
or that
_pageListener = new PageListener();
_viewPager.setOnPageChangeListener(_pageListener);
and keep trace of current page with something like that :
private int _currentPage;
private static class PageListener extends SimpleOnPageChangeListener{
public void onPageSelected(int position) {
Log.i(TAG, "page selected " + position);
_currentPage = position;
}
}
Or else you can easily do that with a TabAdapter like this :
public static class TabsAdapter extends FragmentPagerAdapter implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(SherlockFragmentActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
#Override
public int getCount() {
return mTabs.size();
}
#Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
((SherlockFragmentActivity) mContext).supportInvalidateOptionsMenu();
}
public void onPageScrollStateChanged(int state) {
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i = 0; i < mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
}
You only need to keep the current page with one/or two of the methods. For example in onTabSelected
hope it helps you
good luck
I'm trying to set my Tab2 as the initially selected tab using ActionBarShelock but I'm having trouble getting to work.
The tabs are working perfectly but I can't get it to select the 2nd tab instead of the first one when the app starts.
Here's my code:
#Override
public void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppThemeLightDarkActionBar);
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayShowTitleEnabled(true);
mViewPager = new ViewPager(this);
mViewPager.setId(R.id.pager);
setContentView(mViewPager);
ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mTabsAdapter = new TabsAdapter(this, mViewPager);
mTabsAdapter.addTab(bar.newTab().setText("Tab1"), Tab1.class, null);
mTabsAdapter.addTab(bar.newTab().setText("Tab2"),
Tab2.class, null);
mTabsAdapter.addTab(bar.newTab().setText("Tab3"), Tab3.class,
null);
mTabsAdapter.addTab(bar.newTab().setText("Tab4"), Tab4.class, null);
}
public static class TabsAdapter extends FragmentPagerAdapter implements
ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(SherlockFragmentActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
#Override
public int getCount() {
return mTabs.size();
}
#Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(),
info.args);
}
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
}
public void onPageScrollStateChanged(int state) {
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i = 0; i < mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
}
How can I make it work?
Thanks.
Use this at the end of your onCreate method:
mViewPager.setCurrentItem(1);
The above method should be 0-based, so 1 is the second page.