我一直在尝试添加到我的应用程序的 viewPager 遇到问题。
我有一个 SearchResultActivity,里面有一个抽屉。具有以下布局:
<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" />
因为我使用的是片段,所以当第一次到达这个活动时,我在 Activity 的 onCreate 方法中打开使用事务打开一个 RecipeHeadlinesFragment:
@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);
}
RecipeHeadlinesFragment 是一个 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();
}
}
这是我的 RecipeTabsFragment 代码:
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.
}
}
}
这是 RecipeTabsFragment 布局,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>
现在,由于某种原因,在 RecipeTabsFragment 中并暂时离开应用程序(无论是退出主菜单,还是设备进入睡眠模式)并返回应用程序时,应用程序崩溃并发生以下异常:
## 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
##
有没有人知道什么是错的?发生并且可能相关的另一件事是,在RecipeTabsFragment 中并按下后退按钮时,我回到了我的应用程序的主要活动,而不是RecipeHeadlinesFragment,尽管那是我去过的实际地方在 RecipeTabsFragment 之前。帮助任何人? 编辑:所以我想我找到了我要问的主要问题的原因......当我在我的片段中时,我调用 getSherlockActivity() 来获取 FragmentManager 而不是调用片段的 getChildFragmentManager()。问题解决了。