MaterialDesign系列文章(九)AppBarLayout的使用

不怕跌倒,所以飞翔

这个控件要是讲解的话我真不知道该写点什么,就直接参考依然范特稀西的文章直接实现个简书首页的效果,然后简单的讲一下就好了...

简书首页的效果

今天就带大家实现一下这个效果(也算是一个实践吧)!!!

首先分析一下这个页面效果:

  • 顶部是一个Banner
  • 中间是一个RecycleView实现的列表(横向的那个)
  • 一个搜索的条目
  • 底部是一个RecycleView实现的列表

主要知识点:(如果你对此知识点了解的话可以掠过这篇文章了):

  • app:layout_scrollFlags这个标签的使用;
  • app:layout_behavior 这个标签的使用;

实现过程:

1.布局实现

首先是页面的实现过程(这里因为主要是讲MaterialDesign所以这些不是本文讲述的重点,所以贴上代码,兄弟们自己看看就行了,不懂得可以给我留言...)

布局文件
<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context="com.hejin.materialdesign.JianShuActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white">

        <android.support.v4.view.ViewPager
            android:id="@+id/vp"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            app:layout_scrollFlags="scroll"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_tab"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll"/>

        <EditText
            android:id="@+id/et_search"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_margin="10dp"
            android:background="@drawable/edti_text_shape"
            android:gravity="center"
            android:hint="搜索简述的内容和朋友"
            android:textColor="#334455"/>
    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_bottom"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>

这里主要用到的控件在上面都写了,但是在这里又包含本文的重点,所以这里得着重讲一下

app:layout_scrollFlags="scroll"这个标签得作用

可选内容:

  • scroll View会跟随滚动时间一起发生移动(想滚动就必须设置这个)
  • enterAlways 当向下移动时,立即显示View(比如Toolbar)。
  • exitUntilCollapsed 向上滚动时收缩View,但可以固定Toolbar一直在上面。
  • enterAlwaysCollapsed 当你的View已经设置minHeight属性又使用此标志时,你的View只能以最小高度进入,只有当滚动视图到达顶部时才扩大到完整高度。

上面这些内容你们会觉得很晦涩难懂,所以我决定花些时间说明一下

scroll 如果你想让这个控件滚动得话就必须设置得一个属性,比如那上面这个布局来说吧,当你在ViewPager中设置这个属性得时候说明这个控件会随着你得手势进行滑动,否则它不会进行滑动,只有RecycleView能进行滑动(但是我发下一个问题,就是在AppBarLayout中如果第一个控件没有设置这个属性的时候,不管后面的控件是否设置这个属性都会导致后面的控件不能进行滑动,所以这里大家注意一下!!!)

enterAlways 如果你向下滑动的时候,会先把设置这个Flag的控件先跟随滑动显示出来,然后在慢慢显是底部的滑动控件,还是那上面的例子说明下:当你的ViewPager同时设置scrollenterAlways两个属性的话(用|分割,可以进行多个设置)每次当你向上滑动的时候会先滑动顶部的ViewPager然后在响应底部的RecycleView的滑动事件,但是当你向下滑动的时候,会先把ViewPager滑动出来,然后在响应RecycleView的滑动事件.

enterAlwaysCollapsed ** 这个属性类似于一种折叠效果,这个属性要enterAlwaysandroid:minHeight**一起配合使用才有效果的,还是拿上面的例子说明:当你向上滑动的时候先会在设置minHeight这段区域响应滑动,然后响应RecycleView的滑动,当向下滑动的时候,也是会先响应minHeight的滑动,然后在响应RecyceView的滑动

exitUntilCollapsed 这个属性和上面的类似,也要设置minHeight,还是拿上面的页面举例,当你上滑的是偶ViewPager会先响应滑动事件,但是会停在minHeight的高度,然后RecycleView响应滑动,当你向下滑动的时候RecycleView会先响应滑动,然后ViewPager从minHeight的高度开始响应滑动.说简单了就是屏幕上方会留一块区域.

这里提供几种供你尝试一下看一下效果你就理解了:

  • app:layout_scrollFlags="scroll"
  • app:layout_scrollFlags="scroll|enterAlways"
  • app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
  • app:layout_scrollFlags="scroll|exitUntilCollapsed"
    基本上就是上面这几种方式,试一下看一下效果就明白了!

app:layout_behavior="@string/appbar_scrolling_view_behavior"至于这个我准备后续单独些一片文章去讲解,这里只要记住只要设置了这个属性的话,会使设置这个属性的控件在AppBarLayout的下面,而不是在它上面(因为CoordinatorLayout是继承ViewGroup的而不是继承LinearLayout的)

2.一些相应的类的实现

适配器(3个):

ViewPager的适配器

lass JianShuVPAdapter extends PagerAdapter {

    private Context mContext;

    public JianShuVPAdapter(Context context) {
        mContext = context;
    }

    @Override
    public int getCount() {
        return 5;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        ImageView mIv = new ImageView(mContext);
        if (position % 2 == 0) {
            mIv.setImageResource(R.mipmap.meizhi);
        } else {
            mIv.setImageResource(R.mipmap.photo);
        }
        mIv.setScaleType(ImageView.ScaleType.CENTER_CROP);
        container.addView(mIv);
        return mIv;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }
}

RecycleView的两个适配器

class JianShuTabRVAdapter extends RecyclerView.Adapter<JianShuTabRVAdapter.TabHolder> {

    private Context mContext;
    private LayoutInflater mInflater;

    public JianShuTabRVAdapter(Context context) {
        mContext = context;
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public TabHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = mInflater.inflate(R.layout.item_jianshu_tab, parent, false);
        return new TabHolder(itemView);
    }

    @Override
    public void onBindViewHolder(TabHolder holder, int position) {
        switch (position) {
            case 0:
                holder.mTvBg.setBackgroundResource(R.drawable.label_shape);
                holder.mTvBg.setText("小说精选");
                break;
            case 1:
                holder.mTvBg.setBackgroundResource(R.drawable.label_shape2);
                holder.mTvBg.setText("摄影游记");
                break;
            case 2:
                holder.mTvBg.setBackgroundResource(R.drawable.label_shape3);
                holder.mTvBg.setText("漫画手绘");
                break;
            case 3:
                holder.mTvBg.setBackgroundResource(R.drawable.label_shape4);
                holder.mTvBg.setText("签约作者");
                break;
            default:
                holder.mTvBg.setBackgroundResource(R.drawable.label_shape);
                holder.mTvBg.setText("你猜我猜");
                break;
        }
    }

    @Override
    public int getItemCount() {
        return 5;
    }

    class TabHolder extends RecyclerView.ViewHolder {
        private TextView mTvBg;

        public TabHolder(View itemView) {
            super(itemView);
            mTvBg = itemView.findViewById(R.id.tv_bg);
        }
    }
}
class JianShuItemRVAdapter extends RecyclerView.Adapter <JianShuItemRVAdapter.ItemTab>{

    private Context mContext;
    private LayoutInflater mInflater;

    public JianShuItemRVAdapter(Context context) {
        mContext = context;
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public ItemTab onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = mInflater.inflate(R.layout.item_jianshu,parent,false);
        return new ItemTab(itemView);
    }

    @Override
    public void onBindViewHolder(ItemTab holder, int position) {

    }

    @Override
    public int getItemCount() {
        return 10;
    }


    class ItemTab extends RecyclerView.ViewHolder{
        public ItemTab(View itemView) {
            super(itemView);
        }
    }
}

主页面

public class JianShuActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_jian_shu);

        initViewPager();
        initRecycleView();
    }


    /**
     * author :  贺金龙
     * create time : 2017/11/7 10:40
     * description : 初始化ViewPager
     */
    private void initViewPager() {
        ViewPager vp = (ViewPager) findViewById(R.id.vp);
        vp.setAdapter(new JianShuVPAdapter(this));
    }

    /**
     * author :  贺金龙
     * create time : 2017/11/7 10:49
     * description : 初始化顶部和底部的RecycleView
     */
    private void initRecycleView() {
        RecyclerView rvTab = (RecyclerView) findViewById(R.id.rv_tab);
        RecyclerView rvItem = (RecyclerView) findViewById(R.id.rv_bottom);

        rvTab.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
        rvTab.setAdapter(new JianShuTabRVAdapter(this));

        rvItem.setLayoutManager(new LinearLayoutManager(this));
        rvItem.setAdapter(new JianShuItemRVAdapter(this));
    }
}

2017年09月11日补充:
如果ToolBar想要联动得话,必须要嵌套在AppBarLayout中去,否则不会有效果的(其实具体为什么我还真的不知道)!


这一系列文章的地址,希望对大家有帮助

项目地址

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

推荐阅读更多精彩内容