如何处理每个片段都有工具栏时的抽屉切换和工具栏返回按钮

12

我在我的应用程序中采用单个活动和多个片段的方法

由于在我的某些片段中,工具栏中有自定义视图,因此我决定为每个片段使用单独的工具栏。

如何为每个片段实现单独的工具栏,而抽屉布局则在我的活动中 主页 类别页面


你找到任何解决方案了吗? - Mitesh Vanaliya
没有找到任何解决方案 - alphanso
6个回答

4

我有同样的问题,我将为每个片段添加自定义工具栏视图。

我的实用方法是:

public static View addRemoveViewFromToolbar(FragmentActivity fragmentActivity, int resourceId) {
    Toolbar toolbar = removeViewFromToolbar(fragmentActivity);
    if (resourceId == 0) {
        return null;
    } else {
        View view = LayoutInflater.from(fragmentActivity).inflate(resourceId, toolbar, false);
        toolbar.addView(view);
        return view;
    }
}


public static Toolbar removeViewFromToolbar(FragmentActivity fragmentActivity) {
    Toolbar toolbar = (Toolbar) fragmentActivity.findViewById(R.id.toolbar);
    if (toolbar.getChildCount() > 1) {
        for (int i = 1; i <= toolbar.getChildCount(); i++) {
            toolbar.removeViewAt(1);
        }
    }
    return toolbar;
}

在我的每个片段中
//Create your custom view based on requirement
    View view = Utility.addRemoveViewFromToolbar(getActivity(), R.layout.toolbar_search_view);
        if (view != null) {
            edtCategory1 = (EditText) view.findViewById(R.id.edtCategory1);
            edtCategory1.setOnClickListener(this);
        }

希望这个解释对你有帮助 :)

0
我建议最简单的方法是使用回调到活动。每当每个片段在活动中加载时,安排一个回调到活动并在活动中加载适当的工具栏。
在您的布局文件夹中有单独的工具栏xml。使用include标记将工具栏放入活动中。一次只保留一个工具栏可见。当片段回调到您的活动时,使必要的工具栏可见。

0

我不确定我是否正确理解了您对应用程序的描述,但最近我做了我认为您所描述的事情。 我的活动布局是一个带有包含单个工具栏和下方FrameLayout的CoordinatorLayout/AppBar布局的DrawerLayout。menu.xml包含了我在所有片段中需要的工具栏项目。在导航菜单中点击的项目将在FrameLayout中交换片段。我的onNavigationItemSelected()调用此方法来交换片段并处理后退堆栈:

 public void switchView(int id, int optArg) {
   if (currentView != id) {
     currentView = id; //currentView keeps track of which fragment is loaded
     FragmentTransaction transaction = getFragmentManager().beginTransaction();
     //Fragment contentFragment is the current fragment in the FrameLayout
     switch (id) {
       case 0: //menu item 1
         contentFragment = new Nav_Item1_Fragment();
         transaction.replace(R.id.fragment_container, contentFragment, "");
         break;
       case 1: //menu item 2
         contentFragment = new Nav_Item2_Fragment();
         transaction.replace(R.id.fragment_container, contentFragment, "");
         break;
       case 2: //menu item 3
         contentFragment = new Nav_Item3_Fragment();
         transaction.replace(R.id.fragment_container, contentFragment, "");
       break;
     }
     // Replace whatever is in the fragment_container view with this fragment,
     // and add the transaction to the back stack
     // transaction.replace(R.id.fragment_container, contentFragment);
     transaction.addToBackStack(null);
     // Commit the transaction
     transaction.commit();
   }
 }

在每个片段的onPrepareOptionsMenu()中,我setVisible()来隐藏/显示与该片段相关的工具栏菜单项。每个菜单项都有一个方法,在活动中指向菜单项的onClick属性,该方法知道它来自哪个片段以及传递给它的视图是什么。
抽屉在活动的onCreate()中设置,使用ActionBarDrawerToggle完成:
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
        this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();

活动 XML:

<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    ...>

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        .../>

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

app_bar_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    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.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:gravity="top"
            .../>

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

    <FrameLayout
        android:id="@+id/fragment_container"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
    </FrameLayout>

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

所以...一个导航菜单,一个应用程序/工具栏,多个片段


不,这不是我想要的。我想为每个片段添加工具栏,并同时处理抽屉开关。 - alphanso

0
为什么你特别想要每个片段都有单独的工具栏?你可以轻松地为每个片段更改工具栏视图。
在你切换片段的函数中 -
public void selectDrawerItem(MenuItem item) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction;
        switch (item.getItemId()) {

                    case R.id.nav_home :
                        getSupportActionBar().setCustomView(R.layout.home_nav_bar);
                        fragmentClass = HomeFragment.class;
                        break;
                    case R.id.nav_settings :
                        getSupportActionBar().setCustomView(R.layout.settings_nav_bar);
                        fragmentClass = SettingsFragment.class;
                        break;

        }
        fragment = (Fragment) fragmentClass.newInstance();
        fragmentManager.popBackStack(null, 
        FragmentManager.POP_BACK_STACK_INCLUSIVE);

        fragmentTransaction = fragmentManager.beginTransaction();
                fragmentTransaction.replace(R.id.fragment_container, fragment);
                fragmentTransaction.addToBackStack(null);
                fragmentTransaction.commit();
}

因此,您可以轻松地使用相同的工具栏,并根据每个片段的要求进行自定义。


我想为每个片段使用单独的工具栏,请再读一遍问题。 - alphanso
请问您为什么想要使用单独的工具栏?使用自定义视图就像使用单独的工具栏。如果您仍然坚持要使用单独的工具栏,我能想到的唯一选择是创建多个ActionBarDrawerToggle实例,并将其与您想要的工具栏实例配对,例如 - ActionBarDrawerToggle toggle1 = new ActionBarDrawerToggle( this, drawerLayout, toolbar1, R.string.navigation_open, R.string.navigation_close); 然后在加载所需的片段之前,执行 drawerLayout.addDrawerListener(toggle1); 这还没有经过测试。所以如果可以,请告诉我它是否有效。 - user3911483

0

这可以用一种非常直接的方式完成。

  1. 首先创建一个带有 drawerlayout 的活动。

  2. 其次,在活动中创建一个容器 viewpager 来容纳 fragments

  3. 第三,在您的 viewpager 上实现一个监听器,它将根据当前显示的 fragment 设置相关的 toolbar

让我通过相关的 XML 和代码来说明。

首先是主活动的 Drawerlayout XML。

    <?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"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:openDrawer="start">
<include
    layout="@layout/app_bar_landing_page"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:headerLayout="@layout/nav_header_landing_page"
    app:menu="@menu/activity_landing_page_drawer" />

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

请注意容器布局app_bar_landing_page。现在这个XML的内容是:
 <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="me.veganbuddy.veganbuddy.ui.LandingPage">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:elevation="4dp"
            app:logo="@drawable/vegan_buddy_menu_icon"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

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

    <android.support.v4.view.ViewPager
        android:id="@+id/container_for_fragments"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>

请注意viewpager,它将作为片段的容器。现在是viewpager上的OnPageChangeListener
mViewPager = (ViewPager) findViewById(R.id.container_for_fragments);
    mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            switch (position+1){
                case 0:setSupportActionBar(aToolbar);
                    break;
                case 1:setSupportActionBar(bToolbar);
                    break;
                case 2:setSupportActionBar(cToolbar);;
                    break;
                case 3:setSupportActionBar(dToolbar);
                    break;
                default:
                    break;
            }
        }

如果需要进一步的澄清,请告诉我。


0

非常简单。除了类别片段的 onclick 操作将带您进入新的活动,而不是片段。现在,由于抽屉布局位于具有导航视图且没有 toolbar 的父活动中,因此第一个抽屉片段是具有四个选项卡和 viewpager 以及顶部的 toolbartablayout,并且在其中一个选项卡即 HOME 中包含 TOP CHARTS、CATEGORIES 和 EDITORS。每个 toolbar 必须在每个片段布局中实现,而不是在活动布局中,因为您想要每个片段的不同工具栏。请注意,Toolbar 不是 Fragment 的属性,而是 ActionBarActivityAppCompatActivity 的属性,然后在持有 HOME、GAMES、MOVIES、MUSIC 的片段的 onCreateView 中放下这些代码。

    public class Drawer1Fragment extends Fragment{
    public Drawer1Fragment () {}
    TabLayout tabLayout;
    Toolbar toolbar;
    DrawerLayout drawerLayout;
        ViewPager viewPager;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        View myChildRoot = inflater.inflate(R.layout.child_fragment_attachment, container, false);
        tabLayout = myChildRoot.findViewById(R.id.tab_layout);
        viewPager= myChildRoot.findViewById(R.id.container_viewPager);
        toolbar = myChildRoot.findViewById(R.id.toolbar);
        drawerLayout = getActivity().findViewById(R.id.drawer_layout);
        ((AppCompatActivity)requireActivity()).setSupportActionBar(toolbar);
        ((AppCompatActivity)requireActivity()).getSupportActionBar().setTitle(getActivity().getResources().getString(R.string.app_name));
        ((AppCompatActivity)requireActivity()).getSupportActionBar().setHomeButtonEnabled(true);
        ((AppCompatActivity)getParentFragment().requireActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(getActivity(),drawerLayout,toolbar,R.drawable.icons,R.string.app_name);
        drawerLayout.addDrawerListener(toggle);
        toggle.syncState();
// The back arrow of a toolbar in fragment is implemented below
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view)
            {
                if(!drawerLayout.isDrawerOpen(GravityCompat.START)) {
                    drawerLayout.openDrawer(GravityCompat.START);
                } else {
                    getActivity().finish();
                }
            }
        });
        
        return myChildRoot;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接