一、效果演示及分析
我們直接看兩幅圖。如下:
上兩幅圖實現的效果就是:
(1)手指左右滑動時,中間的布局呈現不同的效果。而且下面的按鈕也會做相應的改變。
(2)我們也可以不左右滑動,直接點擊下面的按鈕來改變中間的布局。
這就是android開發中經常要用到的Tab效果,可以最大限度的使用屏幕資源。中間的View可以顯示復雜又不同的界面效果。這里為了學習上的簡潔,我每一個界面都只是實現了一個TextView效果而已,但這足以將利用ViewPager實現Tab的原理將清楚了。
我們很容易想到,上面的布局可以由線程布局來完成,上、中、下分別是三個線性布局,而下面的一個布局里面裝了四個按鈕而已。因此編寫布局並不難,下面我們就開始書寫吧。
二、准備相應的資源
我們只需要准備一些圖片即可,即每一個按鈕都有兩種狀態,暗色和亮色。簡單利用PS就可以處理了。
三、開始寫實際的代碼
(1)首先我們把上面和下面的布局構建完成。
上面的布局就是 一個線性布局,中間放了一個TextView而已。我們起名為top.xml,代碼很簡單,如下:
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="65dp" 5 android:background="#fffccc" 6 android:gravity="center"> 7 8 <TextView 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:text="Tab試驗" 12 android:textSize="25dp"/> 13 14 </LinearLayout>
下面的布局采用一個總的線性布局安水平方向擺放四個布局,每一個布局里再放置相應的圖片和文字。我們起名為bottum.xml。代碼如下:
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="wrap_content" 5 android:background="#ccffff" 6 > 7 8 <LinearLayout 9 android:id="@+id/lay_hudie" 10 android:layout_width="0dp" 11 android:layout_height="match_parent" 12 android:layout_weight="1" 13 android:orientation="vertical" 14 android:gravity="center"> 15 16 <ImageButton 17 android:id="@+id/ibtn_hudie" 18 android:layout_width="wrap_content" 19 android:layout_height="wrap_content" 20 android:clickable="false" 21 android:src="@drawable/hudie"/> 22 <TextView 23 android:layout_width="wrap_content" 24 android:layout_height="wrap_content" 25 android:text="蝴蝶"/> 26 " 27 </LinearLayout> 28 29 <LinearLayout 30 android:id="@+id/lay_set" 31 android:layout_width="0dp" 32 android:layout_height="match_parent" 33 android:layout_weight="1" 34 android:orientation="vertical" 35 android:gravity="center"> 36 37 <ImageButton 38 android:id="@+id/ibtn_set" 39 android:clickable="false" 40 android:layout_width="wrap_content" 41 android:layout_height="wrap_content" 42 android:src="@drawable/set"/> 43 <TextView 44 android:layout_width="wrap_content" 45 android:layout_height="wrap_content" 46 android:text="設置"/> 47 48 </LinearLayout> 49 <LinearLayout 50 android:id="@+id/lay_user" 51 android:layout_width="0dp" 52 android:layout_height="match_parent" 53 android:layout_weight="1" 54 android:orientation="vertical" 55 android:gravity="center"> 56 57 <ImageButton 58 android:id="@+id/ibtn_user" 59 android:clickable="false" 60 android:layout_width="wrap_content" 61 android:layout_height="wrap_content" 62 android:src="@drawable/user"/> 63 <TextView 64 android:layout_width="wrap_content" 65 android:layout_height="wrap_content" 66 android:text="用戶"/> 67 68 </LinearLayout> 69 <LinearLayout 70 android:id="@+id/lay_yang" 71 android:layout_width="0dp" 72 android:layout_height="match_parent" 73 android:layout_weight="1" 74 android:orientation="vertical" 75 android:gravity="center"> 76 77 <ImageButton 78 android:id="@+id/ibtn_yang" 79 android:clickable="false" 80 android:layout_width="wrap_content" 81 android:layout_height="wrap_content" 82 android:src="@drawable/yang"/> 83 <TextView 84 android:layout_width="wrap_content" 85 android:layout_height="wrap_content" 86 android:text="羊羊"/> 87 88 </LinearLayout> 89 90 </LinearLayout>
注意:ImageButton里的點擊事件要設定為false。這是因為在后面我們要對它的父view,即相應的LinearLayout設置點擊事件,為了保證點擊事件一定能被LinearLayout捕捉到,所以要將ImageButton的點擊事件設定為false。否則,如果你點擊ImageButton那一部分的屏幕區域,因為它是 放在LinearLayout里面,所以點擊事件先被LinearLayout捕捉。但是LinearLayout發現他里面有一個按鈕也是可以處理點擊事件的,就會把點擊事件傳遞給它處理(這是android里的規定)。但是我們卻沒有給ImageButton設定點擊事件,因為就會造成點擊事件不響應。所以為了讓點擊事件不向下傳遞,我們就將按鈕的點擊事件設為fasle,即讓它不能處理點擊事件。而TextView是本身就不能響應點擊事件的,因為我們不用對它設定。
(2)搭建主界面,其中就包括ViewPager
現在我們將主界面的頭和尾(即上面寫的),以及中間的ViewPager搭建起來。取名為activity_main.xml代碼也很簡單,如下:
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 > 7 8 <include layout="@layout/top"/> 9 10 <android.support.v4.view.ViewPager 11 android:id="@+id/vp" 12 android:layout_width="match_parent" 13 android:layout_height="0dp" 14 android:layout_weight="1" > 15 </android.support.v4.view.ViewPager> 16 17 <include layout="@layout/bottum"/>" 18 </LinearLayout>
注意:在這里我們應當記住,include語句是怎樣引入布局的。還有ViewPager是怎樣引入的。
(3)編寫所有的Tab界面
從效果圖上,我們可以看到Tab界面有4個(即中間黑色每滑動一次就出現不同的TextView)。很簡單,我們編寫四個就可以了,分別命名為Tab01.xml,Tab02.xml,Tab03.xml,Tab04.xml。代碼如下:
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:gravity="center"> 6 7 <TextView 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:text="這是一只蝴蝶" 11 android:textSize="25dp"/> 12 13 </LinearLayout>
其他的一樣,就是把中間的TextView顯示的字改了一下而已。我就不重復了。
(4)寫入活動中展示出來。
這一步還是比較復雜的。具體包括,要為按鈕設定點擊事件,要為ViewPager寫適配器,並且要為它編寫Item改變時的事件。具體看代碼:
1 import java.util.ArrayList; 2 import java.util.List; 3 import java.util.zip.Inflater; 4 import android.os.Bundle; 5 import android.app.Activity; 6 import android.support.v4.view.PagerAdapter; 7 import android.support.v4.view.ViewPager; 8 import android.support.v4.view.ViewPager.OnPageChangeListener; 9 import android.view.LayoutInflater; 10 import android.view.Menu; 11 import android.view.View; 12 import android.view.View.OnClickListener; 13 import android.view.ViewGroup; 14 import android.widget.ImageButton; 15 import android.widget.LinearLayout; 16 17 public class MainActivity extends Activity implements OnClickListener{ 18 19 20 private ViewPager vp; 21 22 private PagerAdapter mAdapter;//適配器 23 24 private List<View> mViews = new ArrayList<View>();//數據集 25 26 private LinearLayout mlay1; 27 private LinearLayout mlay2; 28 private LinearLayout mlay3; 29 private LinearLayout mlay4; 30 31 private ImageButton img1; 32 private ImageButton img2; 33 private ImageButton img3; 34 private ImageButton img4; 35 36 37 38 protected void onCreate(Bundle savedInstanceState) { 39 super.onCreate(savedInstanceState); 40 setContentView(R.layout.activity_main); 41 42 initView(); 43 44 initEvent();//用來 初始化點擊事件 45 46 47 } 48 49 50 51 //初始化點擊事件 52 private void initEvent() { 53 54 55 mlay1.setOnClickListener(this); 56 mlay2.setOnClickListener(this); 57 mlay3.setOnClickListener(this); 58 mlay4.setOnClickListener(this); 59 60 //設置滑動ViewPager時的事件 61 62 vp.setOnPageChangeListener(new OnPageChangeListener() { 63 64 65 //主要在這個方法里操作,當選中相應的view時一系列的響應事件 66 public void onPageSelected(int arg0) { 67 68 resetImg(); 69 int item = vp.getCurrentItem(); 70 switch(item){ 71 72 case 0: 73 img1.setImageResource(R.drawable.hudie2); 74 break; 75 case 1: 76 img2.setImageResource(R.drawable.set2); 77 break; 78 case 2: 79 img3.setImageResource(R.drawable.user2); 80 break; 81 case 3: 82 img4.setImageResource(R.drawable.yang2); 83 break; 84 } 85 86 } 87 88 89 public void onPageScrolled(int arg0, float arg1, int arg2) { 90 // TODO Auto-generated method stub 91 92 } 93 94 95 public void onPageScrollStateChanged(int arg0) { 96 // TODO Auto-generated method stub 97 98 } 99 }); 100 } 101 102 103 104 //該方法初始化各個view 105 private void initView() { 106 107 vp = (ViewPager) findViewById(R.id.vp); 108 109 //獲取底部的各個線性布局 110 mlay1 = (LinearLayout) findViewById(R.id.lay_hudie); 111 mlay2 = (LinearLayout) findViewById(R.id.lay_set); 112 mlay3 = (LinearLayout) findViewById(R.id.lay_user); 113 mlay4 = (LinearLayout) findViewById(R.id.lay_yang); 114 115 116 //獲取各個imageView 117 img1 = (ImageButton) findViewById(R.id.ibtn_hudie); 118 img2 = (ImageButton) findViewById(R.id.ibtn_set); 119 img3 = (ImageButton) findViewById(R.id.ibtn_user); 120 img4 = (ImageButton) findViewById(R.id.ibtn_yang); 121 122 123 //下面將view加入到數據集中 124 View v1 = LayoutInflater.from(this).inflate(R.layout.tab01, null); 125 View v2 = LayoutInflater.from(this).inflate(R.layout.tab02, null); 126 View v3 = LayoutInflater.from(this).inflate(R.layout.tab03, null); 127 View v4 = LayoutInflater.from(this).inflate(R.layout.tab04, null); 128 129 mViews.add(v1); 130 mViews.add(v2); 131 mViews.add(v3); 132 mViews.add(v4); 133 134 135 //然后再根據數據集配置適配器 136 137 mAdapter = new PagerAdapter() { 138 139 140 //銷毀item 141 public void destroyItem(ViewGroup container, int position, 142 Object object) { 143 144 container.removeView(mViews.get(position)); 145 } 146 147 148 //初始化item 149 public Object instantiateItem(ViewGroup container, int position) { 150 151 View view = mViews.get(position); 152 container.addView(view); 153 return view; 154 } 155 156 157 //TODO 158 //這個方法是什么意思,有待進一步查解 159 public boolean isViewFromObject(View arg0, Object arg1) { 160 161 return arg0 == arg1; 162 } 163 164 165 //獲得適配的總數目 166 public int getCount() { 167 168 return mViews.size(); 169 } 170 }; 171 172 173 //為ViewPager設置適配器 174 175 vp.setAdapter(mAdapter); 176 177 178 } 179 180 181 182 183 //點擊事件,會把執行點擊的控件傳進來,即view 184 public void onClick(View v) { 185 resetImg(); 186 switch(v.getId()){ 187 188 case R.id.lay_hudie: 189 vp.setCurrentItem(0);//設置ViewPager當前的view 190 img1.setImageResource(R.drawable.hudie2); 191 break; 192 case R.id.lay_set: 193 vp.setCurrentItem(1);//設置ViewPager當前的view 194 img2.setImageResource(R.drawable.set2); 195 break; 196 case R.id.lay_user: 197 vp.setCurrentItem(2);//設置ViewPager當前的view 198 img3.setImageResource(R.drawable.user2); 199 break; 200 case R.id.lay_yang: 201 vp.setCurrentItem(3);//設置ViewPager當前的view 202 img4.setImageResource(R.drawable.yang2); 203 break; 204 205 } 206 } 207 208 //該方法用來將圖片還原到初始狀態 209 private void resetImg(){ 210 img1.setImageResource(R.drawable.hudie); 211 img2.setImageResource(R.drawable.set); 212 img3.setImageResource(R.drawable.user); 213 img4.setImageResource(R.drawable.yang); 214 } 215 }
好了,所有的工作完成了,我們可以運行程序看看效果了。
四、總結
來看看編寫代碼的過程中,有那些重要的android知識。
(1)在一個布局中引入另外一個布局,可采用如下語句:
<include layout="@layout/top"/>
(2)在布局中書寫ViewPager的代碼,關鍵是要記住它的包名:
<android.support.v4.view.ViewPager android:id="@+id/vp" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > </android.support.v4.view.ViewPager>
(3)ViewPager的適配器,除了書寫它默認的兩個方法外,還要重寫如下兩個方法:
public void destroyItem(ViewGroup container, int position, Object object) public Object instantiateItem(ViewGroup container, int position)
(4)當ViewPager狀態發生改變時,我們想做出一系列響應,應該設置監聽接口,並主要在onPageSelected進行操作。例如:
1 vp.setOnPageChangeListener(new OnPageChangeListener() { 2 3 4 //主要在這個方法里操作,當選中相應的view時一系列的響應事件 5 public void onPageSelected(int arg0) { 6 int item = vp.getCurrentItem(); 7 switch(item){ 8 case 0: 9 img1.setImageResource(R.drawable.hudie2); 10 break; 11 case 1: 12 img2.setImageResource(R.drawable.set2); 13 break; 14 case 2: 15 img3.setImageResource(R.drawable.user2); 16 break; 17 case 3: 18 img4.setImageResource(R.drawable.yang2); 19 break; 20 21 } 22 public void onPageScrolled(int arg0, float arg1, int arg2) { 23 } 24 public void onPageScrollStateChanged(int arg0) { 25 26 } 27 }); 28 }