使用CoordinatorLayout打造知乎界面

这两天在学习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···

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,391评论 25 707
  • RandomAccessFile 随机读取文件内容 构造方法 RandomAccessiFile raf=new ...
    HAHAYA阅读 486评论 0 0
  • 今天读申命记8-11,我看到神是我们的灵粮,神是施慈爱怜悯的神,神是我们永远的力量。 一、生命的灵粮 神让以色列人...
    尤加利阅读 5,247评论 0 0
  • 美好的一天从感恩开始:我感恩生命的富足美好!让我可以自由的生活。我感恩健康!让我可以无忧的生活。我感恩老公辛劳打拼...
    淘淘的简书阅读 182评论 1 0
  • 玩彩是一场华丽的远行,只有提高功底,才会走的更远。今天继续前行。 好运彩吧3D第173期分析: 独胆:5 两码:5...
    金穗宾馆好运彩吧阅读 180评论 0 0