【问题标题】:ViewPager's fragment without activity context没有活动上下文的 ViewPager 片段
【发布时间】:2015-04-29 19:57:30
【问题描述】:

功能: 我正在开发某种配置向导,它可能有很多步骤。每个步骤都有自己的配置,在这种情况下,isSkippable() 是否用户可以跳过该步骤。以及当用户点击菜单项进入下一步或确实完成向导时的回调方法。

问题:我没有活动上下文,当从活动中调用onStepCompleted 时,我的字段也为空。

扩展 ActionBarActivity 且未实现任何接口的活动:

private WizardStepListener mStepListener;

private WizardPagerAdapter mPagerAdapter;
private ViewPager mViewPager;

public static Intent getIntent(final Context context) {
    final Intent intent = new Intent(context, WizardActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    return intent;
}

@Override
public boolean onOptionsItemSelected(final MenuItem item) {
    if (mStepListener == null) {
        return false;
    }

    switch (item.getItemId()) {
        case R.id.action_step_skip:
            moveToNextStep();

            break;

        case R.id.action_step_done:
        case R.id.action_step_next:

            final boolean stepCompleted = mStepListener.onStepCompleted();
            if (stepCompleted && !isLastStep() || !stepCompleted) {
                    break;
            }

            final Intent intent = LandingActivity.getIntent(this);
            WizardActivity.this.startActivity(intent);
            overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_right);
            WizardActivity.this.finish();

            break;

    }

    return true;
}

@Override
protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_wizard);

    final Resources resources = getResources();
    final PagerTabStrip pagerTabStrip = (PagerTabStrip) findViewById(R.id.pager_tab_strip);
    pagerTabStrip.setDrawFullUnderline(false);
    pagerTabStrip.setBackgroundColor(resources.getColor(R.color.tabs_categories_background));
    pagerTabStrip.setTextColor(Color.WHITE);
    pagerTabStrip.setTabIndicatorColor(Color.WHITE);

    mPagerAdapter = new WizardPagerAdapter(getSupportFragmentManager());
    mViewPager = (ViewPager) findViewById(R.id.wizard_pager);
    mViewPager.setAdapter(mPagerAdapter);
    mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {

        @Override
        public void onPageSelected(final int position) {
            setupView(position);
        }

    });

    setupView(0);
}

private void setupView(final int position) {
    final Fragment fragment = mPagerAdapter.getActiveFragment(mViewPager, position);

    mStepListener =
            fragment instanceof WizardStepListener ? (WizardStepListener) fragment : null;

    supportInvalidateOptionsMenu();
}

private boolean isLastStep() { ... }

private boolean moveToNextStep() { ... }

}

扩展Fragment并实现LoaderManager.LoaderCallbacks的片段>,WizardStepListener:

private CategoriesExpandableAdapter mCatAdapter;
private ViewFlipper mViewFlipper;

/**
 * @return A new instance of fragment WizardCategories.
 */
public static WizardCategories newInstance() {
    return new WizardCategories();
}

@Override
public boolean isSkippable() {
    return false;
}

@Override
public boolean onStepCompleted() {
    if (!isAdded()) {
        return false;
    }

    if (mCatAdapter == null || !mCatAdapter.hasCheckedCategories()) {

        FeedbackToast.getInstance(
                getActivity(),
                "Debes seleccionar al menos una categoría",
                FeedbackToast.NEGATIVE
        ).show();

        return false;
    }

    ...

    return true;
}

扩展FragmentPagerAdapter的PagerAdapter:

private final FragmentManager mFragmentManager;

public WizardPagerAdapter(final FragmentManager fm) {
    super(fm);
    mFragmentManager = fm;
}

@Override
public Fragment getItem(final int position) {
    final Fragment fragment;
    switch (position) {
        case 0:
            fragment = WizardCategories.newInstance();

            break;

        default:
            fragment = new Fragment();

            break;
    }

    return fragment;
}

public Fragment getActiveFragment(final ViewPager container, final int position) {
    final String name = makeFragmentName(container.getId(), position);
    final Fragment fragment = mFragmentManager.findFragmentByTag(name);
    return  fragment != null ? fragment : getItem(position);
}

private static String makeFragmentName(final int viewId, final int index) {
    return "android:switcher:" + viewId + ":" + index;
}

我的尝试

  • 更改 PagerAdapter 扩展到 FragmentStatePagerAdapter,但没有成功。
  • 使用 getActiveFragment 从 FragmentManager 检索片段,在另一个可能相关的帖子中看到。

其他 cmets

  • Fragment 的 isAdded() 总是返回 false。
  • 在片段的 onStepCompleted 上调用 getActivity() 始终返回 null。

【问题讨论】:

  • 如何扭转局面,让向导片段自己持有菜单项?然后他们可以直接调用活动,例如((YourActivity)getActivity()).moveToNextPage()。这种方法可以为一个通用的 WizardFragment 完成,然后让所有的向导页面都从那里扩展。
  • 我要试试你建议的这种方法......你认为这能解决我失去活动的事实吗?
  • 好吧,如果没有附加到活动,片段应该无法显示菜单项,所以我假设是的。
  • 您可以在调用 super.onCreate(savedInstanceState) 之后在片段的 onCreate 中调用 getActivity()。我现在正在我的项目中这样做,并且效果很好。
  • @cYrixmorten 你的方法是正确的!而且更优雅!谢谢!想发布答案?将问题标记为已回答?

标签: android android-fragments android-viewpager


【解决方案1】:

如何扭转局面并让向导片段自己持有菜单项?然后他们可以直接调用活动,例如 ((YourActivity)getActivity()).moveToNextPage()。

这种方法可以为一个通用的 WizardFragment 完成,然后让所有的向导页面都从那里扩展。

【讨论】:

  • 我使用接口对它进行了更多的整理,并完善了我现有的接口。奇迹般有效!谢谢!
【解决方案2】:

您应该能够使用 getActivity() 来获取 Activity 并将上下文存储在 onCreate 中的片段中,要记住的主要事情是您需要在调用 onAttach 之后调用它,以便将片段链接到 Activity。

我目前在我的应用程序的 onCreate() 中使用 Activity 的上下文没有问题。

或者,您可以覆盖 onAttach 并直接获取对 Activity 的引用并将其存储在那里:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
}

参考: Using context in a fragment

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 1970-01-01
    相关资源
    最近更新 更多