当前位置: 首页 > 知识库问答 >
问题:

不同菜单和常用工具栏的Viewpager不工作

姚俊材
2023-03-14

我的应用程序里有标签。每个标签是不同的片段和不同的菜单。下面是我正在使用的布局

    <?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);。我已经覆盖了每个片断中的函数onCreateOptionsMenu(),它首先有menu.clear();,然后调用它的超级构造函数,然后膨胀片断自己的菜单XML。但我得到的结果是这样的-

  • 假设有5个选项卡。第2和第3个选项卡中的viewpager由
  • 中的两个片段组成
  • 第一个选项卡没有菜单
  • 第二个选项卡有menu_2(仅用于第二个子片段)
  • 第三个选项卡仍然没有菜单
  • 第四个选项卡有menu_4(仅用于第一个子片段)
  • 第5个选项卡具有菜单_5
  • 最初,选项卡1应该没有菜单,这是正常的。然后直接移动到第三个选项卡,它显示menu_4,默认情况下不显示菜单。然后滑到第4个选项卡,它将显示正确的菜单_4,然后滑回第3个选项卡,它将不显示菜单(这是必需的)。
  • 选项卡5也会发生同样的情况。如果切换到第2个选项卡中的第2个子片段,则在第1个选项卡中观察到相同的行为。

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

那么如何避免这一点呢?

共有1个答案

孙德本
2023-03-14

我编写了一个小的测试应用程序来检查这种行为。

让我们通过示例看看,如果您的片段有什么问题(正如您在上面看到的,具有不同菜单的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>
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();
    }
}
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>
public class FragmentWithViewPager extends Fragment {
    PagerAdapter pagerAdapter;
    ViewPager viewPager;
}
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);
    }
}
 类似资料:
  • 这个章节,我们会创建状态栏、菜单和工具栏。菜单是一组位于菜单栏的命令。工具栏是应用的一些常用工具按钮。状态栏显示一些状态信息,通常在应用的底部。 主窗口 QMainWindow提供了主窗口的功能,使用它能创建一些简单的状态栏、工具栏和菜单栏。 主窗口是下面这些窗口的合称,所以教程在最下方。 状态栏 状态栏是用来显示应用的状态信息的组件。 #!/usr/bin/python3 # -*- codin

  • 这个章节,我们会创建状态栏、菜单和工具栏。菜单是一组位于菜单栏的命令。工具栏是应用的一些常用工具按钮。状态栏显示一些状态信息,通常在应用的底部。 主窗口 QMainWindow 提供了主窗口的功能,使用它能创建一些简单的状态栏、工具栏和菜单栏。 主窗口是下面这些窗口的合称,所以教程在最下方。 状态栏 状态栏是用来显示应用的状态信息的组件。 #!/usr/bin/python3 # -*- codi

  • 在这部分教程中,我们创建了一个状态栏、菜单栏和工具栏。菜单是位于菜单栏中的一组命令。工具栏有一些按钮和应用程序中的一些常用命令。状态栏显示状态信息,通常位于应用程序窗口的底部。 PyQt6 QMainWindow QMainWindow 类提供了主程序窗口。在这里可以创建一个具有状态栏、工具栏和菜单栏的经典应用程序框架。 PyQt6 状态栏 状态栏是显示状态信息的小部件。 # file: stat

  • 我有一个工具栏和一个导航抽屉。当我启动应用程序时,会创建工具栏和导航抽屉。当我单击导航抽屉中的项目时,它会启动新的片段并保留相同的工具栏。当我启动特定片段时,我基本上如何向工具栏添加菜单项,例如搜索、添加、编辑?我不希望在程序开始时使用它们,而是动态创建的。还有,我怎样才能点击这些按钮,让它们启动其他片段呢。我希望在一个片段中,与另一个片段中的编辑按钮相比,工具栏中的编辑按钮可以做特定的事情。谢谢

  • 我在中有一个可以膨胀的工具栏。我有一个名为的菜单,它会膨胀,只显示一个图标。 当用户单击打开片段时。我有另一个菜单,它有两个图标。 当我在片段中膨胀friends菜单时,它仍然显示菜单中的图标。 非常感谢您的任何建议,

  • 我有一个使用本教程创建的抽屉和滑动选项卡的项目。我正在使用支持库使材料设计可用于较老的android版本。我还使用了而不是。我有一个连接到工具栏菜单: 我已经找了好几个星期了,为了有效果。我做错什么了吗? 我如何才能有每个片段的特定菜单?我认为隐藏菜单项可能是更容易实现的选择,但如果你们有任何其他方法来实现,我将不胜感激。