android – Viewpager具有不同的菜单和常用工具栏无法正常工作

我的应用程序中有标签.每个标签都有不同的片段,并有不同的菜单.下面是我正在使用的布局

    <?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/background">

            <include
                layout="@layout/toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_scrollFlags="scroll|enteralways" />


        </android.support.design.widget.AppBarLayout>

        <com.CustomViewPager
            android:id="@+id/view_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="end"
            android:background="@color/background"
            app:layout_anchor="@id/view_pager"
            app:layout_anchorGravity="bottom|center_horizontal"
            app:layout_behavior="com.widget.ScrollTabBehavior"
            app:tabBackground="@color/background"
            app:tabIndicatorColor="@color/toolbar"
            app:tabIndicatorHeight="0dp"
            app:tabMode="fixed"
            app:tabPaddingEnd="0dp"
            app:tabPaddingStart="0dp" />

    </android.support.design.widget.CoordinatorLayout>

    <RelativeLayout
        android:id="@+id/left_drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:layout_marginLeft="-64dp"
        android:layout_marginStart="-64dp"
        android:background="@color/toolbar"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp">

        <ImageButton
            android:id="@+id/close_btn"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:background="@android:color/transparent"
            android:padding="5dp"
            android:src="@drawable/close_icon" />

        <view
            android:id="@+id/drawerlist"
            class="android.support.v7.widget.RecyclerView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/close_btn" />

    </RelativeLayout>
</android.support.v4.widget.DrawerLayout>

现在,onCreate()中的每个片段都提到了setHasOptionsMenu(true);更多.我已经在每个包含menu.clear()的片段中覆盖了onCreateOptionsMenu()函数.首先调用它的超级构造函数然后膨胀片段自己的菜单xml.但我得到的结果是这样的 –

>假设有5个标签.第二个和第三个选项卡中的viewpager每个包含两个以内的片段
>第一个标签没有菜单
>第二个选项卡有menu_2(仅适用于第二个子片段)
>第三个标签再次没有菜单
>第4个选项卡有menu_4(仅适用于第一个子片段)
>第五个标签有menu_5
>最初,选项卡1应该没有菜单可以.然后直接移动到第三个选项卡,它显示menu_4,认情况下不显示菜单.然后滑动到选项卡4,它将显示正确的menu_4然后滑回第3个选项卡,它将显示没有菜单(这是必需的).
>对于选项卡5也会发生同样的情况.如果我在第二个选项卡中切换到第二个子片段,则第一个选项卡会出现相同的行为.

简而言之,根据我的观察,它显示了相邻标签菜单,它实际上是在当前片段之后执行的,因此正在发生这种行为.

那么如何避免这种情况呢?

解决方法:

我写了一个小测试应用程序来检查行为.

enter image description here

让我们看看样本,看看你的片段是否有问题(如上所示,ViewPager与不同的菜单就像魅力一样)

活动的XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_below="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

活动类.每次ViewPager都有PageSelected事件时,重要的部分是invalidateOptionsMenu().然后,我们将setHasOptionsMenu设置为所有片段和子片段(从嵌套的ViewPagers)到false,如果它们在屏幕外.

public class MainActivity extends AppCompatActivity {

    PagerAdapter pagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Fragment[] fragments = {
                Fragment.instantiate(this, FragmentNoMenu.class.getName()),
                Fragment.instantiate(this, FragmentA.class.getName()),
                Fragment.instantiate(this, FragmentNoMenu.class.getName()),
                Fragment.instantiate(this, FragmentB.class.getName()),
        };

        TabLayout tabLayout = (TabLayout)findViewById(R.id.tabLayout);
        ViewPager viewPager = (ViewPager)findViewById(R.id.viewPager);
        pagerAdapter = new PagerAdapter(getSupportFragmentManager(), fragments);
        viewPager.setAdapter(pagerAdapter);
        viewPager.setoffscreenPageLimit(0);
        viewPager.addOnPagechangelistener(new ViewPager.OnPagechangelistener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
            @Override
            public void onPageSelected(int position) {
                invalidateOptionsMenu(position);
            }
            @Override
            public void onPageScrollStateChanged(int state) {}
        });

        invalidateOptionsMenu(0);
        tabLayout.setupWithViewPager(viewPager);
    }

    private void invalidateOptionsMenu(int position) {
        for(int i = 0; i < pagerAdapter.getCount(); i++) {
            Fragment fragment = pagerAdapter.getItem(i);
            fragment.setHasOptionsMenu(i == position);

            if (fragment instanceof FragmentWithViewPager) {
                FragmentWithViewPager fragmentWithViewPager = (FragmentWithViewPager)fragment;
                if (fragmentWithViewPager.pagerAdapter != null) {
                    for (int j = 0; j < fragmentWithViewPager.pagerAdapter.getCount(); j++) {
                        fragmentWithViewPager.pagerAdapter.getItem(j).setHasOptionsMenu(i == position);
                    }
                }
            }
        }

        invalidateOptionsMenu();
    }
}

PagerAdapter类:

public class PagerAdapter extends FragmentPagerAdapter {

    private final Fragment[] fragments;

    public PagerAdapter(FragmentManager fragmentManager, Fragment[] fragments) {
        super(fragmentManager);
        this.fragments = fragments;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return fragments[position].getClass().getSimpleName();
    }

    @Override
    public Fragment getItem(int position) {
        return fragments[position];
    }

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

这是我使用的测试片段:

FragmentNoMenu类:

public class FragmentNoMenu extends android.support.v4.app.Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_no_menu, container, false);
    }
}

FragmentNoMenu布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="#0F0F50"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

FragmentA类是一个嵌套ViewPager的片段:

public class FragmentA extends FragmentWithViewPager {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_a, container, false);

        Fragment[] fragments = {
                Fragment.instantiate(getContext(), SubFragmentA.class.getName()),
                Fragment.instantiate(getContext(), SubFragmentB.class.getName()),
                Fragment.instantiate(getContext(), SubFragmentC.class.getName()),
        };

        if (pagerAdapter == null) {
            pagerAdapter = new PagerAdapter(getChildFragmentManager(), fragments);
        }

        viewPager = (ViewPager)rootView.findViewById(R.id.viewPager);
        viewPager.setAdapter(pagerAdapter);
        return rootView;
    }

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

FragmentA的布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="#B0B0B0"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_marginTop="80dp"
        android:layout_width="match_parent"
        android:layout_height="200dp"/>
</FrameLayout>

FragmentA的菜单

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_item_1"
        android:title="Item 1"
        android:orderInCategory="250"
        app:showAsAction="never" />

    <item
        android:id="@+id/action_item_2"
        android:title="Item 2"
        android:orderInCategory="300"
        app:showAsAction="never" />
</menu>

NB! FragmentA扩展了FragmentWithViewPager – 它是Fragment的一个小扩展,可以更容易地将片段与MainActivity中的嵌套片段区分开来:

public class FragmentWithViewPager extends Fragment {
    PagerAdapter pagerAdapter;
    ViewPager viewPager;
}

FragmentB:

public class FragmentB extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_b, container, false);
    }

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

这是布局&菜单

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="#999999"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

.....

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_item3"
        android:title="Item 3"
        android:icon="@drawable/ic_triage_star"
        android:orderInCategory="250"
        app:showAsAction="always" />
</menu>

子片段(从代码角度看它们看起来都一样):

布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="#AA0000"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="SubFragment C (with icon Menu)"
        android:textSize="24sp"
        android:textColor="#00BB00"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout>

码:

public class SubFragmentB extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.subfragment_b, container, false);
    }
}

而已!我已将项目上传到我的DropBoxfeel free to check it out

我希望,这有帮助

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...