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>
来源:https://www.cnblogs.com/zealotrouge/archive/2013/04/09/3009927.html