I've been having trouble with the viewPager i'm trying to add to my app.
I have a SearchResultActivity that has a drawer in it. with the following layout:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView
android:id="@+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp" />
because I'm using fragments, when first arriving at this activity, I open use a transaction to open a RecipeHeadlinesFragment in the Activity's onCreate method:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drawer_main);
mSearchType = getIntent().getIntExtra(SEARCH_TYPE, -1);
if (mSearchType == ICON_SEARCH) {
mVeggieNamesIcons = getIntent().getStringArrayListExtra(
VEGGIE_NAME_ARR);
mVeggieUrlsIcons = getIntent().getStringArrayListExtra(
VEGGIE_URLS_ARR);
} else if (mSearchType == QUERY_SEARCH) {
mQuery = getIntent().getStringExtra(QUERY);
}
// Generate title
title = new String[] { "Search for a recipe", "My profile",
"Title Fragment 3" };
// Generate subtitle
subtitle = new String[] { "", "", "Subtitle Fragment 3" };
// Generate icon
icon = new int[] { R.drawable.action_about, R.drawable.action_settings,
R.drawable.collections_cloud };
// Locate DrawerLayout in drawer_main.xml
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
// Locate ListView in drawer_main.xml
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// Set a custom shadow that overlays the main content when the drawer
// opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
GravityCompat.START);
// Pass results to MenuListAdapter Class
mMenuAdapter = new MenuListAdapter(this, title, subtitle, icon);
// Set the MenuListAdapter to the ListView
mDrawerList.setAdapter(mMenuAdapter);
// Capture button clicks on side menu
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
// Enable ActionBar app icon to behave as action to toggle nav drawer
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the sliding drawer and the action bar app icon
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.menubutton, R.string.drawer_open,
R.string.drawer_close) {
public void onDrawerClosed(View view) {
getActionBar().setTitle("");
// getActionBar().setBackgroundDrawable(d)
super.onDrawerClosed(view);
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle("menu");
// getActionBar().setBackgroundDrawable(new
// ColorDrawable(Color.GREEN));
super.onDrawerOpened(drawerView);
invalidateOptionsMenu();
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
// Check whether the activity is using the layout version with
// the fragment_container FrameLayout. If so, we must add the first
// fragment
if (findViewById(R.id.content_frame) != null) {
if (savedInstanceState == null) {
Bundle args = new Bundle();
args.putInt(SEARCH_TYPE, mSearchType);
if (mSearchType == QUERY_SEARCH) {
args.putString(QUERY, mQuery);
} else if (mSearchType == ICON_SEARCH) {
args.putStringArrayList(VEGGIE_NAME_ARR, mVeggieNamesIcons);
args.putStringArrayList(VEGGIE_URLS_ARR, mVeggieUrlsIcons);
}
recipeHeadlines.setArguments(args);
// Add the fragment to the 'fragment_container' FrameLayout
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction().replace(R.id.content_frame,
recipeHeadlines);
ft.commit();
} else {
return;
}
}
getActionBar().setIcon(R.color.transparent);
}
The RecipeHeadlinesFragment is a sherlockListFragment. i've created an onArticleSelectedListener interface in it, and made the activity implement it, such that when a list item is selected, the activity's onArticleSelected method is called and a RecipeTabsFragment is initiated and passed to the front using another transaction:
public void onArticleSelected(int position, RecipeObj obj) {
// The user selected the headline of an article from the
// HeadlinesFragment
// Capture the article fragment from the activity layout
RecipeTabsFragment articleFrag = (RecipeTabsFragment) getSupportFragmentManager()
.findFragmentById(R.id.pager);
if (articleFrag != null) {
// If article frag is available, we're in two-pane layout...
// Call a method in the ArticleFragment to update its content
articleFrag.updateArticleView(position, obj);
// todo update data
} else {
// If the frag is not available, we're in the one-pane layout and
// must swap frags...
// Create fragment and give it an argument for the selected article
RecipeTabsFragment newFragment = new RecipeTabsFragment();
Bundle args = new Bundle();
args.putParcelable(RecipeTabsFragment.ARG_RECIPE, obj);
args.putInt(RecipeTabsFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
// Replace whatever is in the fragment_container view with this
// fragment,
// and add the transaction to the back stack so the user can
// navigate back
transaction.replace(R.id.content_frame, newFragment);
// Commit the transaction
transaction.commit();
}
}
this is my RecipeTabsFragment code:
public class RecipeTabsFragment extends SherlockFragment {
// Declare Variables
final static String ARG_POSITION = "position";
final static String TAB_POSITION = "tab";
final static String ARG_RECIPE = "recipeData";
View rootView;
ActionBar mActionBar;
TextView mRecipeTitle;
TextView mRecipeBloger;
RatingBar mRecipeRatingBar;
int mCurrentPosition = -1;
int mCurrentTab = 0;
static ViewPager mPager;
Tab tab;
FragmentStatePagerAdapter mAdapter;
static final int NUM_ITEMS = 3;
// View rootView;
EditText editsearch;
ProgressDialog mProgressDialog;
// ImageAndName[] mTemplist = {};
GridView gridview;
private RecipeObj mRecipeData;
// The container Activity must implement this interface so the frag can
// deliver messages
public interface OnNameSetter {
/** Called by HeadlinesFragment when a list item is selected */
public void setName(String name);
public String getName();
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
//initialize the recipe title,bloger and rating view on the action bar
MenuItem item = menu.findItem(R.id.data_item);
mRecipeTitle = (TextView) item.getActionView().findViewById(
R.id.tv_title_ab);
mRecipeBloger = (TextView) item.getActionView().findViewById(
R.id.tv_bloger_ab);
mRecipeRatingBar = (RatingBar) item.getActionView().findViewById(
R.id.rb_list_item_ab);
//set the actual data to the view
mRecipeTitle.setText(mRecipeData.getFields().getName());
super.onPrepareOptionsMenu(menu);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.recip_detail, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@SuppressWarnings("null")
@Override
public void onStart() {
super.onStart();
Bundle args = getArguments();
if (args != null) {
// Set article based on argument passed in
updateArticleView(args.getInt(ARG_POSITION), (RecipeObj) args.getParcelable(ARG_RECIPE));
} else if (mCurrentPosition != -1) {
// Set article based on saved instance state defined during
// onCreateView
updateArticleView(mCurrentPosition, mRecipeData);
}
}
public void updateArticleView(int position, RecipeObj data) {
mRecipeData = data;
mCurrentPosition = position;
}
public void onResume() {
super.onResume();
//allows to put data on action bar that is not a action widget
getSherlockActivity().supportInvalidateOptionsMenu();
mActionBar = getSherlockActivity().getSupportActionBar();
mActionBar.setTitle("");
FragmentManager fm = getSherlockActivity().getSupportFragmentManager();
final ArrayList<String> titles = new ArrayList<String>();
titles.add("tab1");
titles.add("tab2");
titles.add("tab3");
mAdapter = new FragmentStatePagerAdapter(fm){
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
// Your current main fragment showing how to send arguments to
// fragment
RecipeArticle fragment1 = new RecipeArticle();
Bundle data1 = new Bundle();
data1.putParcelable(RecipeTabsFragment.ARG_RECIPE, mRecipeData);
fragment1.setArguments(data1);
fragment1.setName(titles.get(position));
return fragment1;
case 1:
// Calling a Fragment without sending arguments
RecipePreparation fragment2 = new RecipePreparation();
Bundle data2 = new Bundle();
data2.putParcelable(RecipeTabsFragment.ARG_RECIPE, mRecipeData);
fragment2.setArguments(data2);
fragment2.setName(titles.get(position));
return fragment2;
case 2:
Fragments3 fragment3 = new Fragments3();
// Bundle data2 = new Bundle();
// data2.putParcelable(IngrFragment.ARG_RECIPE, recipeData);
// fragment2.setArguments(data2);
fragment3.setName(titles.get(position));
return fragment3;
default:
return null;
}
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return NUM_ITEMS;
}
@Override
public int getItemPosition(Object item) {
OnNameSetter fragment = (OnNameSetter)item;
String title = fragment.getName();
int position = titles.indexOf(title);
if (position >= 0) {
return position;
} else {
return POSITION_NONE;
}
}
};
mPager = (ViewPager) rootView.findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mAdapter.notifyDataSetChanged();
mPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int arg0) {
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
//
// @Override
public void onPageSelected(int arg0) {
mActionBar.getTabAt(arg0).select();
}
});
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create first Tab
tab = mActionBar
.newTab()
.setText(getString(string.ingrdients))
.setTabListener(
new TabListener<RecipeArticle>(this
.getSherlockActivity(), "SearchPage1",
RecipeArticle.class));
tab.setIcon(R.drawable.ing);
mActionBar.addTab(tab);
// Create second Tab
tab = mActionBar
.newTab()
.setText(getString(string.prepration))
.setTabListener(
new TabListener<RecipePreparation>(this
.getSherlockActivity(), "SearchPage2",
RecipePreparation.class));
tab.setIcon(R.drawable.how);
mActionBar.addTab(tab);
// Create third Tab
tab = mActionBar
.newTab()
.setText(getString(string.comments))
.setTabListener(
new TabListener<Fragments3>(this.getSherlockActivity(),
"SearchPage3", Fragments3.class));
tab.setIcon(R.drawable.why);
mActionBar.addTab(tab);
setHasOptionsMenu(true);
mActionBar.getTabAt(mCurrentTab).select();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (savedInstanceState != null) {
mCurrentPosition = savedInstanceState.getInt(ARG_POSITION);
mRecipeData = savedInstanceState.getParcelable(ARG_RECIPE);
mCurrentTab = savedInstanceState.getInt(TAB_POSITION);
}
rootView = inflater.inflate(R.layout.ingr_tabs, container, false);
return rootView;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Save the current article selection in case we need to recreate the
// fragment
outState.putInt(ARG_POSITION, mCurrentPosition);
outState.putInt(TAB_POSITION, mCurrentTab);
outState.putParcelable(ARG_RECIPE, mRecipeData);
}
public static class TabListener<T extends Fragment> implements
ActionBar.TabListener {
private Fragment mFragment;
private final SherlockFragmentActivity mActivity;
private final String mTag;
private final Class<T> mClass;
/**
* Constructor used each time a new tab is created.
*
* @param sherlockFragmentActivity
* The host Activity, used to instantiate the fragment
* @param tag
* The identifier tag for the fragment
* @param clz
* The fragment's Class, used to instantiate the fragment
*/
public TabListener(SherlockFragmentActivity sherlockFragmentActivity,
String tag, Class<T> clz) {
mActivity = sherlockFragmentActivity;
mTag = tag;
mClass = clz;
}
/* The following are each of the ActionBar.TabListener callbacks */
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mPager.setCurrentItem(tab.getPosition());
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// User selected the already selected tab. Usually do nothing.
}
}
}
and this is the RecipeTabsFragment layout, ingr_tabs.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:tag="ingr_screen"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</android.support.v4.view.ViewPager>
Now, for some reason, while being in the RecipeTabsFragment, and leaving the app temporarily (whether exiting to the home menu, or the device goes to sleep mode) and returning to the app, the app crashes and the following exception occurs:
## 08-26 14:39:30.640: E/AndroidRuntime(5520): FATAL EXCEPTION: main
08-26 14:39:30.640: E/AndroidRuntime(5520): java.lang.RuntimeException: Unable to resume activity {development.example.vegancookbook/development.example.vegancookbook.SearchResultActivity}: java.lang.IllegalStateException: Observer android.support.v4.view.ViewPager$PagerObserver@414db9b0 was not registered.
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2456)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2484)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1185)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.os.Handler.dispatchMessage(Handler.java:99)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.os.Looper.loop(Looper.java:137)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.app.ActivityThread.main(ActivityThread.java:4507)
08-26 14:39:30.640: E/AndroidRuntime(5520): at java.lang.reflect.Method.invokeNative(Native Method)
08-26 14:39:30.640: E/AndroidRuntime(5520): at java.lang.reflect.Method.invoke(Method.java:511)
08-26 14:39:30.640: E/AndroidRuntime(5520): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
08-26 14:39:30.640: E/AndroidRuntime(5520): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
08-26 14:39:30.640: E/AndroidRuntime(5520): at dalvik.system.NativeStart.main(Native Method)
08-26 14:39:30.640: E/AndroidRuntime(5520): Caused by: java.lang.IllegalStateException: Observer android.support.v4.view.ViewPager$PagerObserver@414db9b0 was not registered.
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.database.Observable.unregisterObserver(Observable.java:64)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.view.PagerAdapter.unregisterDataSetObserver(PagerAdapter.java:294)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:409)
08-26 14:39:30.640: E/AndroidRuntime(5520): at development.example.vegancookbook.RecipeTabsFragment.onResume(RecipeTabsFragment.java:196)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.Fragment.performResume(Fragment.java:1521)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:963)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:472)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:163)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:415)
08-26 14:39:30.640: E/AndroidRuntime(5520): at development.example.vegancookbook.RecipeTabsFragment.onResume(RecipeTabsFragment.java:196)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.Fragment.performResume(Fragment.java:1521)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:963)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:1887)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.FragmentActivity.onResumeFragments(FragmentActivity.java:460)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.support.v4.app.FragmentActivity.onPostResume(FragmentActivity.java:449)
08-26 14:39:30.640: E/AndroidRuntime(5520): at com.actionbarsherlock.app.SherlockFragmentActivity.onPostResume(SherlockFragmentActivity.java:69)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.app.Activity.performResume(Activity.java:4552)
08-26 14:39:30.640: E/AndroidRuntime(5520): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2446)
08-26 14:39:30.640: E/AndroidRuntime(5520): ... 10 more
##
does anyone have a clue on whats wrong?? another thing that happens and might be related, is that whilst being in the RecipeTabsFragment, and pressing the back button, I get back to the main activity of my app, and not to the RecipeHeadlinesFragment, though that's the actual place i've been to before the RecipeTabsFragment. Help anyone? EDIT: So I think I found the reason for the main problem I was asking about... when I was in my fragement, I called the getSherlockActivity() to get the FragmentManager instead of calling the fragment's getChildFragmentManager(). problem solved.
I found what the problem was, and I better answer my question for future generations... I used getSupportFragmentManager() inside the fragment instead of using getChildFragmentManager(). that's all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With