一 、前言

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

  效果图如下:

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

  从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有滑动效果,必须做到如下三点:

  CoordinatorLayout作为布局的父布局容器。

  给需要滑动的组件设置 app:layout_scrollFlags=”scroll|enterAlways” 属性。

  滑动的组件必须是AppBarLayout顶部组件。

  给滑动的组件设置app:layout_behavior属性

  5.ViewPager显示的Fragment里面不能是ListView,必须是RecyclerView。

XML/HTML代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:app="http://schemas.android.com/apk/res-auto"  
  4.     android:id="@+id/coordinatorLayout"  
  5.     android:layout_width="match_parent"  
  6.     android:layout_height="match_parent">  
  7.   
  8.     <android.support.design.widget.AppBarLayout  
  9.         android:id="@+id/appBarLayout"  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="wrap_content">  
  12.   
  13.         <android.support.v7.widget.Toolbar  
  14.             android:id="@+id/toolbar"  
  15.             android:layout_width="match_parent"  
  16.             android:layout_height="wrap_content"  
  17.             android:background="@color/launcher_item_select"  
  18.             app:layout_scrollFlags="scroll|enterAlways"  
  19.             app:titleTextAppearance="@style/ansenTextTitleAppearance">  
  20.         </android.support.v7.widget.Toolbar>  
  21.         <android.support.design.widget.TabLayout  
  22.             android:id="@+id/tabLayout"  
  23.             android:layout_width="match_parent"  
  24.             android:layout_height="wrap_content"  
  25.             android:layout_gravity="center_horizontal"  
  26.             android:background="@color/main_color"  
  27.             app:tabIndicatorColor="@color/white_normal"  
  28.             app:tabIndicatorHeight="2dp"  
  29.             app:tabSelectedTextColor="@color/main_title_text_select"  
  30.             app:tabTextAppearance="@style/AnsenTabLayoutTextAppearance"  
  31.             app:tabTextColor="@color/main_title_text_normal"/>  
  32.     </android.support.design.widget.AppBarLayout>  
  33.   
  34.     <android.support.v4.view.ViewPager  
  35.         android:id="@+id/viewPager"  
  36.         android:layout_width="match_parent"  
  37.         android:layout_height="match_parent"  
  38.         app:layout_behavior="@string/appbar_scrolling_view_behavior" />  
  39. </android.support.design.widget.CoordinatorLayout>  

  2.代码实现 MainFragment.java

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

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

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

Java代码
  1. private View.OnClickListener onClickListener=new View.OnClickListener(){  
  2.     @Override  
  3.     public void onClick(View view) {  
  4.         if(drawerListener!=null){  
  5.             drawerListener.open();  
  6.         }  
  7.     }  
  8. };  

  MainActivity.java

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

Java代码
  1. public interface MainDrawerListener{  
  2.     public void open();//打开Drawer  
  3. }  

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

Java代码
  1. mainFragment=new MainFragment(drawerListener);  
Java代码
  1. private MainDrawerListener drawerListener=new MainDrawerListener() {  
  2.     @Override  
  3.     public void open() {  
  4.         mDrawerLayout.openDrawer(Gravity.LEFT);  
  5.     }  
  6. };  

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

Java代码
  1. vPager = (ViewPager) rootView.findViewById(R.id.viewPager);  
  2. vPager.setOffscreenPageLimit(2);//设置缓存页数  
  3. vPager.setCurrentItem(0);  
  4.   
  5. FragmentAdapter pagerAdapter = new FragmentAdapter(getActivity().getSupportFragmentManager());  
  6. SelectedFragment selectedFragment=new SelectedFragment();  
  7. SubscribeFragment subscribeFragment=new SubscribeFragment();  
  8. FindFragment findFragment=new FindFragment();  
  9.   
  10. pagerAdapter.addFragment(selectedFragment,"精选");  
  11. pagerAdapter.addFragment(subscribeFragment,"订阅");  
  12. pagerAdapter.addFragment(findFragment,"发现");  
  13.   
  14. vPager.setAdapter(pagerAdapter);  
  15.   
  16. TabLayout tabLayout = (TabLayout) rootView.findViewById(R.id.tabLayout);  
  17. tabLayout.setupWithViewPager(vPager);  

  三 、分析TabLayout切换源码

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

Java代码
  1. public void setupWithViewPager(ViewPager viewPager) {  
  2.     PagerAdapter adapter = viewPager.getAdapter();  
  3.     if(adapter == null) {  
  4.         throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");  
  5.     } else {  
  6.         this.setTabsFromPagerAdapter(adapter);  
  7.         viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(this));  
  8.         this.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));  
  9.     }  
  10. }  

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

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

Java代码
  1. viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(this));  

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

Java代码
  1. public void onPageSelected(int position) {  
  2.     TabLayout tabLayout = (TabLayout)this.mTabLayoutRef.get();  
  3.     if(tabLayout != null) {  
  4.         tabLayout.getTabAt(position).select();  
  5.     }  
  6.   
  7. }  

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

Java代码
  1. public void select() {  
  2.     this.mParent.selectTab(this);  
  3. }  

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

Java代码
  1. void selectTab(TabLayout.Tab tab) {  
  2.        if(this.mSelectedTab == tab) {  
  3.            if(this.mSelectedTab != null) {  
  4.                if(this.mOnTabSelectedListener != null) {  
  5.                    this.mOnTabSelectedListener.onTabReselected(this.mSelectedTab);  
  6.                }  
  7.   
  8.                this.animateToTab(tab.getPosition());  
  9.            }  
  10.        } else {  
  11.            int newPosition = tab != null?tab.getPosition():-1;  
  12.            this.setSelectedTabView(newPosition);  
  13.            if((this.mSelectedTab == null || this.mSelectedTab.getPosition() == -1) && newPosition != -1) {  
  14.                this.setScrollPosition(newPosition, 0.0F, true);  
  15.            } else {  
  16.                this.animateToTab(newPosition);  
  17.            }  
  18.   
  19.            if(this.mSelectedTab != null && this.mOnTabSelectedListener != null) {  
  20.                this.mOnTabSelectedListener.onTabUnselected(this.mSelectedTab);  
  21.            }  
  22.   
  23.            this.mSelectedTab = tab;  
  24.            if(this.mSelectedTab != null && this.mOnTabSelectedListener != null) {  
  25.                this.mOnTabSelectedListener.onTabSelected(this.mSelectedTab);  
  26.            }  
  27.        }  
  28.   
  29. }  

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

Java代码
  1. if(this.mSelectedTab != null && this.mOnTabSelectedListener != null) {  
  2.     this.mOnTabSelectedListener.onTabSelected(this.mSelectedTab);  
  3. }  

  选择监听的接口

Java代码
  1. public interface OnTabSelectedListener {  
  2.     void onTabSelected(TabLayout.Tab var1);  
  3.   
  4.     void onTabUnselected(TabLayout.Tab var1);  
  5.   
  6.     void onTabReselected(TabLayout.Tab var1);  
  7. }  

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

Java代码
  1. public static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {  
  2.     private final ViewPager mViewPager;  
  3.   
  4.     public ViewPagerOnTabSelectedListener(ViewPager viewPager) {  
  5.         this.mViewPager = viewPager;  
  6.     }  
  7.   
  8.     public void onTabSelected(TabLayout.Tab tab) {  
  9.         this.mViewPager.setCurrentItem(tab.getPosition());  
  10.     }  
  11.   
  12.     public void onTabUnselected(TabLayout.Tab tab) {  
  13.     }  
  14.   
  15.     public void onTabReselected(TabLayout.Tab tab) {  
  16.     }  
  17. }  

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

Java代码
  1. this.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));  

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

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

  四 、剧透

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

本文发布:Android开发网
本文地址:http://www.jizhuomi.com/android/example/579.html
2016年5月30日
发布:鸡啄米 分类:Android开发实例 浏览: 评论:0