web-dev-qa-db-fra.com

Whatsapp comme Collapsing Toolbar

Dans mon application, je voudrais implémenter la page d'accueil de Whatsapp comme une barre d'outils pliable. Autrement dit, tout en faisant défiler la liste, la barre d'outils doit monter et les onglets doivent épingler en haut. Comment puis-je atteindre cet objectif?

Voici ma disposition dans la barre d'application

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

        <Android.support.design.widget.CollapsingToolbarLayout
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:id="@+id/collapsibleToolBarLayout"
            Android:fitsSystemWindows="true"
            app:titleEnabled="false"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">                 

            <Android.support.design.widget.TabLayout
                Android:id="@+id/tabs"
                Android:layout_width="match_parent"
                Android:layout_height="50dp"
                Android:background="@color/white"
                app:tabTextColor="@color/product_page_btn_grey"
                app:tabSelectedTextColor="@color/upcomer_background_red"
                app:tabIndicatorColor="@color/upcomer_background_red"
                Android:layout_gravity="bottom"
                app:layout_scrollFlags="scroll|enterAlways"
                app:tabContentStart="72dp" />

            <Android.support.v7.widget.Toolbar
                Android:id="@+id/toolbar"
                Android:layout_width="match_parent"
                Android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.9"
                Android:background="@color/upcomer_background_red"
                app:popupTheme="@style/AppTheme.PopupOverlay" >

                <ImageView
                    Android:layout_width="wrap_content"
                    Android:layout_height="wrap_content"
                    Android:id="@+id/title_image_view"
                    Android:contentDescription="@null"
                    Android:layout_gravity="start|center_vertical"
                    Android:visibility="gone"
                    Android:src="@drawable/title"/>

                <RelativeLayout
                    Android:layout_width="match_parent"
                    Android:layout_height="match_parent"
                    Android:id="@+id/title_layout"
                    Android:visibility="gone">

                    <TextView
                        Android:layout_width="wrap_content"
                        Android:layout_height="wrap_content"
                        Android:layout_centerVertical="true"
                        Android:id="@+id/toolbarText"
                        style="@Android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title"/>

                    <TextView
                        Android:layout_width="wrap_content"
                        Android:layout_height="wrap_content"
                        Android:id="@+id/send_button"
                        Android:layout_marginRight="10dp"
                        Android:layout_marginEnd="10dp"
                        Android:text="@string/send_text"
                        Android:textColor="@color/white"
                        Android:textSize="18sp"
                        Android:textStyle="bold"
                        Android:visibility="gone"
                        Android:layout_centerVertical="true"
                        Android:layout_alignParentRight="true"
                        Android:layout_alignParentEnd="true"/>

                </RelativeLayout>

                </Android.support.v7.widget.Toolbar>

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



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

Maintenant, le TabLayout n'est pas visible et la barre d'outils reste là même si la liste dans le pager de vue ci-dessous défile. Aide aimablement.

14
Jayakrishnan Salim

Pour obtenir cette fonctionnalité, un CollapsingToolbarLayout n'est en fait pas nécessaire, vous pouvez simplement réduire la barre d'outils définie comme ActionBar.

Voici un exemple de code utilisant une barre d'outils pour l'ActionBar qui se réduira et un TabLayout avec un ViewPager.

Assurez-vous d'abord que le style utilisé pour MainActivity est celui qui n'a pas d'ActionBar, par exemple:

<style name="AppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
    <!-- ....... -->
</style>

MainActivity.Java , qui a le FragmentPagerAdapter et configure les onglets:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // Get the ViewPager and set it's PagerAdapter so that it can display items
        ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
        PagerAdapter pagerAdapter =
                new PagerAdapter(getSupportFragmentManager(), MainActivity.this);
        viewPager.setAdapter(pagerAdapter);

        // Give the TabLayout the ViewPager
        TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        tabLayout.setupWithViewPager(viewPager);

        // Iterate over all tabs and set the custom view
        for (int i = 0; i < tabLayout.getTabCount(); i++) {
            TabLayout.Tab tab = tabLayout.getTabAt(i);
            tab.setCustomView(pagerAdapter.getTabView(i));
        }

    }


    @Override
    public void onResume() {
        super.onResume();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    class PagerAdapter extends FragmentPagerAdapter {

        String tabTitles[] = new String[] { "Tab One", "Tab Two", "Tab Three" };
        Context context;

        public PagerAdapter(FragmentManager fm, Context context) {
            super(fm);
            this.context = context;
        }

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

        @Override
        public Fragment getItem(int position) {

            switch (position) {
                case 0:
                    return new BlankFragment();
                case 1:
                    return new BlankFragment();
                case 2:
                    return new BlankFragment();
            }

            return null;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            // Generate title based on item position
            return tabTitles[position];
        }

        public View getTabView(int position) {
            View tab = LayoutInflater.from(MainActivity.this).inflate(R.layout.custom_tab, null);
            TextView tv = (TextView) tab.findViewById(R.id.custom_text);
            tv.setText(tabTitles[position]);
            return tab;
        }

    }
}

activity_main.xml

Les parties importantes:

  • Utiliser un coordinateur
  • Utilisez app:layout_scrollFlags="scroll|enterAlways|snap" Dans les propriétés de la barre d'outils
  • Utilisez app:layout_behavior="@string/appbar_scrolling_view_behavior" Dans les propriétés de ViewPager

Voici le fichier activity_main.xml :

<Android.support.design.widget.CoordinatorLayout
    Android:id="@+id/main_layout"
    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=".MainActivity">


    <Android.support.design.widget.AppBarLayout
        Android:id="@+id/appBarLayout"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        app:elevation="6dp">
    <Android.support.v7.widget.Toolbar
        Android:id="@+id/toolbar"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_alignParentTop="true"
        Android:background="?attr/colorPrimary"
        Android:minHeight="?attr/actionBarSize"
        Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:elevation="0dp"
        app:layout_scrollFlags="scroll|enterAlways|snap"
        />

    <Android.support.design.widget.TabLayout
        Android:id="@+id/tab_layout"
        app:tabMode="fixed"
        Android:layout_below="@+id/toolbar"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:background="?attr/colorPrimary"
        app:elevation="0dp"
        app:tabTextColor="#d3d3d3"
        app:tabSelectedTextColor="#ffffff"
        app:tabIndicatorColor="#ff00ff"
        Android:minHeight="?attr/actionBarSize"
        />

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

    <Android.support.v4.view.ViewPager
        Android:id="@+id/viewpager"
        Android:layout_below="@+id/tab_layout"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        />

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

custom_tab.xml :

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:orientation="vertical" Android:layout_width="match_parent"
    Android:layout_height="match_parent">
    <TextView
        Android:id="@+id/custom_text"
        Android:layout_width="wrap_content"
        Android:layout_height="match_parent"
        Android:background="?attr/selectableItemBackground"
        Android:gravity="center"
        Android:textSize="16dip"
        Android:textColor="#ffffff"
        Android:singleLine="true"
        />
</LinearLayout>

BlankFragment.Java , cela ajoute simplement suffisamment d'éléments pour le faire défiler:

import Android.support.v4.app.Fragment;
import Android.support.v7.widget.LinearLayoutManager;
import Android.support.v7.widget.RecyclerView;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;;

public class BlankFragment extends Fragment {

    public BlankFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_blank, container, false);

        RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.rv_recycler_view);
        rv.setHasFixedSize(true);
        MyAdapter adapter = new MyAdapter(new String[]{"test one", "test two", "test three", "test four", "test five" , "test six" , "test seven", "test eight" , "test nine"});
        rv.setAdapter(adapter);

        LinearLayoutManager llm = new LinearLayoutManager(getActivity());
        rv.setLayoutManager(llm);

        return rootView;
    }

}

fragment_blank.xml , il est important d'utiliser un RecyclerView ou tout autre affichage prenant en charge le défilement imbriqué, tel qu'un NestedScrollView

(note latérale: vous pouvez appeler setNestedScrollingEnabled(true) sur api-21 et plus pour le faire fonctionner avec un ListView):

<?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.v7.widget.SearchView
        Android:id="@+id/sv_search"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:hint="Search!"
        Android:singleLine="true"
        Android:inputType="textNoSuggestions"
        Android:layout_gravity="start"
        Android:layout_marginRight="18dp"
        Android:ems="10" >
    </Android.support.v7.widget.SearchView>

    <Android.support.v7.widget.RecyclerView
        Android:id="@+id/rv_recycler_view"
        Android:layout_below="@+id/sv_search"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent" >
    </Android.support.v7.widget.RecyclerView>
</RelativeLayout>

MyAdapter.Java , l'adaptateur RecyclerView:

import Android.support.v7.widget.CardView;
import Android.support.v7.widget.RecyclerView;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.TextView;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    private String[] mDataset;

    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    public static class MyViewHolder extends RecyclerView.ViewHolder {
        public CardView mCardView;
        public TextView mTextView;
        public MyViewHolder(View v) {
            super(v);

            mCardView = (CardView) v.findViewById(R.id.card_view);
            mTextView = (TextView) v.findViewById(R.id.tv_text);
        }
    }

    // Provide a suitable constructor (depends on the kind of dataset)
    public MyAdapter(String[] myDataset) {
        mDataset = myDataset;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
                                                     int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.card_item, parent, false);
        // set the view's size, margins, paddings and layout parameters
        MyViewHolder vh = new MyViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.mTextView.setText(mDataset[position]);
    }

    @Override
    public int getItemCount() {
        return mDataset.length;
    }
}

card_item.xml , l'image du cercle et la chaîne "blah blah blah" sont toutes deux du contenu statique, seul le tv_text TextView est mis à jour à partir de la source de données pour cet exemple simple:

<?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="68dp" >

    <Android.support.v7.widget.CardView
        Android:id="@+id/card_view"
        xmlns:card_view="http://schemas.Android.com/apk/res-auto"
        Android:layout_width="match_parent"
        Android:layout_margin="10dp"
        Android:layout_height="62dp"
        card_view:cardCornerRadius="4dp"
        card_view:elevation="14dp">

        <RelativeLayout
            Android:layout_width="match_parent"
            Android:layout_height="match_parent">

        <ImageView
            Android:id="@+id/iv_image"
            Android:layout_height="wrap_content"
            Android:layout_width="wrap_content"
            Android:src="@drawable/abc_btn_radio_material">
        </ImageView>

        <TextView
            Android:id="@+id/tv_text"

            Android:layout_toRightOf ="@+id/iv_image"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:gravity="center" >
        </TextView>

            <TextView
                Android:id="@+id/tv_blah"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:text="blah blah blah......"
                Android:layout_below="@+id/tv_text"
                Android:layout_toRightOf="@+id/iv_image"
                Android:layout_toEndOf="@+id/iv_image">
            </TextView>

        </RelativeLayout>
    </Android.support.v7.widget.CardView>

</RelativeLayout>

dépendances de build.gradle :

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.Android.support:appcompat-v7:23.0.1'
    compile 'com.Android.support:design:23.0.1'
    compile 'com.Android.support:cardview-v7:23.0.1'
    compile 'com.Android.support:recyclerview-v7:23.0.1'
}

Résultat:

enter image description here

40
Daniel Nugent

Cette bibliothèque vous aidera

Il s'agit d'une bibliothèque très simple pour Android qui vous permet de coller un en-tête à une vue déroulante et de lui appliquer facilement une animation

EDIT: Pour utiliser la bibliothèque StikkyHeader, vous avez juste besoin de 3 lignes:

StikkyHeaderBuilder.stickTo(mListView)
.setHeader(R.id.header, containerLayout)
.minHeightHeader(250)
.build();

Exemple:

public class IconAnimator extends HeaderStikkyAnimator {

@Override
public AnimatorBuilder getAnimatorBuilder() {

    View viewToAnimate = getHeader().findViewById(R.id.icon);
    Point point = new Point(50,100) // translate to the point with coordinate (50,100);
    float scaleX = 0.5f //scale to the 50%
    float scaleY = 0.5f //scale to the 50%
    float fade = 0.2f // 20% fade

    AnimatorBuilder animatorBuilder = AnimatorBuilder.create()
        .applyScale(viewToAnimate, scaleX, scaleY)
        .applyTranslation(viewToAnimate, point)
        .applyFade(viewToAnimate, fade);

    return animatorBuilder;
}
}

puis définissez l'animateur sur le StikkyHeader:

 StikkyHeaderBuilder.stickTo(mListView)
.setHeader(R.id.header, containerLayout)
.minHeightHeader(250)
.animator(new IconAnimator())
.build();
2
salih kallai

Ok, donc pour passer l'événement de défilement de votre listview/recyclerview à la appbarlayout, vous devez mettre le drapeau ci-dessous dans votre framelayout/relativelayout/linearlayout contenant votre vue de défilement, c'est-à-dire listview/recyclerview:

app:layout_behavior="@string/appbar_scrolling_view_behavior"

par exemple, dans votre cas, cela devrait être comme:

<Android.support.design.widget.CoordinatorLayout ....>
  <Android.support.design.widget.AppBarLayout ...>
        <Android.support.design.widget.CollapsingToolbarLayout
            app:layout_scrollFlags="scroll|exitUntilCollapsed" ..>                 
            <Android.support.design.widget.TabLayout
                app:layout_scrollFlags="scroll|enterAlways" ../>
            <Android.support.v7.widget.Toolbar >
                ..........
            </Android.support.v7.widget.Toolbar>
        </Android.support.design.widget.CollapsingToolbarLayout>
    </Android.support.design.widget.AppBarLayout>


    <FrameLayout 
       app:layout_behavior="@string/appbar_scrolling_view_behavior"
       ....>

     // Frame containing your listview/recyclerview/ scrollingview

    <FrameLayout>


</Android.support.design.widget.CoordinatorLayout >
2
Haresh Chaudhary

Exactement ce que vous voulez (il suffit de le copier-coller)

<?xml version="1.0" encoding="utf-8"?>


<Android.support.design.widget.CoordinatorLayout
    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:id="@+id/root_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context="com.arkatechnolabs.designpractice.MainActivity">

    <Android.support.design.widget.AppBarLayout
        Android:layout_width="match_parent"
        Android:layout_height="250dp"
        Android:id="@+id/appbarLayout"
        Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        >

        <Android.support.design.widget.CollapsingToolbarLayout
            Android:id="@+id/collapsibleToolBarLayout"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:background="?attr/colorPrimary"
            app:expandedTitleMarginStart="10dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">


            <Android.support.design.widget.TabLayout
                Android:id="@+id/tabs"
                Android:layout_width="match_parent"
                Android:layout_height="?attr/actionBarSize"
                Android:layout_gravity="bottom"
                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
            </Android.support.design.widget.TabLayout>

            <Android.support.v7.widget.Toolbar
                Android:id="@+id/toolbar"
        Android:layout_width="match_parent"
        Android:layout_height="?attr/actionBarSize"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
       </Android.support.v7.widget.Toolbar>

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

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




    <Android.support.v4.widget.NestedScrollView
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">


        <RelativeLayout
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:id="@+id/title_layout"
            Android:visibility="gone">

            <TextView
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_centerVertical="true"
                Android:id="@+id/toolbarText"
                />

            <TextView
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:id="@+id/send_button"
                Android:layout_marginRight="10dp"
                Android:layout_marginEnd="10dp"
                Android:text="Send Text"
                Android:textColor="@Android:color/white"
                Android:textSize="18sp"
                Android:textStyle="bold"
                Android:visibility="gone"
                Android:layout_centerVertical="true"
                Android:layout_alignParentRight="true"
                Android:layout_alignParentEnd="true"/>

        </RelativeLayout>
    </Android.support.v4.widget.NestedScrollView>

    <Android.support.design.widget.FloatingActionButton
        Android:id="@+id/fab_btn"
        Android:layout_gravity="right|bottom"
        Android:layout_marginRight="5dp"
        Android:layout_marginTop="5dp"
        Android:layout_marginBottom="5dp"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:src="@drawable/ic_fab"
        app:fabSize="normal">
    </Android.support.design.widget.FloatingActionButton>

</Android.support.design.widget.CoordinatorLayout>
1
vabhi vab