title: 帶你實現開發者頭條APP(四)---首頁優化(加入design包)
tags: design,Toolbar,TabLayout,RecyclerView
grammar_cjkRuby: true
---java
上次模仿開發者頭條首頁實現了一個版本,給345大神,個人產品經理一看,又被鄙視了一把,說還在用老的技術,因而乎這三天把整個design包研究了一遍,而後把首頁的代碼幾乎重寫了一遍。。。。順便用上了android studio,方便你們導入。。。android
效果圖以下:
從gif動態效果圖中咱們能夠看出,跟上次沒有啥變化,惟一變化的就是列表上拉的時候會隱藏標題欄。。。其實裏面的代碼幾乎重寫了一遍,用了Android Design Support Library。緩存
Google在2015的IO大會上,給咱們帶來了更加詳細的Material Design設計規範,同時,也給咱們帶來了全新的Android Design Support Library,在這個support庫裏面,Google給咱們提供了更加規範的MD設計風格的控件。最重要的是,Android Design Support Library的兼容性更廣,直接能夠向下兼容到Android 2.2。這不得不說是一個良心之做。app
標題欄我以前引用的一個佈局文件,如今改爲了Toolbar。一個控件就夠了。
三個切換的Tab以前用的三個TextView,如今換成了TabLayout。
換了以後有哪些優勢:ide
1).跟的上時代,逼格提升,更加規範的MD設計風格
2).控件變少了,如今一個功能一個控件就夠
3).點擊Tab文字變色,還有指示器的滑動在xml加個屬性就行。
4).隱藏顯示標題欄很方便。只須要在佈局文件中改動就行.函數
最外層是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 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" android:id="@+id/coordinatorLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:id="@+id/appBarLayout" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/launcher_item_select" app:layout_scrollFlags="scroll|enterAlways" app:titleTextAppearance="@style/ansenTextTitleAppearance"> </android.support.v7.widget.Toolbar> <android.support.design.widget.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@color/main_color" app:tabIndicatorColor="@color/white_normal" app:tabIndicatorHeight="2dp" app:tabSelectedTextColor="@color/main_title_text_select" app:tabTextAppearance="@style/AnsenTabLayoutTextAppearance" app:tabTextColor="@color/main_title_text_normal"/> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </android.support.design.widget.CoordinatorLayout>
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的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吧。
帶你實現開發者頭條(一) 啓動頁實現
帶你實現開發者頭條(二) 實現左滑菜單
帶你實現開發者頭條APP(三) 首頁實現
各位看官若是以爲文章不錯,幫忙點個贊吧,對於你來講是舉手之勞,但對於我來講這就是堅持下去的動力。
推薦下本身建立的Android開發 QQ羣: 202928390歡迎你們的加入.
若是你想第一時間看咱們的後期文章,掃碼關注公衆號,每週不按期推送Android開發實戰教程文章,你還等什麼,趕快關注吧,學好技術,出任ceo,贏取白富美。。。。
Android開發666 - 安卓開發技術分享 掃描二維碼加關注