Tab頁很適合用來做平行功能之間的引導,而各功能頁面用ViewPager來展示會顯得比較平滑、過渡自然,所以自然就有了許多軟件將二者結合,用於展示主功能界面,比如網易新聞和360優化大師的主界面,那么下面就來做一個這樣的帶Tab頁的ViewPager吧~
基本需求:1,點擊Tab頁,ViewPager做出相應滑動,且Tab頁中有表示切換的動畫
2,滑動ViewPager,Tab頁中有表示切換的動畫
3,Tab頁可以動態添加並自行計算所占寬度
基本思路是:用一個橫向LinearLayout管理動態加載的Tab頁,下方是ViewPager,再用代碼將二者關聯起來就可以了,代碼如下
1 public class TabViewPager extends LinearLayout 2 { 3 /* 數據段begin */ 4 public final static String TAG = "TabViewPager"; 5 private Context mContext; 6 7 private LinearLayout mTabHost; 8 private ImageView mUnderline; 9 private ViewPager mViewPager; 10 11 //tab及underline寬度,也是underline的最小移動距離 12 private int mTabWidth; 13 /* 數據段end */ 14 15 /* 函數段begin */ 16 public TabViewPager(Context context, AttributeSet attrs) 17 { 18 super(context, attrs); 19 20 mContext = context; 21 22 inflate(mContext, R.layout.tab_view_pager, this); 23 initViews(); 24 } 25 26 private void initViews() 27 { 28 mTabHost = (LinearLayout) findViewById(R.id.tab_host); 29 mUnderline = (ImageView) findViewById(R.id.tab_underline); 30 mViewPager = (ViewPager) findViewById(R.id.view_pager); 31 } 32 33 public void initTabs(String[] tabTitles, int parentWidth) 34 { 35 LinearLayout.LayoutParams tabHostLayoutParams; 36 TextView tab; 37 38 mTabWidth = parentWidth / tabTitles.length; 39 40 //設置寬度 41 if (tabTitles.length > 0) 42 { 43 tabHostLayoutParams = new LinearLayout.LayoutParams(mTabWidth, LinearLayout.LayoutParams.WRAP_CONTENT); 44 } 45 else 46 { 47 return; 48 } 49 50 //動態添加tab 51 for (int loopVal = 0; loopVal < tabTitles.length; loopVal++) 52 { 53 tab = new TextView(mContext); 54 tab.setText(tabTitles[loopVal]); 55 tab.setTextSize(22); 56 tab.setTextColor(getResources().getColor(R.color.white)); 57 58 tabHostLayoutParams.weight = 1; 59 tabHostLayoutParams.gravity = Gravity.CENTER_VERTICAL; 60 tab.setLayoutParams(tabHostLayoutParams); 61 tab.setGravity(Gravity.CENTER); 62 63 tab.setOnClickListener(new TabOnClickListener(loopVal)); 64 65 mTabHost.addView(tab); 66 } 67 68 //設置underline寬度,使得下划線與tab寬度保持一致 69 FrameLayout.LayoutParams frameLayoutParams = new FrameLayout.LayoutParams(mTabWidth, FrameLayout.LayoutParams.WRAP_CONTENT); 70 frameLayoutParams.gravity = Gravity.BOTTOM; 71 mUnderline.setLayoutParams(frameLayoutParams); 72 mUnderline.setBackgroundDrawable(getResources().getDrawable(R.drawable.tab_view_pager_underline)); 73 } 74 75 public void setAdapter(PagerAdapter pagerAdapter) 76 { 77 mViewPager.setAdapter(pagerAdapter); 78 //滑動viewPager時也要執行mUnderline的移動動畫 79 mViewPager.setOnPageChangeListener(new OnPageChangeListener() 80 { 81 private int currentPosition = -1; 82 private int nextPosition = -1; 83 84 @Override 85 public void onPageSelected(int position) 86 { 87 nextPosition = position; 88 //mUnderline的移動動畫 89 mUnderline.startAnimation(new UnderlineTranslateAnimation(currentPosition * mTabWidth, nextPosition * mTabWidth, 0, 0)); 90 } 91 92 @Override 93 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) 94 { 95 currentPosition = position; 96 } 97 98 @Override 99 public void onPageScrollStateChanged(int state) 100 { 101 } 102 }); 103 } 104 105 public void setCurrentItem(int position) 106 { 107 //記錄當前的位置后再設置選中位置 108 int currentPosition = mViewPager.getCurrentItem(); 109 mViewPager.setCurrentItem(position); 110 int nextPosition = mViewPager.getCurrentItem(); 111 112 //mUnderline的移動動畫 113 mUnderline.startAnimation(new UnderlineTranslateAnimation(currentPosition * mTabWidth, nextPosition * mTabWidth, 0, 0)); 114 } 115 /* 函數段end */ 116 117 /* 內部類begin */ 118 private class TabOnClickListener implements OnClickListener 119 { 120 private int viewPosition = -1; 121 122 public TabOnClickListener(int position) 123 { 124 viewPosition = position; 125 } 126 127 @Override 128 public void onClick(View v) 129 { 130 if (AppEnv.bAppdebug) 131 { 132 Log.d(TAG, "tab onClick --> " + ((TextView) v).getText()); 133 } 134 135 setCurrentItem(viewPosition); 136 } 137 } 138 139 private class UnderlineTranslateAnimation extends TranslateAnimation 140 { 141 public UnderlineTranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) 142 { 143 super(fromXDelta, toXDelta, fromYDelta, toYDelta); 144 145 setFillAfter(true); 146 } 147 148 } 149 /* 內部類end */ 150 }
這樣,只需調用initTabs()來設置Tab頁,和setAdapter()來設置適配器即可使用。
相應布局代碼
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="fill_parent" 5 android:layout_height="fill_parent" 6 android:orientation="vertical" 7 tools:ignore="ContentDescription" > 8 9 <FrameLayout 10 android:layout_width="fill_parent" 11 android:layout_height="0dp" 12 android:layout_weight="1" > 13 14 <LinearLayout 15 android:id="@+id/tab_host" 16 android:layout_width="fill_parent" 17 android:layout_height="wrap_content" 18 android:layout_gravity="center_vertical" 19 android:orientation="horizontal" > 20 </LinearLayout> 21 22 <ImageView 23 android:id="@+id/tab_underline" 24 android:layout_width="0dp" 25 android:layout_height="0dp" /> 26 </FrameLayout> 27 28 <android.support.v4.view.ViewPager 29 android:id="@+id/view_pager" 30 android:layout_width="fill_parent" 31 android:layout_height="0dp" 32 android:layout_weight="7" /> 33 34 </LinearLayout>
