帶你實現開發者頭條APP(四)---首頁優化(加入design包)

来源:http://www.cnblogs.com/yishaochu/archive/2016/04/24/5428709.html
-Advertisement-
Play Games

title: 帶你實現開發者頭條APP(四) 首頁優化(加入design包) tags: design,Toolbar,TabLayout,RecyclerView grammar_cjkRuby: true 一 、前言 上次模仿開發者頭條首頁實現了一個版本,給 "345大神,我的產品經理" 一看, ...



title: 帶你實現開發者頭條APP(四)---首頁優化(加入design包)
tags: design,Toolbar,TabLayout,RecyclerView
grammar_cjkRuby: true
---

一 、前言

上次模仿開發者頭條首頁實現了一個版本,給345大神,我的產品經理一看,又被鄙視了一把,說還在用老的技術,於是乎這三天把整個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。
<?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>
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吧。

五 、源碼下載

點擊下載源碼

六 、相關文章閱讀

帶你實現開發者頭條(一) 啟動頁實現
帶你實現開發者頭條(二) 實現左滑菜單
帶你實現開發者頭條APP(三) 首頁實現

各位看官如果覺得文章不錯,幫忙點個贊吧,對於你來說是舉手之勞,但對於我來說這就是堅持下去的動力。

推薦下自己創建的Android開發 QQ群: 202928390歡迎大家的加入.

如果你想第一時間看我們的後期文章,掃碼關註公眾號,每周不定期推送Android開發實戰教程文章,你還等什麼,趕快關註吧,學好技術,出任ceo,贏取白富美。。。。

      Android開發666 - 安卓開發技術分享
            掃描二維碼加關註

Android開發666


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 鍵路徑 在一個給定的實體中,同一個屬性的所有值具有相同的數據類型。 鍵-值編碼技術用於進行這樣的查找—它是一種間接訪問對象屬性的機制。 - 鍵路徑是一個由用點作分隔符的鍵組成的字元串,用於指定一個連接在一起的對象性質序列。第一個鍵的性質是由先前的性質決定的,接下來每個鍵的值也是相對於其前面的性質。 ...
  • 自定義 cell 1 什麼是自定義 cell 自定義 cell 即 tableView,collectionView,scrollView中的 cell 使用的時候不能滿足我們使用 cell 的需求,需要自己定義一個 cell. 2 cell 的重用 原因:cell 的顯示原理的,一個 cell 顯 ...
  • 當前蘋果已經禁止了,通過IOS應用直接跳轉APP下載鏈接的方法。但是仍然可以使用另外一種方法直接跳轉AppStore。 這種方法需要增加一個類庫StoreKit.framework。 這裡使用這功能是為用戶提供更新,下麵說下我實現這個功能的詳細步驟。 一、增加一個網頁到伺服器上去,title增加你當 ...
  • 一,效果圖。 二,工程圖。 三,代碼。 RootViewController.h RootViewController.m myCell.h myCell.m CardViewController.h CardViewController.m ...
  • 一、OC簡介 在C語言的基礎上,增加了一層最小的面向對象語法;完全相容C語言;可以在OC代碼中混入C語言代碼,甚至是C++代碼;可以使用OC開發Mac OS X平臺和iOS平臺的應用程式。 二、OC語法預覽 (一)關鍵字 基本上所有的關鍵字都是以@開頭的,如@interface @implement ...
  • 本文內容根據個人自學整理記錄,理解不當之處,希望大家批評指正,大家相互學習,寫學習歸納,寫博客是個好習慣,希望能夠堅持下去。 在前一篇文章當中介紹了 Android 的系統框架,主要是為了讓大家對Android 系統的內部層次結構有個清晰的認識,是開發 Android 程式開發的基礎。對 Andro ...
  • 閉包是可以在代碼中被傳遞和使用的自包含功能模塊,它很像c和oc中的block,和.net中的lambdasbas表達式。 閉包可以捕獲和存儲其所在上下文中任意常量和變數的引用。 包裹著這些常量和變數的包俗稱閉包。Swift會為您管理在捕獲過程中涉及到的記憶體操作。下麵是閉包的3中表現形式 全局函數是一 ...
  • 1、產品設計圖 可以以6的長寬比 750*1134來設計。這些圖片用於描述app是什麼樣子的,這是app開發人員的開發參考。 2、產品切圖 將設計師將設計稿切成可以用來開發的圖 顏色值 iOS顏色值取 RGB各顏色的值比如某個色值,給予iOS開發的色值為 R:12 G:34 B:56 給出的值就是 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...