美文网首页Androidandroid成神之路程序员
使用CoordinatorLayout打造知乎界面

使用CoordinatorLayout打造知乎界面

作者: 真的是叫时光啊 | 来源:发表于2016-09-07 15:27 被阅读0次

    这两天在学习com.android.support:design类库的使用,也算有些小心得。就想打造一个类似于知乎的上滑隐藏、下滑加载Toolbar和TabLayout的界面布局。用起来体验还是很不错的。
    中间呢也借鉴了不少大神的博客。比如:
    http://www.jianshu.com/p/488283f74e69
    http://androidwing.net/index.php/70
    程序运行效果如下:

    aa.gif

    当然了,实际操作领悟还要全靠自己。那么今天,我就把大家带进门。
    1.知乎首页是一个Activity和多个Fragment。底部导航栏和顶部Toolbar在Activity的布局中。
    2.除了第一个Fragment,其余的Toolbar全部隐藏掉,换成Fragment的自身的顶部导航栏。

    那么我们今天主要就是完成Activity的布局效果。
    首先我们先看布局文件。我一点一点的贴,一点一点的讲,免得一大片代码让大家烦躁。而且,我觉得难就难在可能大家对这些新的东西的属性和API不熟悉。慢慢来

    //最外层的布局,CoordinatorLayout就是我们用来协调它的各种子View
    <android.support.design.widget.CoordinatorLayout
        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"
        android:fitsSystemWindows="true"
        tools:context="com.sg.zhidemo.MainActivity">
    

    之后呢,我添加了一个FrameLayout,用来替换Fragment的

    <FrameLayout    android:id="@+id/main_center_fl"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        //这里要说的。如果没有这个属性,FrameLayout或者Fragment就会在Toolbar的下面,而如果用了这个属性,就会根据appbar的大小来协调自身的位置
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
    </FrameLayout>
    

    接下来就是顶部的AppBar了,其实他就是一个可以将各种玩意和Toolbar组合到一起使用的一个容器而已。如果这里不愿意写的话呢,可以直接去new Moudle,创建一个ScrollViewActivity,内容大同小异

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">
            <android.support.v7.widget.Toolbar
                android:id="@+id/main_toolbar"
                android:layout_width="match_parent"
    //这个barSize是Google建议的高度,是56dp
                android:layout_height="?attr/actionBarSize" 
                android:background="?attr/colorPrimary"
    //前两个属性我就不说了,一会给大家推荐文章有,snap就是具有弹性的感觉,自己体会··
                app:layout_scrollFlags="scroll|enterAlways|snap">
    //这里我就是懒省事,随便写的ET
                <EditText
                    android:background="@drawable/shape"
                    android:hint="搜索话题。。。"
                    android:layout_width="wrap_content"
                    android:layout_height="42dp" />
            </android.support.v7.widget.Toolbar>
    </android.support.design.widget.AppBarLayout>
    

    然后是底部导航栏

    //用CardView包裹更好看了····
    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
    //设置位置和高度
        android:layout_gravity="bottom"
        app:cardElevation="8dp"
    //这里是重点,这里我们使用了自定义的行为。也是着重要写的地方。稍后讲
        app:layout_behavior="com.sg.zhidemo.FooterBehavior">
        <android.support.design.widget.TabLayout
            android:id="@+id/main_bottom_tab"
            android:layout_width="match_parent"
            android:layout_height="66dp"
    //去掉指示器
            app:tabIndicatorColor="@null" />
    </android.support.v7.widget.CardView>
    

    最后是一个悬浮的FAB

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"    android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right|bottom"
        android:layout_marginBottom="80dp"
        android:layout_marginRight="30dp"
        android:src="@android:drawable/ic_dialog_email"
    //用到了和上面一样的自定义行为,都是用来协调滑动事件的
        app:layout_behavior="com.sg.zhidemo.FooterBehavior" />
    

    布局就这么写完了。是不是也没有什么难的啊。。
    MainActivity中无非就是寻找控件,设置点击事件来切换Fragment,我就不写了,这里我们着重看一下FooterBehavior。
    再看之前,我还想说以下,一共有两种Behavior。
    一种是:Aview依赖Bview,在Bview移动的时候,Aview可以获取到B的一些属性和数据,同时调整自身的属性。
    另外一种呢就是我们要写的这种,当布局中有滑动事件发生的时候,会通知注册的View,是否要去处理自身的一些方法。怎么注册呢,就是靠app:layout_behavior="com.sg.zhidemo.FooterBehavior"这种行为来注册。

    来,接下来我直接把整个代码贴出来(摘自 简明的博客)

    //Behavior这个类就是用来协调我们的行为的。
    public class FooterBehavior extends CoordinatorLayout.Behavior<View> {
        private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();
        private float viewY;//控件距离coordinatorLayout底部距离
        private boolean isAnimate;//动画是否在进行
        public FooterBehavior(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    //coordinatorLayout中有滚动发生的时候会回调该方法。我们可以在该方法中获取到滚动的方向,可以获取到注册该行为的view,也就是child。大家一定要Ctrl+q看看英文的文档介绍。
        @Override
        public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
            //在第一次进入的时候获取到控件距离父布局(coordinatorLayout)底部距离。根据这个控件到底部的距离,使用插值器,来做显示隐藏的动画。
            if(child.getVisibility() == View.VISIBLE && viewY==0){
                viewY=coordinatorLayout.getHeight()-child.getY();
            } 
           return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;//判断是否竖直滚动
        }
       @Override
        public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
            //手指向上移动,屏幕内容上移dy>0,手指下移dy<0
            if (dy >=0 && !isAnimate && child.getVisibility()==View.VISIBLE) {
                //hide和show的代码我就不写了,无非就是调用动画来显示隐藏控件(虽然我感觉动画的代码才是最难的··)
                hide(child);
            } else if (dy <0 && !isAnimate && child.getVisibility()==View.GONE) {
                show(child);
            }
        }
    }
    

    这样就结束了。
    我推荐如果是想写滚动下移上移,最好自定义一个FooterBehavior或者是HeaderBehavior。如果是Aview依赖BView最好使用比例去依赖,而不要根据具体的值去依赖。
    同时给大家推荐几篇好的文章。
    本文基本就是搬运简明的博客,只不过他用的是单个Activity。我改了一下
    http://www.jianshu.com/p/488283f74e69
    这个也是大神啊,不过Demo跑起来卡
    http://androidwing.net/index.php/70
    还有徐宜生大神的这个,建议不会的跟着代码走一遍,收货颇多,超级值
    http://blog.csdn.net/eclipsexys/article/details/46349721
    Github地址:https://github.com/SshiGguang/SGUi
    第一次用Git···

    相关文章

      网友评论

        本文标题:使用CoordinatorLayout打造知乎界面

        本文链接:https://www.haomeiwen.com/subject/flulettx.html