Indicator确实是个老梗了...
有重写HorizontalScrollView的,有重写LinearLayout。
这个是重写LinearLayout的哦,往LinearLayout里add TextView用作tab标签,在LinearLayout底部画一个矩形当作指示器。
ViewPager滚动的时候用简单的小学加减乘除混合运算来机选这个矩形位置,然后滚动就好了
属性
[html]
1. <?xml version="1.0" encoding="utf-8"?>
2. <resources>
3.
4. <attr name="tab_color_normal" format="color" />
5. <attr name="tab_color_light" format="color" />
6. <attr name="cursor_color" format="color" />
7. <attr name="cursor_height" format="dimension" />
8.
9. <declare-styleable name="Indicator">
10. <attr name="tab_color_normal" />
11. <attr name="tab_color_light" />
12. <attr name="cursor_color" />
13. <attr name="cursor_height" />
14. </declare-styleable>
15.
16. </resources>
Indicator.java 关键的地方都谢了注释
[java]
1. package com.mingwei.indicator.view;
2.
3. import java.util.List;
4.
5. import android.annotation.TargetApi;
6. import android.content.Context;
7. import android.content.res.TypedArray;
8. import android.graphics.Canvas;
9. import android.graphics.Color;
10. import android.graphics.Paint;
11. import android.graphics.Paint.Style;
12. import android.graphics.Rect;
13. import android.os.Build;
14. import android.support.v4.view.ViewPager;
15. import android.support.v4.view.ViewPager.OnPageChangeListener;
16. import android.util.AttributeSet;
17. import android.util.TypedValue;
18. import android.view.Gravity;
19. import android.view.View;
20. import android.view.View.OnClickListener;
21. import android.widget.HorizontalScrollView;
22. import android.widget.LinearLayout;
23. import android.widget.TextView;
24.
25. import com.mingwei.indicator.R;
26.
27. @TargetApi(Build.VERSION_CODES.HONEYCOMB)
28. public class Indicator extends LinearLayout implements OnClickListener, OnPageChangeListener {
29. /**
30. * 绘制时用的画笔
31. */
32. private Paint mPaint;
33. /**
34. * 默认颜色
35. */
36. private int mCursorColor;
37. /**
38. * 滚动的指示器的矩形范围
39. */
40. private Rect mRect = new Rect();
41. /**
42. * 滚动游标的绘制范围
43. */
44. private int mL, mR, mT, mB;
45. /**
46. * 最多可见的游标数
47. */
48. private int mVisiableTabCount = 4;
49. /**
50. * 游标高度
51. */
52. private int mCursorHeight = 6;
53. /**
54. * tab的宽度
55. */
56. private int mTabWidth;
57. /**
58. * 选中和非选中状态的标签文字颜色
59. */
60. private int mTabColorNormal;
61. private int mTabColorLight;
62. /**
63. * 水平滚动的距离
64. */
65. private float mTranslationX;
66. /**
67. * 需要监听ViewPager动作来跟新游标
68. */
69. private ViewPager mViewPager;
70.
71. public Indicator(Context context) {
72. this(context, null);
73. }
74.
75. public Indicator(Context context, AttributeSet attrs) {
76. this(context, attrs, 0);
77. }
78.
79. public Indicator(Context context, AttributeSet attrs, int defStyleAttr) {
80. super(context, attrs, defStyleAttr);
81. initAttr(context, attrs, defStyleAttr);
82. new Paint();
83. mPaint.setColor(mCursorColor);
84. true);
85. mPaint.setStyle(Style.FILL);
86. }
87.
88. private void initAttr(Context context, AttributeSet attrs, int defStyleAttr) {
89. TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.Indicator);
90. mTabColorNormal = array.getColor(R.styleable.Indicator_tab_color_normal, Color.BLACK);
91. mTabColorLight = array.getColor(R.styleable.Indicator_tab_color_light, Color.WHITE);
92. mCursorColor = array.getColor(R.styleable.Indicator_cursor_color, Color.BLACK);
93. mCursorHeight = array.getDimensionPixelSize(R.styleable.Indicator_cursor_height, mCursorHeight);
94. array.recycle();
95. }
96.
97. @Override
98. protected void onFinishInflate() {
99. super.onFinishInflate();
100. }
101.
102. @Override
103. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
104. super.onSizeChanged(w, h, oldw, oldh);
105.
106. int count = getChildCount();
107. if (count == 0) {
108. return;
109. }
110. mTabWidth = getWidth() / mVisiableTabCount;
111. for (int i = 0; i < count; i++) {
112. View view = getChildAt(i);
113. LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
114. 0;
115. params.width = mTabWidth;
116. params.height = getHeight() - mCursorHeight;
117. view.setLayoutParams(params);
118. }
119. 0;
120. mT = getHeight() - mCursorHeight;
121. mR = mTabWidth;
122. mB = getHeight();
123. new Rect(mL, mT, mR, mB);
124. }
125.
126. @Override
127. protected void dispatchDraw(Canvas canvas) {
128. super.dispatchDraw(canvas);
129. canvas.save();
130. 0);
131. canvas.drawRect(mRect, mPaint);
132. canvas.restore();
133.
134. }
135.
136. private void scroll(int position, float offset) {
137. mTranslationX = getWidth() / mVisiableTabCount * (position + offset);
138. /**
139. * 当tab数大于可见数目的时候,整个容器滚动
140. */
141. if (getChildCount() > mVisiableTabCount && offset > 0 && (position >= mVisiableTabCount - 2)) {
142. if (mVisiableTabCount != 1) {
143. /**
144. * 当tab等于可见数目不是倒数第二个时滚动容器,否则仍然滚动游标
145. */
146. if (position != getChildCount() - 2) {
147. 2)) * mTabWidth + (int) (offset * mTabWidth), 0);
148. }
149. else {
150. int) (offset * mTabWidth), 0);
151. }
152. }
153. invalidate();
154.
155. }
156.
157. public void setViewPager(ViewPager viewPager) {
158. mViewPager = viewPager;
159. this);
160. }
161.
162. public void setTabs(String[] tabs) {
163. removeAllViews();
164. for (String t : tabs) {
165. createChild(t);
166. }
167. 0);
168. view.setTextColor(mTabColorLight);
169. }
170.
171. public void setTabs(List<String> tabs) {
172. removeAllViews();
173. for (String t : tabs) {
174. createChild(t);
175. }
176. 0);
177. view.setTextColor(mTabColorLight);
178. }
179.
180. private void setTabLight(int arg0) {
181. int count = getChildCount();
182. for (int i = 0; i < count; i++) {
183. TextView view = (TextView) getChildAt(i);
184. if (i == arg0) {
185. view.setTextColor(mTabColorLight);
186. else {
187. view.setTextColor(mTabColorNormal);
188. }
189. }
190. }
191.
192. /**
193. * 创建子View
194. *
195. * @param text
196. */
197. private void createChild(String text) {
198. new TextView(getContext());
199. view.setText(text);
200. view.setGravity(Gravity.CENTER);
201. view.setTextColor(mTabColorNormal);
202. 16);
203. this);
204. view.setTag(getChildCount());
205. addView(view);
206. }
207.
208. @Override
209. public void onPageScrollStateChanged(int arg0) {
210.
211. }
212.
213. @Override
214. public void onPageScrolled(int arg0, float arg1, int arg2) {
215. scroll(arg0, arg1);
216. }
217.
218. @Override
219. public void onPageSelected(int arg0) {
220. setTabLight(arg0);
221. }
222.
223. @Override
224. public void onClick(View arg0) {
225. int i = (Integer) arg0.getTag();
226. mViewPager.setCurrentItem(i);
227. }
228.
229. }
XML使用
[html]
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. <com.mingwei.indicator.view.Indicator
8. xmlns:ming="http://schemas.android.com/apk/res-auto"
9. android:id="@+id/indicator"
10. android:layout_width="match_parent"
11. android:layout_height="45dp"
12. android:orientation="horizontal"
13. ming:cursor_color="@color/indicator_color"
14. ming:cursor_height="3dp"
15. ming:tab_color_light="@color/tab_color_checked"
16. ming:tab_color_normal="@color/tab_color_normal" >
17. </com.mingwei.indicator.view.Indicator>
18.
19. <android.support.v4.view.ViewPager
20. android:id="@+id/viewpager"
21. android:layout_width="match_parent"
22. android:layout_height="match_parent" >
23. </android.support.v4.view.ViewPager>
24.
25. </LinearLayout>
MainActivity
[java]
1. package com.mingwei.indicator;
2.
3. import java.util.ArrayList;
4. import java.util.Arrays;
5. import java.util.List;
6.
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.view.Menu;
13. import android.view.MenuItem;
14.
15. import com.mingwei.indicator.view.Indicator;
16.
17. public class MainActivity extends FragmentActivity {
18.
19. private ViewPager mViewPager;
20.
21. private List<Fragment> mFragments = new ArrayList<Fragment>();
22.
23. private FragmentPagerAdapter mAdapter;
24.
25. private List<String> mStrings = Arrays.asList("标签1", "标签2", "标签3", "标签4", "标签5");
26.
27. private Indicator mIndicator;
28.
29. @Override
30. protected void onCreate(Bundle savedInstanceState) {
31. super.onCreate(savedInstanceState);
32. setContentView(R.layout.activity_main);
33. initView();
34. }
35.
36. private void initView() {
37.
38. for (String tabs : mStrings) {
39. SimpleFragment fragment = SimpleFragment.newInstance(tabs);
40. mFragments.add(fragment);
41. }
42. mViewPager = (ViewPager) findViewById(R.id.viewpager);
43. mIndicator = (Indicator) findViewById(R.id.indicator);
44. mIndicator.setTabs(mStrings);
45. mIndicator.setViewPager(mViewPager);
46. new FragmentPagerAdapter(getSupportFragmentManager()) {
47.
48. @Override
49. public int getCount() {
50. return mFragments.size();
51. }
52.
53. @Override
54. public Fragment getItem(int position) {
55. return mFragments.get(position);
56. }
57. };
58. mViewPager.setAdapter(mAdapter);
59.
60. }
61.
62. @Override
63. public boolean onCreateOptionsMenu(Menu menu) {
64. // Inflate the menu; this adds items to the action bar if it is present.
65. getMenuInflater().inflate(R.menu.main, menu);
66. return true;
67. }
68.
69. @Override
70. public boolean onOptionsItemSelected(MenuItem item) {
71. // Handle action bar item clicks here. The action bar will
72. // automatically handle clicks on the Home/Up button, so long
73. // as you specify a parent activity in AndroidManifest.xml.
74. int id = item.getItemId();
75. if (id == R.id.action_settings) {
76. return true;
77. }
78. return super.onOptionsItemSelected(item);
79. }
80. }