Design各控件的搭配使用3

来源:互联网 发布:国产电视剧推荐 知乎 编辑:程序博客网 时间:2024/03/28 16:37
在上一个版本基础上新增:
对RecyclerView的操作(线性,网格,瀑布流)
QuickReturnBehavior控制底部Footer的显示



<android.support.v4.widget.DrawerLayout 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/drawerLayout"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity" >    <android.support.design.widget.CoordinatorLayout        android:id="@+id/coordinatorLayout"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:fitsSystemWindows="true" >        <!-- 第一部分:伸缩工具栏 -->        <!-- AppBarLayout目前必须是第一个嵌套在CoordinatorLayout里面的子view -->        <!-- AppBarLayout里面定义的view只要设置了app:layout_scrollFlags属性,就可以在RecyclerView滚动事件发生的时候被触发: -->        <!-- app:layout_scrollFlags属性里面必须至少启用scroll这个flag,这样这个view才会滚动出屏幕,否则它将一直固定在顶部。 -->        <!--可以使用的其他flag有:enterAlways: 一旦向上滚动这个view就可见。enterAlwaysCollapsed: 顾名思义,这个flag定义的是何时进入(已经消失之后何时再次显示)。假设你定义了一个最小高度(minHeight)同时enterAlways也定义了,那么view将在到达这个最小高度的时候开始显示,并且从这个时候开始慢慢展开,当滚动到顶部的时候展开完。exitUntilCollapsed: 同样顾名思义,这个flag时定义何时退出,当你定义了一个minHeight,这个view将在滚动到达这个最小高度的时候消失。        -->        <!-- 记住,要把带有scroll flag的view放在前面,这样收回的view才能让正常退出,而固定的view继续留在顶部。 -->        <android.support.design.widget.AppBarLayout            android:id="@+id/appbar"            android:layout_width="match_parent"            android:layout_height="240dp"            android:fitsSystemWindows="true"            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" >            <!-- 如果想制造toolbar的折叠效果,我们必须把Toolbar放在CollapsingToolbarLayout中: -->            <!-- 通常,我们我们都是设置Toolbar的title,而现在,我们需要把title设置在CollapsingToolBarLayout上,而不是Toolbar。 -->            <!-- 给需要有折叠效果的组件设置 layout_collapseMode属性 -->            <!-- Toolbar 的高度layout_height必须固定,不能 “wrap_content”,否则Toolbar不会滑动,也没有折叠效果 -->            <android.support.design.widget.CollapsingToolbarLayout                android:id="@+id/collapsing_toolbar"                android:layout_width="match_parent"                android:layout_height="match_parent"                app:layout_scrollFlags="scroll|exitUntilCollapsed"                android:fitsSystemWindows="true"                app:contentScrim="?attr/colorPrimary"                app:expandedTitleMarginEnd="64dp"                app:expandedTitleMarginStart="48dp" >                <!-- 制造视差效果 -->                <!-- CollapsingToolbarLayout还能让我们做出更高级的动画,比如在里面放一个ImageView,然后在它折叠的时候渐渐淡出。同时在用户滚动的时候title的高度也会随着改变。 -->                <!-- 为了制造出这种效果,我们添加一个定义了app:layout_collapseMode="parallax" 属性的ImageView。 -->                <ImageView                    android:id="@+id/backdrop"                    android:layout_width="match_parent"                    android:layout_height="match_parent"                    app:layout_collapseMode="parallax"                    app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"                    android:fitsSystemWindows="true"                    android:scaleType="centerCrop"                    android:src="@drawable/bg_login" />                <android.support.v7.widget.Toolbar                    android:id="@+id/toolbar"                    android:layout_width="match_parent"                    android:layout_height="?attr/actionBarSize"                    app:layout_collapseMode="pin"                    app:layout_scrollFlags="scroll|enterAlways"                    app:popupTheme="@style/ThemeOverlay.AppCompat.Dark"                    app:titleTextAppearance="@style/TextAppearance.AppCompat.Headline" />                            </android.support.design.widget.CollapsingToolbarLayout>        </android.support.design.widget.AppBarLayout><android.support.v7.widget.RecyclerView            android:id="@+id/recyclerView"            android:layout_width="match_parent"            android:layout_height="match_parent"            app:layout_behavior="@string/appbar_scrolling_view_behavior" />        <!-- 响应QuickReturnFooterBehavior,偶尔会报java.lang.StackOverflowError 故注释掉  --><TextView      android:id="@+id/footerView"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:layout_gravity="bottom"          app:layout_behavior="com.mb.widget.QuickReturnBehavior"          android:background="@color/quickreturn_background"          android:gravity="center"          android:padding="16dp"          android:text="QuickReturn Footer"          android:textAppearance="@style/TextAppearance.AppCompat.Headline"          android:textColor="@android:color/white" />                   <!-- FloatingActionButton继承自ImageView;backgroundTint背景颜色,默认的背景颜色是Theme主题中的; elevation阴影的深度 -->        <!-- 目前使用的behavior是QuickReturnFooterBehavior,还可以试试 ScrollAwareFABBehavior-->        <android.support.design.widget.FloatingActionButton            android:id="@+id/floatingActionButton"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_margin="16dp"            app:layout_anchor="@id/recyclerView"            app:layout_anchorGravity="bottom|right|end"            app:layout_behavior="com.mb.widget.ScrollAwareFABBehavior"             android:src="@drawable/ic_plus"            app:backgroundTint="#FF9900"            app:elevation="16dp"            app:fabSize="normal" />         <!-- 为了能让FloatingActionButton也能折叠且消失出现,我们必须给FAB设置锚点属性app:layout_anchor="@id/appbar" --><!-- 此处可以不设置Behavior,默认就是com.mb.widget.ScrollAwareFABBehavior -->        <android.support.design.widget.FloatingActionButton            android:layout_width="wrap_content"            android:layout_height="wrap_content"            app:layout_anchor="@id/appbar"            app:layout_anchorGravity="bottom|right|end"            android:src="@drawable/ic_search"            app:backgroundTint="#CCCC00"            app:fabSize="normal" />            </android.support.design.widget.CoordinatorLayout>    <android.support.design.widget.NavigationView        android:id="@+id/navigationView"            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:layout_gravity="start"            app:headerLayout="@layout/drawer_header"            app:menu="@menu/drawer">                </android.support.design.widget.NavigationView>    </android.support.v4.widget.DrawerLayout>



package com.example.test;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import com.mb.widget.Cheeses;import com.mb.widget.SimpleStringRecyclerViewAdapter;import android.content.Context;import android.content.res.Configuration;import android.os.Bundle;import android.support.design.widget.CollapsingToolbarLayout;import android.support.design.widget.CoordinatorLayout;import android.support.design.widget.FloatingActionButton;import android.support.design.widget.NavigationView;import android.support.design.widget.NavigationView.OnNavigationItemSelectedListener;import android.support.design.widget.Snackbar;import android.support.v4.widget.DrawerLayout;import android.support.v7.app.ActionBarDrawerToggle;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.DefaultItemAnimator;import android.support.v7.widget.GridLayoutManager;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.support.v7.widget.StaggeredGridLayoutManager;import android.support.v7.widget.Toolbar;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.Toast;/** * http://www.open-open.com/lib/view/open1437312265428.html * @author pythoner * */public class MainActivity extends AppCompatActivity {private Context context;private ActionBarDrawerToggle drawerToggle;private RecyclerView recyclerView;private SimpleStringRecyclerViewAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);context=this;Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);//使用了ActionBarDrawerToggle之后,下面的设置可以不用// App Logo//        toolbar.setLogo(R.drawable.ic_launcher);        // Title//        toolbar.setTitle("App Title");        // Sub Title//        toolbar.setSubtitle("Sub title");        //Navigation Icon//        toolbar.setNavigationIcon(R.drawable.ic_launcher);                setSupportActionBar(toolbar);        getSupportActionBar().setDisplayHomeAsUpEnabled(true);                final DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);        drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.drawer_open,  R.string.drawer_close);          drawerToggle.syncState();          drawerLayout.setDrawerListener(drawerToggle);                final NavigationView navigationView = (NavigationView) findViewById(R.id.navigationView);        navigationView.setNavigationItemSelectedListener(new OnNavigationItemSelectedListener() {@Overridepublic boolean onNavigationItemSelected(MenuItem item) {// TODO Auto-generated method stubToast.makeText(context,  item.getTitle(), Toast.LENGTH_SHORT).show();return false;}});                final CoordinatorLayout coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);        //通常,我们我们都是设置Toolbar的title,而现在,我们需要把title设置在CollapsingToolBarLayout上,而不是Toolbar。        CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);        collapsingToolbar.setTitle("Title");                FloatingActionButton floatingActionButton = (FloatingActionButton) findViewById(R.id.floatingActionButton);        floatingActionButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubfinal Snackbar snackbar = Snackbar.make(coordinatorLayout, "测试弹出提示", Snackbar.LENGTH_LONG);snackbar.show();snackbar.setAction("取消", new View.OnClickListener() {@Overridepublic void onClick(View v) {snackbar.dismiss();}});}});        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);//recyclerView.addItemDecoration(new DividerGridItemDecoration(this));        recyclerView.setItemAnimator(new DefaultItemAnimator());//动画effect        LinearLayoutManager manager = new LinearLayoutManager(this);        manager.setOrientation(LinearLayoutManager.VERTICAL);        recyclerView.setLayoutManager(manager);                List<String> cheeseStrings=Arrays.asList(Cheeses.sCheeseStrings);        List<String> list=new ArrayList<String>(cheeseStrings);        adapter=new SimpleStringRecyclerViewAdapter(this,list);        recyclerView.setAdapter(adapter);                }@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {switch (item.getItemId()){        case R.id.action_add:            adapter.addItemAt(1);            break;        case R.id.action_remove:        adapter.removeItemAt(1);            break;        case R.id.action_0:        LinearLayoutManager manager0 = new LinearLayoutManager(this);        manager0.setOrientation(LinearLayoutManager.HORIZONTAL);        recyclerView.setLayoutManager(manager0);        break;        case R.id.action_1:        LinearLayoutManager manager1 = new LinearLayoutManager(this);        manager1.setOrientation(LinearLayoutManager.VERTICAL);        recyclerView.setLayoutManager(manager1);        break;        case R.id.action_2:        GridLayoutManager manager2 = new GridLayoutManager(this,4);        recyclerView.setLayoutManager(manager2);        break;        case R.id.action_3:        GridLayoutManager manager3 = new GridLayoutManager(this,3);        manager3.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {        @Override        public int getSpanSize(int position) {        return (3 - position % 3);        }        });        recyclerView.setLayoutManager(manager3);        break;        case R.id.action_4:        StaggeredGridLayoutManager manager4 = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);        recyclerView.setLayoutManager(manager4);        break;        case R.id.action_5:        StaggeredGridLayoutManager manager5 = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.HORIZONTAL);        recyclerView.setLayoutManager(manager5);        break;        }return super.onOptionsItemSelected(item);}/** 设备配置改变时 */        @Override        public void onConfigurationChanged(Configuration newConfig) {            super.onConfigurationChanged(newConfig);            drawerToggle.onConfigurationChanged(newConfig);        }        }


package com.mb.widget;import android.animation.Animator;import android.content.Context;import android.support.design.widget.CoordinatorLayout;import android.support.v4.view.ViewCompat;import android.support.v4.view.animation.FastOutSlowInInterpolator;import android.util.AttributeSet;import android.view.View;import android.view.ViewPropertyAnimator;import android.view.animation.Interpolator;/** * CoodinatorLayout给我们实现了一个可以被子view代理实现方法的一个布局。这和传统的ViewGroup不同,子view从此知道了彼此之间的存在, * 一个子view的变化可以通知到另一个子view。CoordinatorLayout所做的事情就是当成一个通信的桥梁,连接不同的view。 * 使用Behavior对象进行通信。 * @author pythoner * */public class QuickReturnBehavior extends CoordinatorLayout.Behavior<View>{private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();private final Context context;private int mYDirectionChange;//Y轴滑动方向变化public QuickReturnBehavior(Context context, AttributeSet attrs) {super();this.context=context;}//这个方法告诉CoordinatorLayout,这个view是依赖AppBarLayout的,后续父亲可以利用这个方法,查找到这个child所有依赖的兄弟结点。@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {// TODO Auto-generated method stubreturn super.layoutDependsOn(parent, child, dependency);}//这个方法,可以在这个回调中记录dependency的一些位置信息,在onLayoutChild中利用保存下来的信息进行计算,然后得到自身的具体位置。@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {// TODO Auto-generated method stubreturn super.onDependentViewChanged(parent, child, dependency);}@Overridepublic void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {// TODO Auto-generated method stubsuper.onDependentViewRemoved(parent, child, dependency);}//这个方法是用来子view用来布局自身使用,如果依赖其他view,那么系统会首先调用@Overridepublic boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {// TODO Auto-generated method stubreturn super.onLayoutChild(parent, child, layoutDirection);}//这个是CoordinatorLayout在进行measure的过程中,利用Behavior对象对子view进行大小测量的一个方法。//在这个方法内,我们可以通过parent.getDependencies(child);//这个方法,获取到这个child依赖的view,然后通过获取这个child依赖的view的大小来决定自身的大小。@Overridepublic boolean onMeasureChild(CoordinatorLayout parent, View child, int parentWidthMeasureSpec, int widthUsed,int parentHeightMeasureSpec, int heightUsed) {// TODO Auto-generated method stubreturn super.onMeasureChild(parent, child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);}//以下四个方法刚好是NestedScrollingParent的方法,也就是对CoodinatorLayout进行的一个代理(Proxy),//即CoordinatorLayout自己不对这些消息进行处理,而是传递给子view的Behavior,进行处理。//利用这样的方法,实现了view和view之间的交互和视觉的协同(布局、滑动)。@Overridepublic void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy,int[] consumed) {// TODO Auto-generated method stubsuper.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);if (dy > 0 && mYDirectionChange < 0|| dy < 0 && mYDirectionChange > 0) {            // We detected a direction change- cancel existing animations and reset our cumulative delta Y            child.animate().cancel();            mYDirectionChange = 0;        }mYDirectionChange += dy;if (mYDirectionChange > 0 && child.getVisibility() == View.VISIBLE) {            hide(child);        } else if (mYDirectionChange < 0 && child.getVisibility() == View.GONE) {            show(child);        }}@Overridepublic void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed,int dyConsumed, int dxUnconsumed, int dyUnconsumed) {// TODO Auto-generated method stubsuper.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);}@Overridepublic boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild,View target, int nestedScrollAxes) {// TODO Auto-generated method stub//Log.i("tag", "nestedScrollAxes===="+nestedScrollAxes);//2return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;}@Overridepublic void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) {// TODO Auto-generated method stubsuper.onStopNestedScroll(coordinatorLayout, child, target);}//源码中hide里调用show,show里调用hide,有可能会造成死锁,偶尔会报堆栈溢出异常!故注释掉了源码//目前我在hide的onAnimationStart中添加了view.setVisibility(View.VISIBLE),运行没有问题    private void hide(final View view) {        ViewPropertyAnimator animator = view.animate()                .translationY(view.getHeight())                .setInterpolator(INTERPOLATOR)                .setDuration(400);        animator.setListener(new Animator.AnimatorListener() {            @Override            public void onAnimationStart(Animator animator) {            view.setVisibility(View.VISIBLE);//by pythoner added            }            @Override            public void onAnimationEnd(Animator animator) {                // Prevent drawing the View after it is gone                view.setVisibility(View.GONE);            }            @Override            public void onAnimationCancel(Animator animator) {                // Canceling a hide should show the view//                show(view);//by pythoner removed            }            @Override            public void onAnimationRepeat(Animator animator) {}        });        animator.start();    }    private void show(final View view) {        ViewPropertyAnimator animator = view.animate()                .translationY(0)                .setInterpolator(INTERPOLATOR)                .setDuration(400);        animator.setListener(new Animator.AnimatorListener() {            @Override            public void onAnimationStart(Animator animator) {                view.setVisibility(View.VISIBLE);            }            @Override            public void onAnimationEnd(Animator animator) {                        }            @Override            public void onAnimationCancel(Animator animator) {                // Canceling a show should hide the view//                hide(view);//by pythoner removed            }            @Override            public void onAnimationRepeat(Animator animator) {}        });        animator.start();    }    }
原创粉丝点击