2016-03-13 18 views
9

In meiner App möchte ich WhatsApp Homepage wie zusammenklappbare Symbolleiste implementieren. Das heißt, während Sie in der Liste nach unten scrollen, sollte die Symbolleiste nach oben gehen und die Tabs sollten an der Spitze hängen. Wie kann ich das erreichen?WhatsApp wie Collapsing Toolbar

Hier ist mein appbar Layout

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

Nun ist die TabLayout nicht sichtbar ist und die Toolbar bleibt es, auch wenn die Liste in der Ansicht Pager unten gescrollt wird. Freundlich helfen. und leicht anzuwenden Animation es

EDIT

Antwort

24

Um diese Funktionalität zu erreichen, wird CollapsingToolbarLayout eigentlich nicht benötigt. Sie können die Toolbar, die als ActionBar definiert ist, einfach ausblenden.

Hier ist Beispielcode mit einer Symbolleiste für die ActionBar, die zusammenbricht, und ein TabLayout mit einem ViewPager.

zunächst sicher, dass der Stil für MainActivity verwendet wird, ist eine, die nicht eine ActionBar hat, zB:

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

MainActivity.java, welche die FragmentPagerAdapter hat und setzt die Registerkarten oben:

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

Die wichtigen Teile:

  • Verwenden Sie einen CoordinatorLayout
  • Verwenden app:layout_scrollFlags="scroll|enterAlways" in der Symbolleiste Eigenschaften
  • Verwenden app:layout_behavior="@string/appbar_scrolling_view_behavior" in die ViewPager Eigenschaften

Hier ist die activity_main .xml Datei:

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

    <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, dies fügt einfach genug Elemente, um es bewegen zu machen:

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 ist es wichtig, einen RecyclerView oder einen anderen View this sup Ports Scrollen, wie zum Beispiel einer NestedScrollView

verschachtelt (Randnotiz: Sie setNestedScrollingEnabled(true) auf api-21 anrufen und bis es mit einem Listview arbeiten zu lassen):

<?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, die RecyclerView Adapter:

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, der Kreis Bild und das "bla bla bla" String sind sowohl statische Inhalte, nur der Text tv_text View für dieses einfache Beispiel aus der Datenquelle aktualisiert:

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

build.gradle Abhängigkeiten:

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

Ergebnis:

enter image description here

+0

Vielen Dank Daniel. :) –

+0

Alles an einem Ort. Groß!!! –

+0

Woh ... Du hast es genagelt. Awesome Erklärung – ADM

1

This library will help you

Dies ist eine sehr einfache Bibliothek für Android, dass Sie einen Header zu einer scrollbaren Ansicht zu bleiben erlaubt: Um die StikkyHeader Bibliothek zu verwenden, die Sie gerade benötigen 3 Zeilen:

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

Beispiel:

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

und dann den Animator zum StikkyHeader gesetzt:

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

Könnten Sie bitte einen Beispielcode einfügen? –

0

Ok, also um das Scroll-Ereignis Ihrer listview/recyclerview zum appbarlayout zu übergeben, müssen Sie in Ihrem framelayout/relativelayout/linearlayout mit Ihrer Scrollen Ansicht, die die unten Flagge setzen, listview/recyclerview dh:

app:layout_behavior="@string/appbar_scrolling_view_behavior" 

zum Beispiel, sollte es in Ihrem Fall sein wie:

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

Genau das, was Sie wollen (Just kopieren und einfügen)

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