Im using an ActionBar, which loads different Fragments. This is done within a FragmentActivity class. One of the Fragent should have a ViewPager holding different Fragments.
I dont get any error anymore now, but the ViewPager and the PagerTitleStrip and all the Fragents inside the ViewPager are not shown up at all. The other Fragments from the ActionBar working properly. Im using all classes from the Support-Package.
I rdid read a lot of posts here, but I couldnt find it out yet.
In my ActivityClass derived from FragmentAcivity, I use the Listener:
SettingsActiviy.java
protected class SettingsTabsListener implements ActionBar.TabListener {
private Fragment fragment;
public SettingsTabsListener(Fragment fragment) {
this.fragment = fragment;
Log.e("SettingsTabListener","Contructor Fragment is " + fragment);
}
#Override
public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction xaction=fragMgr.beginTransaction();
// Dont know if we really need that...
if (fragment instanceof SettingsActivityOverviewFragment) {
if (fragment == null) {
fragment = SettingsActivityOverviewFragment.newInstance(appWidgetId);
}
}
xaction.replace(R.id.FragmentPlaceholder, (Fragment)fragment);
xaction.commit();
}
#Override
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction xaction=fragMgr.beginTransaction();
xaction.remove(fragment);
xaction.commit();
}
SettingsActivityOverviewFragment.java
public class SettingsActivityOverviewFragment extends Fragment {
private static final Field sChildFragmentManagerField;
ViewPager viewPager;
PagerAdapter pagerAdapter;
public static final SettingsActivityOverviewFragment newInstance(int appWidgetId){
SettingsActivityOverviewFragment f = new SettingsActivityOverviewFragment();
Bundle bdl = new Bundle(1);
bdl.putInt("appWidgetId", appWidgetId);
f.setArguments(bdl);
return f;
}
/* this is a fix caused by googles nullpointer, until detach-method */
static {
Field f = null;
try {
f = Fragment.class.getDeclaredField("mChildFragmentManager");
f.setAccessible(true);
} catch (NoSuchFieldException e) {
}
sChildFragmentManagerField = f;
}
#Override
public void onDetach() {
super.onDetach();
if (sChildFragmentManagerField != null) {
try {
sChildFragmentManagerField.set(this, null);
} catch (Exception e) {
}
}
}
/* end of fix */
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View result=inflater.inflate(R.layout.settings_frag_overview, container, false);
viewPager=(ViewPager)result.findViewById(R.id.overview_pager);
Log.e("SettingsActivityOverviewFragment","viewPager content is " + viewPager + ", " + viewPager.getHeight());
pagerAdapter = buildAdapter();
new SetAdapterTask().execute();
return(result);
}
private PagerAdapter buildAdapter() {
return(new SettingsOverviewPagerAdapter(getActivity(), getChildFragmentManager()));
}
public void onActivityResult(int requestCode, int resultCode, android.content.Intent data) {
}
private class SetAdapterTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void result) {
if(pagerAdapter != null) viewPager.setAdapter(pagerAdapter);
}
}
}
SettingsOverviewPagerAdapter.java
public class SettingsOverviewPagerAdapter extends FragmentPagerAdapter {
Context ctxt=null;
public SettingsOverviewPagerAdapter(Context ctxt, FragmentManager mgr) {
super(mgr);
this.ctxt=ctxt;
}
#Override
public int getCount() {
Log.i("SettingsOverviewPagerAdapter","getCount returns 10");
return(10);
}
#Override
public Fragment getItem(int position) {
return(EditorFragment.newInstance(position));
}
#Override
public String getPageTitle(int position) {
return(EditorFragment.getTitle(ctxt, position));
}
}
EditorFragment.java
public class EditorFragment extends Fragment {
private static final String KEY_POSITION = "position";
static EditorFragment newInstance(int position) {
EditorFragment frag = new EditorFragment();
Bundle args = new Bundle();
args.putInt(KEY_POSITION, position);
frag.setArguments(args);
return (frag);
}
static String getTitle(Context ctxt, int position) {
return (String.format("ctest", position + 1));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View result = inflater.inflate(R.layout.editor, container, false);
EditText editor = (EditText) result.findViewById(R.id.editor);
int position = getArguments().getInt(KEY_POSITION, -1);
editor.setHint(getTitle(getActivity(), position));
return (result);
}
}
SettingsFragOverview.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/overview_pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.PagerTitleStrip
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#33b5e5"
android:textColor="#fff"/>
</android.support.v4.view.ViewPager>
EditorFragment.xml
<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/editor"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="textMultiLine"
android:gravity="left|top"
/>
This typically occurs when:
Using an inner fragment as parent of ViewPager
Parent container has a scrollview in it.
Related
I want to Change the Pager Layout at runtime with other fragment but without the PagerSlidingTabStrip Title. How .I can make it .
Second how .I can call method home Fragment in another fragments.
Here is The Home Layout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginBottom="50dp"
android:id="#+id/SlidingStrips"
android:layout_marginTop="10dp"
android:layout_below="#id/AcountBalance">
<com.refractored.PagerSlidingTabStrip
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:pstsPaddingMiddle="true"
app:pstsDividerWidth="1dp"
app:pstsDividerPadding="5dp"
app:pstsDividerColor="#50FFFFFF"
android:textColor="#50FFFFFF"
app:pstsTextColorSelected="#android:color/white"
app:pstsIndicatorColor="#android:color/white"
app:pstsUnderlineColor="#android:color/white" />
<!--Change this to true if you want to center items-->
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
tools:context=".HomeFragmentLayout" />
</LinearLayout>
And how i'm Adding fragments here is the ChildFragments that added with the parent fragment these two fragments add two tabs with Hour and day Tabs.
public class HomeFragment : Fragment, IOnTabReselectedListener, ViewPager.IOnPageChangeListener
{
View view;
private MyPagerAdapter adapter;
private int count = 1;
private int currentColor;
List<Android.Support.V4.App.Fragment> fragments = new List<Android.Support.V4.App.Fragment>();
public static ViewPager pager;
private PagerSlidingTabStrip tabs;
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your fragment here
}
public static HomeFragment NewInstance()
{
var frag1 = new HomeFragment { Arguments = new Bundle() };
return frag1;
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView(inflater, container, savedInstanceState);
if (view == null)
{
view = inflater.Inflate(Resource.Layout.HomeFragmentLayout, container, false);
return view;
}
else
{
return view;
}
}
public override void OnViewCreated(View view, Bundle savedInstanceState)
{
base.OnViewCreated(view, savedInstanceState);
try
{
fragments.Add(new HourlyFragment());
fragments.Add(new DayFragment());
adapter = new MyPagerAdapter(ChildFragmentManager, fragments);
pager = view.FindViewById<ViewPager>(Resource.Id.pager);
tabs = View.FindViewById<PagerSlidingTabStrip>(Resource.Id.tabs);
pager.Adapter = adapter;
tabs.SetViewPager(pager);
var pageMargin = (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, 4, Resources.DisplayMetrics);
pager.PageMargin = pageMargin;
pager.CurrentItem = 0;
tabs.OnTabReselectedListener = this;
tabs.OnPageChangeListener = this;
}
catch (System.Exception ex)
{
}
}
.// public void ReplaceFragment(Fragment fragment)
//{
// try
// {
// FragmentManager manager = ChildFragmentManager;
// FragmentTransaction transaction = manager.BeginTransaction();
// transaction.Add(Resource.Id.content_frame, fragment);
// transaction.Commit();
// }
// catch (System.Exception ex)
// {
// }
//}
public void OnTabReselected(int position)
{
Toast.MakeText(Context.ApplicationContext, "Tab reselected: " + position, ToastLength.Short).Show();
}
public void OnPageScrollStateChanged(int state)
{
Console.WriteLine("Page scroll state changed: " + state);
}
public void OnPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
Console.WriteLine("Page Scrolled");
}
public void OnPageSelected(int position)
{
Console.WriteLine("Page selected: " + position);
}
}
Here is the pager Adapter
public class MyPagerAdapter : FragmentPagerAdapter
{
List<Android.Support.V4.App.Fragment> fragments;
private readonly string[] Titles =
{
"Hour", "Day"
};
public MyPagerAdapter(FragmentManager fm, List<Android.Support.V4.App.Fragment> fragments) : base(fm)
{
this.fragments = fragments;
}
public override ICharSequence GetPageTitleFormatted(int position)
{
return new String(Titles[position]);
}
//}
public override int Count { get { return fragments.Count; } }
public override Fragment GetItem(int position)
{
return fragments[position];
}
public override long GetItemId(int position)
{
return base.GetItemId(position);
}
}
You could do like below,suppose you need to call the replacement method in HomeFragment.
Add below codes in your MyPagerAdapter class (how to replace the fragment at runtime):
private bool[] flags;
public override int GetItemPosition(Java.Lang.Object #object)
{
return PositionNone;
}
public override Java.Lang.Object InstantiateItem(ViewGroup container, int position)
{
if (flags != null && flags[position])
{
/** Get the cached fragment and replace it with a new fragment*/
Android.Support.V4.App.Fragment fragment = (Android.Support.V4.App.Fragment)base.InstantiateItem(container, position);
string fragmentTag = fragment.Tag;
Android.Support.V4.App.FragmentTransaction ft = fm.BeginTransaction();
ft.Remove(fragment);
fragment = fragments[position];
ft.Add(container.Id, fragment, fragmentTag);
ft.Attach(fragment);
ft.Commit();
/** Set to false when the replacement is complete*/
flags[position] = false;
if (fragment != null)
{
return fragment;
}
else
{
return base.InstantiateItem(container, position);
}
}
else
{
return base.InstantiateItem(container, position);
}
}
public void setFragments(List<Android.Support.V4.App.Fragment> fragments)
{
if (this.fragments != null)
{
flags = new bool[fragments.Count];
for (int i = 0; i < fragments.Count; i++)
{
flags[i] = true;
}
}
this.fragments = fragments;
NotifyDataSetChanged();
}
then the replace method in your HomeFragment :
public void ReplaceFragment()
{
fragments[0] = new NewFragment(); //suppose you want to replace the first HourlyFragment
fragments[1] = new DayFragment();
adapter.setFragments(fragments);
}
in the other fragment(for example a click event),you could call the replace method which in the HomeFragment like :
private void Button_Click(object sender, EventArgs e)
{
foreach (Android.Support.V4.App.Fragment fragment in Activity.SupportFragmentManager.Fragments)
{
if (fragment is HomeFragment)
{
((HomeFragment)fragment).ReplaceFragment();
}
}
}
My Fragment class:
onCreatedView:
parentActivity = (MainActivity) getActivity();
parentView = inflater.inflate(R.layout.fragmentla, container, false);
mFragmentAdapter = new myFragmentAdapter(parentActivity.getSupportFragmentManager(), parentView.getContext());
// Get the ViewPager and set it's PagerAdapter so that it can display items
ViewPager viewPager = (ViewPager) parentView.findViewById(R.id.viewpager);
viewPager.setAdapter(mFragmentAdapter);
// Give the TabLayout the ViewPager
TabLayout tabLayout = (TabLayout) parentView.findViewById(R.id.tablayout);
tabLayout.setupWithViewPager(viewPager);
Thats my fragment (Blue border). My fragment contains toolbar, tablayout, and viewpager.
My FragmentAdapter class:
public class myFragmentAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 2;
private String tabTitles[] = new String[] { "ITEM1", "ITEM2" };
private Context context;
public myFragmentAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public int getCount() {
return 2;
}
#Override
public Fragment getItem(int position) {
if(position == 0) {
return FirstFragment.newInstance(position + 1);
} else {
return SecondFragment.newInstance(position + 1);
}
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
And this is my FirstFragment class:
public static FirstFragment newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
FirstFragment fragment = new FirstFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getInt(ARG_PAGE);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
parentView = inflater.inflate(R.layout.fragment_first_newest, container, false);
sometext = (TextView) parentView.findViewById(R.id.wi_my_text);
return parentView;
}
So, my question is: Everytime that I press my menu button in toolbar the textview should change, but this return null cause "onCreatedView" is not called anymore. I tried with this in Fragment class:
public boolean onOptionsItemSelected(MenuItem item){
...
Fragment mFragment = mFragmentAdapter.getItem(0);
if(mFragment instanceof FirstFragment){
((FirstFragment) mFragment).OnButtonPressed();
}
}
Then on my FirstFragment but still getting null exception:
public void OnButtonPressed() {
someText.setText("its working");
createLocationRequest();
}
UPDATED: MY XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:id="#+id/wi_my_text"
android:layout_height="24dp"
android:layout_gravity="center"
android:gravity="center"
android:textStyle="bold"
android:paddingEnd="5dp"
android:text="texttest"/>
</LinearLayout>
I am implementing nested fragments in a ViewPager. When I perform the transaction by replacing the child fragment in the parent fragment after executing addToBackStack(), I am able to see the view shown below. But when I press back button and the code reaches the MainActivity's onBackPressed() method, I notice the stack size is 1, and I successfully popout the Fragment. The problem starts now
My app closes and for a brief amount of time, I see my child fragment closing and then the app closing.
MainActivity
public class MainActivity extends FragmentActivity implements FragmentCommunicationListener {
ViewPager viewPager;
PagerAdapter pagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//createTabs();
viewPager = (ViewPager) findViewById(R.id.pager);
Fragment[] fragments = new Fragment[]{
new ViewStudentsFragment(),
new AddStudentFragment()
};
pagerAdapter = new PagerAdapter(getSupportFragmentManager(), this, fragments);
viewPager.setAdapter(pagerAdapter);
}
#Override
public void passMsg(Fragment fragment, Bundle msg) {
int currentItem = viewPager.getCurrentItem();
Fragment targetFragment;
if (currentItem == 0) {
targetFragment = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + 1);
((AddStudentFragment) targetFragment).renderData(msg);
viewPager.setCurrentItem(1);
} else {
targetFragment = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + 0);
((ViewStudentsFragment) targetFragment).updateList(msg,viewPager);
viewPager.setCurrentItem(0);
}
}
#Override
public void onBackPressed() {
ViewStudentsFragment fragment = (ViewStudentsFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + 0);
super.onBackPressed();
if (fragment.getChildFragmentManager().getBackStackEntryCount() != 0) {
fragment.getChildFragmentManager().popBackStack();
}
}
}
Parent Fragment
public class ViewStudentsFragment extends Fragment {
ArrayList<Student> studentList = new ArrayList<Student>();
ListView list;
ListViewAdapter listAdapter;
GridView grid;
FragmentCommunicationListener fragComm = null;
int resIdView, resIdSort;
GridViewAdapter gridAdapter;
static ImageButton toggleView, toggleSort;
View view;
ViewPager viewPager=null;
public ViewStudentsFragment() {
}
private static ViewStudentsFragment viewStudentsFragment;
FragmentTransaction transaction;
Fragment details ;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_view_students, container, false);
toggleView = (ImageButton) view.findViewById(R.id.viewImageButton);
toggleSort = (ImageButton) view.findViewById(R.id.sortImageButton);
transaction= getChildFragmentManager().beginTransaction();
view.findViewById(R.id.container).setVisibility(View.GONE);
...
toggleView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
...
}
});
toggleSort.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
...
}
});
registerForContextMenu(list);
registerForContextMenu(grid);
return view;
}
public void updateList(Bundle bundle,ViewPager vp) {
viewPager=vp;
...
}
listAdapter.notifyDataSetChanged();
gridAdapter.notifyDataSetChanged();
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof FragmentCommunicationListener) {
fragComm = (FragmentCommunicationListener) activity;
} else {
throw new ClassCastException();
}
}
#Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
...
}
#Override
public boolean onContextItemSelected(MenuItem item) {
...
switch (menuItemIndex) {
case Constant.VIEW_STUDENT_DETAIL:
bundle.putSerializable("viewField", student); view.findViewById(R.id.container).setVisibility(View.VISIBLE);
transaction.addToBackStack(null);
details = new Details();
transaction.replace(R.id.container, details, "task");
transaction.commit();
details.setArguments(bundle);
break;
...
default:
}
listAdapter.setStudentList(studentList);
gridAdapter.setStudentList(studentList);
listAdapter.notifyDataSetChanged();
gridAdapter.notifyDataSetChanged();
return true;
}
}
ChildFragment
public class Details extends Fragment {
View view;
static Details details;
Context context;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
context=container.getContext();
Bundle bundle = getArguments();
view=inflater.inflate(R.layout.display_details, container, false);
...
return view;
}
#Override
public void onDetach() {
super.onDetach();
view.findViewById(R.id.displayDetails).setVisibility(View.GONE);
}
#Override
public void onDestroyView() {
super.onDestroyView();
view.findViewById(R.id.displayDetails).setVisibility(View.GONE);
}
#Override
public void setArguments(Bundle bundle) {
super.setArguments(bundle);
}
}
PagerAdapter
public class PagerAdapter extends FragmentPagerAdapter {
private String[] tabMenu;
private int pageCount;
private Context context;
private Fragment[] fragments;
public PagerAdapter(FragmentManager fm, Context context, Fragment[] fragments) {
super(fm);
this.context = context;
tabMenu = context.getResources().getStringArray(R.array.tab_menu);
pageCount = tabMenu.length;
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return fragments[position];
}
#Override
public int getCount() {
return fragments.length;
}
#Override
public CharSequence getPageTitle(int position) {
return tabMenu[position];
}
}
If you use FragmentTransaction.addToBackStack(), the back button is handled automatically for you.
When you do this:
#Override
public void onBackPressed() {
ViewStudentsFragment fragment = (ViewStudentsFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + 0);
super.onBackPressed();
if (fragment.getChildFragmentManager().getBackStackEntryCount() != 0) {
fragment.getChildFragmentManager().popBackStack();
}
}
you are basically popping the backstack twice, which is why your application quit.
Replace the onBackPressed() method in your Activity with this:
#Override
public void onBackPressed() {
ViewStudentsFragment fragment = (ViewStudentsFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + 0);
if (fragment.getChildFragmentManager().getBackStackEntryCount() != 0) {
fragment.getChildFragmentManager().popBackStack();
}
else {
super.onBackPressed();
}
}
I have an activity that has a viewpager fragment in it
one of the pages has another viewpager fragment in it
the problem is, when i reach the page of the inner viewpager fragment, the "onCreateView" of the inner viewpager fragments doesnt get called, and so the page is blank.
Why is that ?
here is my code :
fragment_viewpager.xml
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" >
</android.support.v4.view.ViewPager>
fragment_viewpager_with_logo.xml
<include layout="#layout/logo" />
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" >
</android.support.v4.view.ViewPager>
public class ViewPagerFragment extends Fragment {
private ViewPager fragmentPager;
private PagerAdapter fragmentAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (container instanceof ViewPager) {
return inflater.inflate(R.layout.fragment_viewpager_with_logo, container, false);
}
return inflater.inflate(R.layout.fragment_viewpager, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
fragmentPager = (ViewPager)getView().findViewById(R.id.pager);
fragmentPager.setAdapter(fragmentAdapter);
}
public void setAdapter(PurchaseFragmentStatePagerAdapter fragmentAdapter) {
this.fragmentAdapter = fragmentAdapter;
}
public void setCurrentItem(int i) {
fragmentPager.setCurrentItem(i);
}
public int getCurrentItem() {
return fragmentPager.getCurrentItem();
}
public void setOnPageChangeListener(OnPageChangeListener l) {
if (fragmentPager == null) {
fragmentPager = (ViewPager) getView().findViewById(R.id.pager);
}
fragmentPager.setOnPageChangeListener(l);
}
}
in some activity :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_container);
MyFragmentStatePagerAdapter fragmentAdapter = new MyStatePagerAdapter(getSupportFragmentManager());
List<Fragment> fragments = new ArrayList<Fragment>();
fragments.add(settingsFragment);// settings
ViewPagerFragment vpFragment = new ViewPagerFragment();
fragments.add(vpFragment);
fragmentAdapter.setFragments(fragments);
fragmentPager.setAdapter(fragmentAdapter);
MyFragmentStatePagerAdapter innerFragmentAdapter = new MyFragmentStatePagerAdapter(getSupportFragmentManager());
List<Fragment> innerFragments = new ArrayList<Fragment>();
innerFragments.add(settingsFragment);
innerFragmentAdapter.setFragments(innerFragments);
vpFragment.setAdapter(innerFragmentAdapter);
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.content_fragment, fragmentPager).commit();
}
MyFragmentStatePagerAdapter
public class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
private List<BaseFragment> fragments;
#Inject
public MyFragmentStatePagerAdapter(FragmentManager fm) {
super(fm);
}
public void setFragments(List<Fragment> fragments) {
this.fragments = fragments;
}
#Override
public BaseFragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments == null ? 0 : fragments.size();
}
}
In the Fragment use fragment.getChildFragmentManager() in FragmentPagerAdapter's constructor instead of getActivity().getFragmentManager()
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.