博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
带你实现开发者头条APP(四)---首页优化(加入design包)
阅读量:5743 次
发布时间:2019-06-18

本文共 7226 字,大约阅读时间需要 24 分钟。

title: 带你实现开发者头条APP(四)---首页优化(加入design包)

tags: design,Toolbar,TabLayout,RecyclerView
grammar_cjkRuby: true
---

一 、前言

上次模仿开发者头条首页实现了一个版本,给一看,又被鄙视了一把,说还在用老的技术,于是乎这三天把整个design包研究了一遍,然后把首页的代码几乎重写了一遍。。。。顺便用上了android studio,方便大家导入。。。

效果图如下:

效果图
从gif动态效果图中我们可以看出,跟上次没有啥变化,唯一变化的就是列表上拉的时候会隐藏标题栏。。。其实里面的代码几乎重写了一遍,用了Android Design Support Library。

Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,在这个support库里面,Google给我们提供了更加规范的MD设计风格的控件。最重要的是,Android Design Support Library的兼容性更广,直接可以向下兼容到Android 2.2。这不得不说是一个良心之作。

二、Toolbar+TabLayout 实现 标题栏+三个切换Tab

标题栏我之前引用的一个布局文件,现在改成了Toolbar。一个控件就够了。

三个切换的Tab之前用的三个TextView,现在换成了TabLayout。
换了之后有哪些优点:

1).跟的上时代,逼格提高,更加规范的MD设计风格

2).控件变少了,现在一个功能一个控件就够
3).点击Tab文字变色,还有指示器的滑动在xml加个属性就行。
4).隐藏显示标题栏很方便。只需要在布局文件中改动就行.

1.布局文件

最外层是CoordinatorLayout,里面主要就分两块,AppBarLayout+ViewPager(AppBarLayout里面包含标题栏的Toolbar+TabLayout,ViewPager用来切换Fragment显示)

为了使得Toolbar有滑动效果,必须做到如下三点:

  1. CoordinatorLayout作为布局的父布局容器。
  2. 给需要滑动的组件设置 app:layout_scrollFlags=”scroll|enterAlways” 属性。
  3. 滑动的组件必须是AppBarLayout顶部组件。
  4. 给滑动的组件设置app:layout_behavior属性
    5.ViewPager显示的Fragment里面不能是ListView,必须是RecyclerView。
2.代码实现 MainFragment.java

1).初始化Toolbar,加载menu布局,实现标题栏的自定义。给NavigationIcon设置点击事件等。下面贴出代码实现,还有menu布局文件我就不贴出来了。那个也没啥技术含量。

Toolbar toolbar = (Toolbar) rootView.findViewById(R.id.toolbar);        toolbar.inflateMenu(R.menu.ansen_toolbar_menu);        toolbar.setNavigationIcon(R.mipmap.ic_menu_white);        toolbar.setTitle("关注公众号[Android开发者666]");        toolbar.setTitleTextColor(getResources().getColor(android.R.color.white));        toolbar.setNavigationOnClickListener(onClickListener);

NavigationIcon监听函数,回调到MainActivity去。

private View.OnClickListener onClickListener=new View.OnClickListener(){        @Override        public void onClick(View view) {            if(drawerListener!=null){                drawerListener.open();            }        }    };

MainActivity.java

首先写了一个用来回调的接口

public interface MainDrawerListener{        public void open();//打开Drawer    }

初始化Fragment的时候把MainDrawerListener对象传递过去 这样才能实现回调

mainFragment=new MainFragment(drawerListener);
private MainDrawerListener drawerListener=new MainDrawerListener() {        @Override        public void open() {            mDrawerLayout.openDrawer(Gravity.LEFT);        }    };

2).给ViewPager设置Fragment适配器,给TabLayout绑定ViewPager,这样ViewPager滑动的时候或者选择tab的时候都会切换fragment。

vPager = (ViewPager) rootView.findViewById(R.id.viewPager);        vPager.setOffscreenPageLimit(2);//设置缓存页数        vPager.setCurrentItem(0);        FragmentAdapter pagerAdapter = new FragmentAdapter(getActivity().getSupportFragmentManager());        SelectedFragment selectedFragment=new SelectedFragment();        SubscribeFragment subscribeFragment=new SubscribeFragment();        FindFragment findFragment=new FindFragment();        pagerAdapter.addFragment(selectedFragment,"精选");        pagerAdapter.addFragment(subscribeFragment,"订阅");        pagerAdapter.addFragment(findFragment,"发现");        vPager.setAdapter(pagerAdapter);        TabLayout tabLayout = (TabLayout) rootView.findViewById(R.id.tabLayout);        tabLayout.setupWithViewPager(vPager);

三 、分析TabLayout切换源码

我们调用TabLayout的setupWithViewPager(ViewPager viewPager)方法的时候就是设置切换监听的时候。

public void setupWithViewPager(ViewPager viewPager) {        PagerAdapter adapter = viewPager.getAdapter();        if(adapter == null) {            throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");        } else {            this.setTabsFromPagerAdapter(adapter);            viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(this));            this.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));        }    }

从上面代码中我们可以看到主要设置了两个监听函数。先说第一个。

在TabLayout里面有一个静态类TabLayoutOnPageChangeListener,用来处理ViewPager改变状态(切换或者增加)监听,看过我第三篇文章的同学对ViewPager的状态改变监听应该很熟悉了。

viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(this));

TabLayoutOnPageChangeListener实现了ViewPagerde 的OnPageChangeListener接口,在onPageSelected方法中调用了当前选中的某个Tab的select方法。

public void onPageSelected(int position) {            TabLayout tabLayout = (TabLayout)this.mTabLayoutRef.get();            if(tabLayout != null) {                tabLayout.getTabAt(position).select();            }        }

然后继续跟踪TabLayout.Tab类的select() 看看如何实现的。我们可以看到又调用了父类(TabLayout)的selectTab。

public void select() {            this.mParent.selectTab(this);        }

然后跟踪selectTab方法,这里大家可以看到参数是某个具体Tab对象,首先判断是不是当前tab,如果不是设置选择当前的tab,开启tab滑动动画。

void selectTab(TabLayout.Tab tab) {        if(this.mSelectedTab == tab) {            if(this.mSelectedTab != null) {                if(this.mOnTabSelectedListener != null) {                    this.mOnTabSelectedListener.onTabReselected(this.mSelectedTab);                }                this.animateToTab(tab.getPosition());            }        } else {            int newPosition = tab != null?tab.getPosition():-1;            this.setSelectedTabView(newPosition);            if((this.mSelectedTab == null || this.mSelectedTab.getPosition() == -1) && newPosition != -1) {                this.setScrollPosition(newPosition, 0.0F, true);            } else {                this.animateToTab(newPosition);            }            if(this.mSelectedTab != null && this.mOnTabSelectedListener != null) {                this.mOnTabSelectedListener.onTabUnselected(this.mSelectedTab);            }            this.mSelectedTab = tab;            if(this.mSelectedTab != null && this.mOnTabSelectedListener != null) {                this.mOnTabSelectedListener.onTabSelected(this.mSelectedTab);            }        }    }

上面的代码我就不一一解释了,直接看最下面那两行代码。调用tab的选择方法。

if(this.mSelectedTab != null && this.mOnTabSelectedListener != null) {                this.mOnTabSelectedListener.onTabSelected(this.mSelectedTab);            }

选择监听的接口

public interface OnTabSelectedListener {        void onTabSelected(TabLayout.Tab var1);        void onTabUnselected(TabLayout.Tab var1);        void onTabReselected(TabLayout.Tab var1);    }

在TabLayout内部实现了OnTabSelectedListener接口,在onTabSelected方法中调用了ViewPager的setCurrentItem(),这个方法大家应该都熟悉吧,我就不多做解释了。

public static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {        private final ViewPager mViewPager;        public ViewPagerOnTabSelectedListener(ViewPager viewPager) {            this.mViewPager = viewPager;        }        public void onTabSelected(TabLayout.Tab tab) {            this.mViewPager.setCurrentItem(tab.getPosition());        }        public void onTabUnselected(TabLayout.Tab tab) {        }        public void onTabReselected(TabLayout.Tab tab) {        }    }

上面说到了第一种监听,就是ViewPager滑动的时候如何切换item,如果切换tab。现在来说第二种情况,就是点击选择tab的时候。如何切换的。继续回到TabLayout的setupWithViewPager(ViewPager viewPager)方法。

this.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));
看到ViewPagerOnTabSelectedListener类是不是很熟悉,其实就是第一种方法最后调用的那个类。。。。。因为点击某个tab的时候,tab切换的代码已经运行,所以我们这里只需要设置下ViewPager当前选中的item就行。

从源码分析的文章第一次写,不知道这样写出来大家看的懂么,还有不对的地方也欢迎大家提出,可以给我评论哦,我会第一时间回复大家。

四 、透剧

本来打算顺便写下RecyclerView的实现的,但是发现内容已经不少了,那就留着下篇文章吧,下篇文章打算左滑里面的布局用NavigationView实现。然后加上RecyclerView吧。

你可能感兴趣的文章
刨根问底--技术--jsoup登陆网站
查看>>
OSChina 五一劳动节乱弹 ——女孩子晚上不要出门,发生了这样的事情
查看>>
Spring--通过注解来配置bean
查看>>
pandas 十分钟入门
查看>>
nginx rewrite
查看>>
前端安全系列(一):如何防止XSS攻击?
查看>>
查看Linux并发连接数
查看>>
你是谁不重要,关键是你跟谁!
查看>>
CSS中规则@media的用法
查看>>
pychecker:分析你的python代码
查看>>
我的友情链接
查看>>
DNS显性+隐性URL转发原理
查看>>
我的友情链接
查看>>
网易有道 IP地址、手机号码归属地和身份证 查询接口API
查看>>
鼠标停留在GridView某一行时行的颜色改变
查看>>
系列3:WAS Liberty Profile hello mysql jdbc
查看>>
基础知识:python模块的导入
查看>>
Android MVC之我的实现
查看>>
我的友情链接
查看>>
我的友情链接
查看>>