web-dev-qa-db-fra.com

Gonfler AppBarLayout avec la barre d'outils + TabLayout

J'ai actuellement DrawerLayout dans mon fichier main.xml. Il existe une barre d'outils encapsulée dans un AppBarLayout, puis un simple LinearLayout pour échanger des fragments. 

L'un des fragments vers lesquels je navigue, je veux qu'il contienne un TabLayout pour un ViewPager de fragments. Actuellement, j'ai les deux dans le fichier de présentation du fragment, mais cela provoque l'apparition d'une ombre portée entre la barre d'outils et TabLayout, ce que je ne souhaite pas. Je ne souhaite pas non plus utiliser setElevation () car cela ne fonctionnera pas pour les périphériques antérieurs à Lollipop.

Une solution possible serait de gonfler AppBarLayout à partir de mon fragment, de sorte qu'il contienne à la fois la barre d'outils et les onglets. Cependant, je ne sais pas trop comment faire cela, donc toute aide serait la bienvenue. 

Voici mon fichier main.xml:

<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/drawerLayout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context="com.lumivote.lumivote.ui.MainActivity">

    <Android.support.design.widget.CoordinatorLayout
        Android:id="@+id/rootLayout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent">

        <Android.support.design.widget.AppBarLayout
            Android:id="@+id/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:background="?attr/colorPrimary"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

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

        <LinearLayout
            Android:id="@+id/flContent"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:orientation="vertical"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

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

    <Android.support.design.widget.NavigationView
        Android:id="@+id/navigation"
        Android:layout_width="wrap_content"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        app:headerLayout="@layout/nav_header"
        app:itemIconTint="#333"
        app:itemTextColor="#333"
        app:menu="@menu/navigation_drawer_items" />

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

Et voici le fichier xml de mon fragment:

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical"
    tools:context="com.alexdao.democracy.ui.candidate_tab.CandidateListFragment">

    <Android.support.design.widget.TabLayout
        Android:id="@+id/tabLayout"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:background="@color/myPrimaryColor"
        app:tabMode="fixed"
        app:tabGravity="fill"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

    <Android.support.v4.view.ViewPager
        Android:id="@+id/viewpager"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:background="@Android:color/white" />
</LinearLayout>
24
adao7000

Pour résoudre mon problème, j'ai fini par placer la barre d'outils, TabLayout et ViewPager dans MainActivity. 

main_activity.xml:

<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/drawerLayout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Android.support.design.widget.CoordinatorLayout
        Android:id="@+id/rootLayout"
        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:background="?attr/colorPrimary"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

            <Android.support.design.widget.TabLayout
                Android:id="@+id/tabLayout"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                app:tabMode="fixed"
                app:tabGravity="fill"
                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

            <Android.support.v4.view.ViewPager
                Android:id="@+id/viewpager"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:background="@Android:color/white" />
        </Android.support.design.widget.AppBarLayout>

        <RelativeLayout
            Android:id="@+id/flContent"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:orientation="vertical"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

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

    <Android.support.design.widget.NavigationView
        Android:id="@+id/navigation"
        Android:layout_width="wrap_content"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        app:headerLayout="@layout/nav_header"
        app:itemIconTint="#333"
        app:itemTextColor="#333"
        app:menu="@menu/navigation_drawer_items" />

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

Ensuite, dans tous mes fragments, je règle la visibilité du TabLayout et du ViewPager par programme dans onCreateView:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        TabLayout tabLayout = (TabLayout) getActivity().findViewById(R.id.tabLayout);
        tabLayout.setVisibility(View.GONE);
        ViewPager mViewPager = (ViewPager) getActivity().findViewById(R.id.viewpager);
        mViewPager.setVisibility(View.GONE);

        return inflater.inflate(R.layout.fragment_layout, container, false);
}

Bien sûr, dans le fragment avec des onglets, vous voudriez définir la visibilité sur View.VISIBLE au lieu de View.GONE.

2
adao7000

Vous pouvez avoir une barre d’outils séparée pour chaque fragment. Il est possible de définir la barre d’outils fragments comme barre d’activités. Exemple de code:

Toolbar toolbar = (Toolbar) v.findViewById(R.id.toolbar);
 ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);

Il devrait également être possible d’obtenir des titres, des icônes et d’autres éléments ..__ Avec ceux-ci, vous pouvez imiter les ombres portées sur les appareils pré-Lollipop, peu importe ce que vous portez dessus.

12
Sebastian Pakieła

J'ai modifié la solution donnée par bleeding182 et l'ai également utilisée pour AppBarLayout (pour résoudre le problème signalé par bopa ).

@Override
public void onAttach(Context context) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        getActivity().findViewById(R.id.appbar).setElevation(0);
    }
    super.onAttach(context);

}

@Override
public void onDetach() {
    super.onDetach();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        getActivity().findViewById(R.id.appbar).setElevation(R.dimen.toolbar_elevation);
    }
}

Ce que j'ai fait, c'est remplacer l'appel à getSupportActionBar () en attribuant un ID à mon AppBarLayout, puis en appelant findViewById (), puis en appelant setElevation sur son résultat. Testé sur l'API 23.

5
naman1901

J'ai eu un problème similaire où je voulais une TabLayout juste à l'intérieur d'un fragment.

Sans changer aucun autre code, vous pouvez résoudre ce problème en utilisant onAttach et onDetach dans votre fragment avec TabLayout.

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    // todo add some further checks, e.g. instanceof, actionbar != null

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        ((AppCompatActivity) activity).getSupportActionBar().setElevation(0);
    }
}

@Override
public void onDetach() {
    super.onDetach();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        ((AppCompatActivity) getActivity()).getSupportActionBar()
                .setElevation(getResources().getDimension(R.dimen.toolbar_elevation));
    }
}

Assurez-vous de définir la même élévation sur votre TabLayout et tout fonctionne bien! ;RÉ

4
David Medenjak

Vous pouvez simplement ajouter TabLayout par programmation à partir de Fragment dans lequel vous avez besoin de TabLayout. 

tabLayout = (TabLayout) inflater.inflate(R.layout.tablay, null);
appBarLayout = (AppBarLayout) getActivity().findViewById(R.id.appbar);
appBarLayout.addView(tabLayout, new LinearLayoutCompat.LayoutParams(
    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));

et supprimer TabLayout de AppBar dans onDetach ()

@Override
public void onDetach() {
    appBarLayout.removeView(tabLayout);
    super.onDetach();
}
3
Artem_Iens

La méthode Artem_lens a fonctionné pour moi avec quelques modifications.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    ...

    mTabLayout = (TabLayout) inflater.inflate(
            R.layout.partial_tab_layout,
            container,
            false);
    mAppBarLayout = (AppBarLayout) getActivity().findViewById(R.id.app_bar);
    mAppBarLayout.addView(mTabLayout,
            new LinearLayoutCompat.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT));

    ...
}

Et en enlevant la vue à onDestroyView()

@Override
public void onDestroyView() {
    mAppBarLayout.removeView(mTabLayout);
    super.onDestroyView();
}
1
Gnzlt

La solution est simple dans le XML. Ajoutez simplement le code suivant à votre AppBarLayout: app:elevation="0dp". Donc, AppBarLayout devrait ressembler à ceci:

<Android.support.design.widget.AppBarLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    app:elevation="0dp"
    Android:theme="@style/AppTheme.AppBarOverlay">
0
josecdeveloper