Viewpager with different menu and common toolbar not working(具有不同菜单和常用工具栏的 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">让我们看一下示例,看看您的片段是否有问题(如上所示,具有不同菜单的 ViewPager 就像魅力一样)
Activity
的 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">
Activity
类.重要的部分是 invalidateOptionsMenu()
每次 ViewPager
有 PageSelected 事件.然后,我们将 setHasOptionsMenu
设置为所有片段,并将 subfragments(来自嵌套的 ViewPager
s)设置为 false
屏幕.
公共类 MainActivity 扩展 AppCompatActivity {分页适配器分页适配器;@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);片段 [] 片段 = {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(), 片段);viewPager.setAdapter(pagerAdapter);viewPager.setOffscreenPageLimit(0);viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {@覆盖public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@覆盖公共无效 onPageSelected(int position) {无效选项菜单(位置);}@覆盖公共无效 onPageScrollStateChanged(int state) {}});无效选项菜单(0);tabLayout.setupWithViewPager(viewPager);}私人无效invalidateOptionsMenu(int位置){for(int i = 0; i < pagerAdapter.getCount(); i++) {片段片段 = pagerAdapter.getItem(i);fragment.setHasOptionsMenu(i == 位置);如果(片段实例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);}}}}无效选项菜单();}}
PagerAdapter
类:
公共类 PagerAdapter 扩展 FragmentPagerAdapter {私有最终片段 [] 片段;公共 PagerAdapter(FragmentManager fragmentManager, Fragment[] 片段) {超级(片段管理器);this.fragments = 片段;}@覆盖公共 CharSequence getPageTitle(int position) {返回片段[位置].getClass().getSimpleName();}@覆盖公共片段getItem(int位置){返回片段[位置];}@覆盖公共 int getCount() {返回片段.长度;}}
这是我使用的测试片段:
FragmentNoMenu
类:
public class FragmentNoMenu 扩展 android.support.v4.app.Fragment {@Nullable@覆盖public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup 容器, @Nullable Bundle savedInstanceState) {返回inflater.inflate(R.layout.fragment_no_menu,容器,假);}}
FragmentNoMenu
布局:
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"安卓:背景=#0F0F50"android:layout_width="match_parent"android:layout_height="match_parent"/>
FragmentA
类是一个带有嵌套 ViewPager 的 Fragment:
公共类 FragmentA 扩展 FragmentWithViewPager {@Nullable@覆盖public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup 容器, @Nullable Bundle savedInstanceState) {查看 rootView = inflater.inflate(R.layout.fragment_a, container, false);片段 [] 片段 = {Fragment.instantiate(getContext(), SubFragmentA.class.getName()),Fragment.instantiate(getContext(), SubFragmentB.class.getName()),Fragment.instantiate(getContext(), SubFragmentC.class.getName()),};如果(pagerAdapter == null){pagerAdapter = new PagerAdapter(getChildFragmentManager(), 片段);}viewPager = (ViewPager)rootView.findViewById(R.id.viewPager);viewPager.setAdapter(pagerAdapter);返回根视图;}@覆盖public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {inflater.inflate(R.menu.fragment_a,菜单);super.onCreateOptionsMenu(menu, inflater);}}
FragmentA
的布局:
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"安卓:背景=#B0B0B0"android:layout_width="match_parent"android:layout_height="match_parent">
FragmentA
的菜单:
<?xml version="1.0" encoding="utf-8"?><菜单 xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"><项目android:id="@+id/action_item_1"android:title="项目 1"机器人:orderInCategory="250"应用程序:showAsAction="从不"/><项目android:id="@+id/action_item_2"android:title="项目 2"机器人:orderInCategory="300"应用程序:showAsAction="从不"/></菜单>
注意!FragmentA
扩展了 FragmentWithViewPager
- 它是 Fragment
的一个小扩展,以便更容易在 MainActivity 中区分带有嵌套片段的片段:
公共类 FragmentWithViewPager 扩展 Fragment {分页适配器分页适配器;视图页面视图页面;}
片段B
:
公共类 FragmentB 扩展 Fragment {@Nullable@覆盖public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup 容器, @Nullable Bundle savedInstanceState) {返回inflater.inflate(R.layout.fragment_b,容器,假);}@覆盖public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {inflater.inflate(R.menu.fragment_b,菜单);super.onCreateOptionsMenu(menu, inflater);}}
这是布局&菜单:
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"安卓:背景=#999999"android:layout_width="match_parent"android:layout_height="match_parent"/>......<?xml 版本="1.0" 编码="utf-8"?><菜单 xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"><项目android:id="@+id/action_item3"android:title="第 3 项"android:icon="@drawable/ic_triage_star"机器人:orderInCategory="250"应用程序:showAsAction="总是"/></菜单>
子片段(从代码的角度来看,它们看起来都一样):
布局:
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"安卓:背景=#AA0000"android:layout_width="match_parent"android:layout_height="match_parent"><文本视图android:text="SubFragment C (带图标菜单)"安卓:textSize="24sp"安卓:textColor="#00BB00"机器人:重力=中心"android:layout_width="match_parent"android:layout_height="match_parent"/></框架布局>
代码:
公共类 SubFragmentB 扩展 Fragment {@Nullable@覆盖public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup 容器, @Nullable Bundle savedInstanceState) {返回inflater.inflate(R.layout.subfragment_b,容器,假);}}
就是这样!我已将项目上传到我的保管箱 - 随时查看!
希望对你有帮助
I have tabs in my app. Each tab is of different fragments and has different menu. Below is the layout which I am using
<?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>
Now with every Fragment in onCreate()
I have mentioned setHasOptionsMenu(true);
further more. I have overriden the function onCreateOptionsMenu()
in each fragment which has menu.clear();
at first then calling it's super constructor then inflating fragment's own menu xml. But result I am getting is something like this -
- Suppose there are 5 tabs. 2nd and 3rd tab has viewpager within each consist of two more fragments within
- 1st tab has no menu
- 2nd tab has menu_2 (only for 2nd child fragment)
- 3rd tab again has no menu
- 4th tab has menu_4 (only for 1st child fragment)
- 5th tab has menu_5
- Initially, there should be no menu for tab 1 which is ok. Then moving to 3rd tab directly it shows menu_4 which by default should show no menu. Then sliding to tab 4, it will show proper menu_4 then sliding back to 3rd tab it will show no menu (which is as required).
- This same thing happens for tab 5. If I am switching to 2nd child fragment within 2nd tab then the same behavior is observed with 1st tab.
In short, according to my observation it is showing the menu of adjacent tabs which is actually getting executed after the current fragment and therefore such behavior is occurring.
So how to avoid this?
解决方案 I have written small test-application to check the behaviour.
Let's go through the sample and see, if something wrong with your fragments (as you see above, ViewPager with different menus works like a charm)
Activity
's 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>
Activity
class. Important part is invalidateOptionsMenu()
every time ViewPager
has PageSelected event. Then, we setting setHasOptionsMenu
to all fragments and subfragments(from the nested ViewPager
s) to false
if they out of screen.
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
class:
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;
}
}
Here're my test fragments I used:
FragmentNoMenu
class:
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
layout:
<?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
class is a Fragment with nested 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
's layout:
<?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
's menu:
<?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
extends FragmentWithViewPager
- it's a small extension of Fragment
to make it easier to distinguish Fragments with nested fragments in 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);
}
}
It's layout & menu:
<?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>
Subfragments (they are all look the same from the code perspective):
Layouts:
<?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>
Code:
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);
}
}
That's it! I've uploaded the project to my dropbox - feel free to check it out!
I hope, it helps
这篇关于具有不同菜单和常用工具栏的 Viewpager 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:具有不同菜单和常用工具栏的 Viewpager 不起作用
基础教程推荐
- 如何在 iPhone 上显示来自 API 的 HTML 文本? 2022-01-01
- android 应用程序已发布,但在 google play 中找不到 2022-01-01
- UIWebView 委托方法 shouldStartLoadWithRequest:在 WKWebView 中等效? 2022-01-01
- 在 gmail 中为 ios 应用程序检索朋友的朋友 2022-01-01
- 如何在 UIImageView 中异步加载图像? 2022-01-01
- Android:对话框关闭而不调用关闭 2022-01-01
- 当从同一个组件调用时,两个 IBAction 触发的顺序是什么? 2022-01-01
- 如何在没有IB的情况下将2个按钮添加到右侧的UINavigationbar? 2022-01-01
- 如何让对象对 Cocos2D 中的触摸做出反应? 2022-01-01
- Kivy Buildozer 无法构建 apk,命令失败:./distribute.sh -m “kivy"d 2022-01-01