Дублирование пунктов меню с помощью ViewPager и Fragments - PullRequest
2 голосов
/ 20 ноября 2011

Я создаю приложение для Android (минимум SDK Level 10, Gingerbread 2.3.3) с некоторыми фрагментами в ViewPager.Я использую ActionBarSherlock для создания ActionBar и android-viewpagertabs для добавления вкладок в ViewPager, как в клиенте Market.

У меня есть один глобальный пункт менючто я хочу показать на каждой вкладке / фрагмент.На первой из трех вкладок я хочу иметь два дополнительных пункта меню.

Но теперь происходят две странные вещи:

Во-первых, если я запускаю приложение, все вроде бы нормально, я могуувидеть все три пункта меню на первой странице и только один пункт, если я проведу по второй и третьей вкладке.Но если я вернусь ко второй вкладке с третьей, я снова смогу увидеть все три элемента, чего не должно быть.Если я проведу пальцем назад к первой, а затем снова ко второй вкладке, все снова в порядке.

Другая странная вещь заключается в том, что каждый раз, когда я поворачиваю устройство, пункты меню из фрагмента добавляются снова, дажехотя они уже находятся в меню.

Код FragmentActivity, который отображает ViewPager и его вкладки:

public class MainActivity extends FragmentActivity {

    public static final String TAG = "MainActivity";

    private ActionBar actionBar;
    private Adapter adapter;
    private ViewPager viewPager;
    private ViewPagerTabs tabs;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.volksempfaenger);

        actionBar = getSupportActionBar();

        adapter = new Adapter(getSupportFragmentManager());
        adapter.addFragment(getString(R.string.title_tab_subscriptions),
                SubscriptionGridFragment.class);
        // adding more fragments here

        viewPager = (ViewPager) findViewById(R.id.viewpager);
        viewPager.setAdapter(adapter);

        tabs = (ViewPagerTabs) findViewById(R.id.tabs);
        tabs.setViewPager(viewPager);
    }

    public static class Adapter extends FragmentPagerAdapter implements
            ViewPagerTabProvider {

        private FragmentManager fragmentManager;
        private ArrayList<Class<? extends Fragment>> fragments;
        private ArrayList<String> titles;

        public Adapter(FragmentManager fm) {
            super(fm);
            fragmentManager = fm;
            fragments = new ArrayList<Class<? extends Fragment>>();
            titles = new ArrayList<String>();
        }

        public void addFragment(String title, Class<? extends Fragment> fragment) {
            titles.add(title);
            fragments.add(fragment);
        }

        @Override
        public int getCount() {
            return fragments.size();
        }

        public String getTitle(int position) {
            return titles.get(position);
        }

        @Override
        public Fragment getItem(int position) {
            try {
                return fragments.get(position).newInstance();
            } catch (InstantiationException e) {
                Log.wtf(TAG, e);
            } catch (IllegalAccessException e) {
                Log.wtf(TAG, e);
            }
            return null;
        }

        @Override
        public Object instantiateItem(View container, int position) {
            FragmentTransaction fragmentTransaction = fragmentManager
                    .beginTransaction();
            Fragment f = getItem(position);
            fragmentTransaction.add(container.getId(), f);
            fragmentTransaction.commit();
            return f;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        BaseActivity.addGlobalMenu(this, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return BaseActivity.handleGlobalMenu(this, item);
    }

}

Код фрагмента, который должен иметь свои собственные пункты меню:

public class SubscriptionGridFragment extends Fragment {

    private GridView subscriptionList;
    private SubscriptionListAdapter adapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    // ...

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.subscription_list, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // ...
    }
}

Ответы [ 3 ]

1 голос
/ 24 августа 2012

Нашел это в примере проекта Android. В операции фрагмента onCreate должен проверить, сохранен ли сохраненныйInstanceState, как это:

    setContentView(R.layout.custom_detail_fragment);

    if (savedInstanceState != null) {
        return;
    }

    CDFrag = new CustomDetailFragment();
    getSupportFragmentManager().beginTransaction().add(R.id.custom_detail_fragment_container, CDFrag).commit();

Ключ этой части:

    if (savedInstanceState != null) {
        return;
    }

Я также получал дубликаты на панели действий, когда я поворачивался и после добавления этой проверки дублирование прекращалось.

1 голос
/ 23 февраля 2013

У меня была такая же проблема.

Моя ошибка была в том, что я создал новый Viewpager в oncreate и установил его как id

viewpager.setId(viewpager.hashcode());
setContentView(viewpager);

Но это была большая ошибка, потому что после изменения ориентацииFragmentPagerAdapter пытается повторно использовать старые фрагменты.Он просматривает в FragmentManager фрагмент с идентификатором, сгенерированным из идентификатора видовых пейджеров и позицией фрагментов.

public Object instantiateItem(ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }

        final long itemId = getItemId(position);

        // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);

Контейнер - это пейджер.1013 *

viewpager.setId(R.id.viewpager);
setContentView(viewpager);
0 голосов
/ 20 ноября 2011

Благодаря SimonVT из freenode / # android-dev: "protip: посмотрите, что на самом деле делает fragpageradapter, перед тем как переопределить instantiateItem"

Удаление этого метода решило всю проблему.

...