Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 安卓開發復習筆記——Fragment+ViewPager組件(高仿微信界面)

安卓開發復習筆記——Fragment+ViewPager組件(高仿微信界面)

編輯:關於Android編程

麼是ViewPager?     關於ViewPager的介紹和使用,在之前我寫過一篇相關的文章《安卓開發復習筆記——ViewPager組件(仿微信引導界面)》,不清楚的朋友可以看看,這裡就不再重復。       什麼是Fragment?      Fragment是Android3.0後新增的概念,Fragment名為碎片,不過卻和Activity十分相似,具有自己的生命周期,它是用來描述一些行為或一部分用戶界面在一個Activity中,我們可以合並多個Fragment在一個單獨的activity中建立多個UI面板,或者重用Fragment在多個activity中。   關於Fragment的生命周期,由於Fragment需要依賴Activity,也就是說當一個Activity的生命周期結束之後,那麼Fragment的生命周期也自然結束。如果把一個Activiy比作一座大宅子的話,那麼Fragment就可以比作大宅子裡的房間,大宅子裡的房間其中一間倒塌了,並不會引起整個大宅子的倒塌,但如果大宅子倒塌了,那麼大宅裡的房間也就都倒塌了。   下面來看下Fragment的生命周期:                    Activity和Fragment生命周期對比(相似):                  為了更好的理解Fragment,我找了下面的一張圖:     看左邊這張圖,它是我們傳統的手機界面,假設它現在呈現的是一個新聞列表頁,那麼當我們點擊列表項中,我們將會跳轉到新聞詳細頁中,上面是標題,下面是正文,這裡是2個Activity。     再看看右邊的圖,左邊是新聞列表頁,右邊是新聞詳細頁,我們可以動態的點擊左邊的列表項,使得右邊的新聞詳細頁動態變化,這裡只有1個Activity裡面嵌套了2個Fragment,左邊一個,右邊一個。                                                       好了,做了簡單的介紹後,先來看看今天我們要實現的效果圖:(高仿微信主界面)       這裡我畫了張界面分析圖,畫圖永遠的痛,湊合著看哈           這裡的XML布局文件,我把每一部分都分開寫了:   top1.xml   復制代碼  1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  2     xmlns:tools="http://schemas.android.com/tools"  3     android:layout_width="match_parent"  4     android:layout_height="50dp"  5     android:background="@drawable/bg"  6     android:paddingLeft="12dp"  7     android:paddingRight="12dp" >  8   9     <LinearLayout 10         android:layout_width="wrap_content" 11         android:layout_height="wrap_content" 12         android:layout_centerVertical="true" 13         android:gravity="center" 14         android:orientation="horizontal" > 15  16         <ImageView 17             android:layout_width="30dp" 18             android:layout_height="30dp" 19             android:src="@drawable/weixin" /> 20  21         <TextView 22             android:layout_width="wrap_content" 23             android:layout_height="wrap_content" 24             android:layout_marginLeft="12dp" 25             android:text="微信" 26             android:textColor="@android:color/white" 27             android:textSize="18dp" /> 28     </LinearLayout> 29  30     <LinearLayout 31         android:layout_width="wrap_content" 32         android:layout_height="wrap_content" 33         android:layout_alignParentRight="true" 34         android:layout_centerVertical="true" 35         android:gravity="center" 36         android:orientation="horizontal" > 37  38         <ImageView 39             android:layout_width="30dp" 40             android:layout_height="30dp" 41             android:src="@drawable/search" /> 42  43         <ImageView 44             android:layout_width="30dp" 45             android:layout_height="30dp" 46             android:src="@drawable/add" /> 47  48         <ImageView 49             android:layout_width="30dp" 50             android:layout_height="30dp" 51             android:src="@drawable/more" /> 52     </LinearLayout> 53  54 </RelativeLayout> 復制代碼     top2.xml   復制代碼  1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  2     android:layout_width="match_parent"  3     android:layout_height="40dp"  4     android:orientation="vertical" >  5   6     <LinearLayout  7         android:layout_width="match_parent"  8         android:layout_height="37dp"   9         android:gravity="center_vertical" 10         android:background="#cccccc" 11         > 12  13         <LinearLayout 14             android:layout_width="wrap_content" 15             android:layout_height="wrap_content" 16             android:layout_weight="1" 17             android:gravity="center" > 18  19             <TextView 20                 android:id="@+id/tv1" 21                 android:layout_width="wrap_content" 22                 android:layout_height="wrap_content" 23                 android:text="聊天"  24                 android:textColor="#339900"/> 25         </LinearLayout> 26  27         <LinearLayout 28             android:layout_width="wrap_content" 29             android:layout_height="wrap_content" 30             android:layout_weight="1" 31             android:gravity="center" > 32  33             <TextView 34                  android:id="@+id/tv2" 35                 android:layout_width="wrap_content" 36                 android:layout_height="wrap_content" 37                 android:text="發現"  38                 android:textColor="@android:color/black"/> 39         </LinearLayout> 40  41         <LinearLayout 42             android:layout_width="wrap_content" 43             android:layout_height="wrap_content" 44             android:layout_weight="1" 45             android:gravity="center" > 46  47             <TextView 48                  android:id="@+id/tv3" 49                 android:layout_width="wrap_content" 50                 android:layout_height="wrap_content" 51                 android:text="通訊錄"  52                 android:textColor="@android:color/black"/> 53         </LinearLayout> 54     </LinearLayout> 55  56     <LinearLayout 57         android:layout_width="match_parent" 58         android:layout_height="3dp" > 59  60         <ImageView 61             android:id="@+id/tabline" 62             android:layout_width="100dp" 63             android:layout_height="match_parent" 64             android:background="@drawable/tabline" /> 65     </LinearLayout> 66  67 </LinearLayout> 復制代碼     mywx.xml(用include包含前2個布局文件,並設置垂直排列)   復制代碼  1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  2     xmlns:tools="http://schemas.android.com/tools"  3     android:layout_width="match_parent"  4     android:layout_height="match_parent"  5     android:orientation="vertical"  6     tools:context="com.example.weixin_test.MyWxTest" >  7   8     <include layout="@layout/top1" />  9  10     <include layout="@layout/top2" /> 11  12      13  <android.support.v4.view.ViewPager 14      android:id="@+id/viewpager" 15      android:layout_width="match_parent" 16      android:layout_height="wrap_content" 17      android:layout_weight="1" 18      > 19       20       21  </android.support.v4.view.ViewPager> 22 </LinearLayout> 復制代碼      Fragment1.xml(由於Flagment的布局文件只是簡單采用字符標示,布局都一樣,這裡只給出第一個Fragment布局文件)   復制代碼  1 <?xml version="1.0" encoding="utf-8"?>  2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  3     android:layout_width="match_parent"  4     android:layout_height="match_parent"  5     >  6       7     <TextView   8         android:layout_width="wrap_content"  9         android:layout_height="wrap_content" 10         android:text="我是第一個界面" 11         android:textSize="30dp" 12         android:layout_centerInParent="true" 13          14         /> 15      16  17 </RelativeLayout> 復制代碼     接下來是JAVA代碼了,注釋很全(其實用法還是之前的ViewPager,只不過之前的ViewPager的數據源裡存放的是view對象,而這裡是Fragment)   復制代碼   1 package com.example.weixin_test;   2    3 import java.util.ArrayList;   4 import java.util.List;   5    6 import android.graphics.Color;   7 import android.os.Bundle;   8 import android.support.v4.app.Fragment;   9 import android.support.v4.app.FragmentActivity;  10 import android.support.v4.app.FragmentPagerAdapter;  11 import android.support.v4.view.ViewPager;  12 import android.support.v4.view.ViewPager.OnPageChangeListener;  13 import android.util.DisplayMetrics;  14 import android.util.Log;  15 import android.view.Display;  16 import android.view.ViewGroup.LayoutParams;  17 import android.view.Window;  18 import android.widget.ImageView;  19 import android.widget.LinearLayout;  20 import android.widget.TextView;  21   22 public class MyWxTest extends FragmentActivity {  23   24     private ViewPager viewPager;// 聲明一個viewpager對象  25     private TextView tv1;  26     private TextView tv2;  27     private TextView tv3;  28     private ImageView tabline;  29     private List<Fragment> list;// 聲明一個list集合存放Fragment(數據源)  30   31     private int tabLineLength;// 1/3屏幕寬  32     private int currentPage = 0;// 初始化當前頁為0(第一頁)  33   34     @Override  35     protected void onCreate(Bundle savedInstanceState) {  36         super.onCreate(savedInstanceState);  37         requestWindowFeature(Window.FEATURE_NO_TITLE);  38         setContentView(R.layout.mywx);  39         // 初始化滑動條1/3  40         initTabLine();  41   42         // 初始化界面  43         initView();  44     }  45   46     private void initTabLine() {  47         // 獲取顯示屏信息  48         Display display = getWindow().getWindowManager().getDefaultDisplay();  49         // 得到顯示屏寬度  50         DisplayMetrics metrics = new DisplayMetrics();  51         display.getMetrics(metrics);  52         // 1/3屏幕寬度  53         tabLineLength = metrics.widthPixels / 3;  54         // 獲取控件實例  55         tabline = (ImageView) findViewById(R.id.tabline);  56         // 控件參數  57         LayoutParams lp = tabline.getLayoutParams();  58         lp.width = tabLineLength;  59         tabline.setLayoutParams(lp);  60     }  61   62     private void initView() {  63         // 實例化對象  64         viewPager = (ViewPager) findViewById(R.id.viewpager);  65         tv1 = (TextView) findViewById(R.id.tv1);  66         tv2 = (TextView) findViewById(R.id.tv2);  67         tv3 = (TextView) findViewById(R.id.tv3);  68         list = new ArrayList<Fragment>();  69   70         // 設置數據源  71         Fragment1 fragment1 = new Fragment1();  72         Fragment2 fragment2 = new Fragment2();  73         Fragment3 fragment3 = new Fragment3();  74   75         list.add(fragment1);  76         list.add(fragment2);  77         list.add(fragment3);  78   79         // 設置適配器  80         FragmentPagerAdapter adapter = new FragmentPagerAdapter(  81                 getSupportFragmentManager()) {  82   83             @Override  84             public int getCount() {  85                 return list.size();  86             }  87   88             @Override  89             public Fragment getItem(int arg0) {  90                 return list.get(arg0);  91             }  92         };  93   94         // 綁定適配器  95         viewPager.setAdapter(adapter);  96   97         // 設置滑動監聽  98         viewPager.setOnPageChangeListener(new OnPageChangeListener() {  99  100             @Override 101             public void onPageSelected(int position) { 102                 // 當頁面被選擇時,先講3個textview的字體顏色初始化成黑 103                 tv1.setTextColor(Color.BLACK); 104                 tv2.setTextColor(Color.BLACK); 105                 tv3.setTextColor(Color.BLACK); 106  107                 // 再改變當前選擇頁(position)對應的textview顏色 108                 switch (position) { 109                 case 0: 110                     tv1.setTextColor(Color.rgb(51, 153, 0)); 111                     break; 112                 case 1: 113                     tv2.setTextColor(Color.rgb(51, 153, 0)); 114                     break; 115                 case 2: 116                     tv3.setTextColor(Color.rgb(51, 153, 0)); 117                     break; 118                 } 119  120                 currentPage = position; 121  122             } 123  124             @Override 125             public void onPageScrolled(int arg0, float arg1, int arg2) { 126                 Log.i("tuzi", arg0 + "," + arg1 + "," + arg2); 127  128                 // 取得該控件的實例 129                 LinearLayout.LayoutParams ll = (android.widget.LinearLayout.LayoutParams) tabline 130                         .getLayoutParams(); 131  132                 if (currentPage == 0 && arg0 == 0) { // 0->1移動(第一頁到第二頁) 133                     ll.leftMargin = (int) (currentPage * tabLineLength + arg1 134                             * tabLineLength); 135                 } else if (currentPage == 1 && arg0 == 1) { // 1->2移動(第二頁到第三頁) 136                     ll.leftMargin = (int) (currentPage * tabLineLength + arg1 137                             * tabLineLength); 138                 } else if (currentPage == 1 && arg0 == 0) { // 1->0移動(第二頁到第一頁) 139                     ll.leftMargin = (int) (currentPage * tabLineLength - ((1 - arg1) * tabLineLength)); 140                 } else if (currentPage == 2 && arg0 == 1) { // 2->1移動(第三頁到第二頁) 141                     ll.leftMargin = (int) (currentPage * tabLineLength - (1 - arg1) 142                             * tabLineLength); 143                 } 144  145                 tabline.setLayoutParams(ll); 146  147             } 148  149             @Override 150             public void onPageScrollStateChanged(int arg0) { 151                 // TODO Auto-generated method stub 152  153             } 154         }); 155  156     } 157  158 } 復制代碼 對這個類做下說明:   1、這裡的滑動屏幕下劃線動態跟隨的效果,其實實現方法有2種,原理是一樣的   (1)可以使用ViewPager的兩個子類ViewFlipper和ViewSwitche,這種方法比較簡單,直接用就行。   (2)用原生代碼實現,也就是動態的去控制下劃線的左外邊距。   這裡我采用的是第2種方法,我覺得授人予魚還不如授人予漁,其實也並不復雜,細節去理下細節就懂了。       這裡需要注意一個地方,我們在給ViewPager設置監聽器時,這邊會復寫一個onPageScrolled方法,裡面有3個參數,我用Log打印出它們在頁面滑動時的數據變化       這是頁面一向頁面二滑動時候的數據記錄:   我們可以發現第一個參數值直接從0->1,第二個參數值從0.0依次增加到0.9xx無限靠近1,然後頁面到達第二頁它又恢復成了0,第三個參數從1開始累積到300+(這個我們不去關注)       這是頁面二向頁面三滑動時候的數據記錄:   我們可以發現第一個參數值直接從1->2,第二個參數值從0.0依次增加到0.9xx無限靠近1,然後頁面到達第二頁它又恢復成了0,第三個參數從1開始累積到300+(這個我們不去關注)       因此我們可以發現一個規律:   當ViewPager頁面值為0(第一頁)且當參數一為0時,頁面的狀態時從  第一頁到第二頁   當ViewPager頁面值為1(第二頁)且當參數一為1時,頁面的狀態時從  第一頁到第二頁   以此類推,大家可以自己打印出來看看,對這些數據比較有感覺,由於文章篇幅問題,這裡就不再貼圖了。       我們可以利用第二個參數從0.0推薦遞增到1,這個數據來控制左外邊距(在第一頁時左外邊距為0,第二頁時左外邊距為1/3屏幕寬,第三頁時左外邊距為2/3屏幕寬)   由此推導出的公式為:   向左滑時:當前頁數*屏幕1/3寬+onPageScrolled方法第二個參數*屏幕1/3寬   向右滑時:當前頁數*屏幕1/3寬-(1-onPageScrolled方法第二個參數)*屏幕1/3寬           2、由於這裡使用到了Fragment,這裡就不再和以往一樣繼承Activity,這裡需要繼承Activity的子類FragmentActivity。               由於3個Fragment的代碼幾乎一致,所以這裡只給出Fragment1.java   復制代碼  1 package com.example.weixin_test;  2   3 import android.os.Bundle;  4 import android.support.annotation.Nullable;  5 import android.support.v4.app.Fragment;  6 import android.view.LayoutInflater;  7 import android.view.View;  8 import android.view.ViewGroup;  9  10 public class Fragment1 extends Fragment { 11     @Override 12     public View onCreateView(LayoutInflater inflater, 13             @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 14         return inflater.inflate(R.layout.fragment1, container, false); 15     } 16  17 } 復制代碼  來講一下關於這個類的說明:   1、Fragment一般是作為Activity界面的一部分,它把Layout對象嵌入到了Activity之中,若要對一個Fragment提供Layout對象必須去調用一個onCreateView()方法,它的返回值是一個View對象,這個方法為我們提供了一個LayoutInflater便於我們把XML布局文件轉換成View對象。       2、onCreateView()方法中:   container參數是用來存放Fragment的layout。   saveInstanceState參數是一個Bundle,跟Activity的onCreate()中Bundle差不多,用於狀態恢復。       3、inflate()方法中有三個參數:   1:layout的資源id。   2:存放fragment的layout的ViewGroup。   3:這個布爾值是代表是否在創建Fragment的layout期間,把layout附加到container上,由於系統已經把layout對象存放在了ViewGroup中,所以這裡為false。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved