android android-collapsingtoolbarlayout

android - Whatsapp como Barra de herramientas contraída



android-collapsingtoolbarlayout (4)

De acuerdo, para pasar el evento de desplazamiento de su vista de lista listview/recyclerview a la appbarlayout , debe colocar la bandera a continuación en su framelayout/relativelayout/linearlayout contiene su vista de desplazamiento, es decir, vista de lista listview/recyclerview :

app:layout_behavior="@string/appbar_scrolling_view_behavior"

por ejemplo, en su caso debería ser como:

<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 >

En mi aplicación, me gustaría implementar la página de inicio de Whatsapp como una barra de herramientas plegable. Es decir, mientras se desplaza hacia abajo en la lista, la barra de herramientas debería subir y las pestañas deberían fijarse en la parte superior. ¿Cómo puedo conseguir esto?

Aquí está mi diseño de la barra de aplicaciones

<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>

Ahora TabLayout no está visible y la barra de herramientas permanece allí aunque se desplaza la lista en el localizador de vistas a continuación. Amablemente ayuda.


Exactamente lo que quieres (solo cópialo y pégalo)

<?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>


Para lograr esta funcionalidad, en realidad no se necesita un CollapsingToolbarLayout, simplemente puede contraer la Barra de herramientas que está configurada como la Barra de acciones.

Aquí hay un código de muestra usando una barra de herramientas para la barra de acciones que colapsará, y un TabLayout con un ViewPager.

Primero asegúrese de que el estilo utilizado para MainActivity sea uno que no tenga una Barra de acciones, por ejemplo:

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

MainActivity.java , que tiene el FragmentPagerAdapter y configura las pestañas:

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

Las partes importantes:

  • Use un coordinador
  • Use la app:layout_scrollFlags="scroll|enterAlways|snap" en las propiedades de la barra de herramientas
  • Use app:layout_behavior="@string/appbar_scrolling_view_behavior" en las propiedades de ViewPager

Aquí está el archivo 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 , esto simplemente agrega suficientes elementos para que se desplace:

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 , es importante usar un RecyclerView o cualquier otra Vista que admita el desplazamiento anidado, como un NestedScrollView

(nota al margen: puede llamar a NestedScrollView en api-21 y superior para que funcione con 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 , el adaptador 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 , la imagen del círculo y la cadena "blah blah blah" son contenido estático, solo el tv_text TextView se actualiza desde la fuente de datos para este simple ejemplo:

<?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>

Dependencias 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'' }

Resultado:


Esta biblioteca te ayudará

Esta es una biblioteca muy simple para Android que le permite pegar un encabezado a una vista desplazable y aplicarle animación fácilmente

EDITAR: para usar la biblioteca StikkyHeader, solo necesita 3 líneas:

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

Ejemplo:

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; } }

y luego configura el animador en StikkyHeader:

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