​http://ouyangfeng521.iteye.com/blog/1112905​


在玩MM时看到里面的tab 很酷 就学着做了一个

 

效果如下:


android模仿移动MM Tab 点击 背景 滑动效果_layout

上代码 现在我把他搞成了一个控件了 用法跟ListView 差不多

控件类:

 


Java代码   ​



1. package
2.
3. import
4.
5. import
6. import
7. import
8. import
9. import
10. import
11. import
12. import
13. import
14. import
15.
16. import
17.
18. public class ScrcoolTab extends
19.
20. private int top,bottom; // 该布局的top与bottom
21.
22. private LayoutInflater mInflater; // 控件xml 解析器
23.
24. private OnItemClickListener clickListener; // 点击事件
25.
26. private int defaultTab; // 默认选中第几个
27.
28. private boolean move = false; //标识是否可以移动,主要为了实现一个项点击后,用户不能点击第二个
29.
30. private HashMap<Integer, Integer []> childPointCache = new
31.
32. int childWidth = 0; //因为要控件居中,所以计算出每个控件可以有多少宽度
33.
34. private int gleft,currentwidth,currentleft; // 上一个选中项的左坐标 当前点击的控件的宽度 当前点击的控件的左坐标
35.
36. private Integer [] current = {0,0}; //tab 背景的坐标
37.
38. private Drawable tabpictrue; //tab 移动的背景图片
39.
40. private int tabpicpadding ; //tab 背景图片大于控件多少
41.
42. private int moveunit; // tab图片第次移动多少
43.
44. private int duration;//移动速度
45.
46. public
47. super(context, attrs);
48. mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
49. TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ScrcoolTab);
50. final int
51. for (int i = 0; i < N; i++) {
52. int
53. switch
54. case
55. tabpictrue = (Drawable) a.getDrawable(i);
56. break;
57. case
58. 5);
59. break;
60. case
61. 5);
62. break;
63. case
64. 100);
65. break;
66. }
67. }
68. "ScrcoolTab", "construt");
69. }
70.
71. @Override
72. protected void
73. super.onDraw(canvas);
74. if( ! isDrawItem()) return;
75. 0] -tabpicpadding ,top , current[0] + currentwidth + tabpicpadding , bottom);
76. tabpictrue.draw(canvas);
77. }
78.
79.
80. @Override
81. protected void onLayout(boolean changed, int l, int t, int r, int
82. "ScrcoolTab", "onLayout");
83. super.onLayout(changed, l, t, r, b);
84. top = t;
85. bottom = b;
86. int
87. if(0 == count) return;
88. int
89. childWidth = w / count;
90. null;
91. null;
92. for(int i = 0;i < count;i++){
93. v = getChildAt(i);
94. points = scalcChildPoint(v, i);
95. 0] ,((bottom - top) - v.getHeight()) /2 , points[1], ((bottom - top) - v.getHeight()) /2
96. new
97. new
98.
99. @Override
100. public void
101. if( !move ){
102. true;
103. itemOnclick(v ,((Integer)v.getTag()).intValue() );
104. }
105. }
106.
107. });
108. }
109. //set default tab
110. View mDefaultTab = getChildAt(defaultTab);
111. if(null
112. itemOnclick(v , defaultTab);
113. }
114. }
115.
116. public synchronized void update(View v ,int
117. "ScrcoolTab", "update");
118. new
119. 0];
120. // 得到当前点击的控件的宽度
121. //如果重复点一个项,则不会移动
122. if(gleft == current [0]) {
123. false; //下一个点击可以移动
124. return
125. }
126. //通知设置监听
127. "ScrcoolTab", "tab moved");
128. defaultTab = position;
129. final boolean pathleft = gleft > current[0] ? true : false;//判断是向左还是向右
130. final int num = Math.abs((gleft - current[0]) / moveunit);
131. int i = 0;
132. while( i < num){
133. if( pathleft ){
134. gleft = gleft - moveunit;
135. 0] = gleft;
136. else{
137. gleft = gleft + moveunit;
138. 0] = gleft;
139. }
140. try
141. Thread.sleep(duration);
142. catch
143. e.printStackTrace();
144. }
145. "ScrcoolTab", "Thread: left"+current[0]);
146. postInvalidate();
147. i++;
148. }
149. //校正 因为除数可能有精度损失
150. if(gleft != currentleft){
151. 0] = currentleft;
152. postInvalidate();
153. }
154. 0];
155. false;
156. }
157.
158. /**
159. * 当点击一项时,移动背景坐标
160. * @param v
161. */
162. public synchronized void itemOnclick(final View v ,final int
163. "ScrcoolTab", "itemOnclick position:"
164.
165. new Thread( new
166.
167. @Override
168. public void
169. update (v , position);
170. }
171.
172. }).start();
173.
174. }
175.
176. /**
177. * 设置数据适配器
178. * @param adapter
179. */
180. public void
181. "ScrcoolTab", "setAdapter");
182. if(null != adapter && 0 != adapter.getResource() && null
183. null;
184. for(String str : adapter.getData()){
185. this ,false);
186. if(view instanceof
187. this.addView(view);
188. }
189. }
190. }
191.
192. /**
193. * 计算每个子控件的坐标
194. * @param view
195. * @param position
196. * @return
197. */
198. public Integer [] scalcChildPoint(View view ,int
199. new Integer [2];
200. 0] = childWidth * position + (childWidth - view.getWidth())/2;
201. 1] = points [0] + view.getWidth();
202. "ScrcoolTab", "scalcChildPoint position :" + position + "left:" + points [0] + "right:" + points [1]);
203. new
204. return
205. }
206.
207. /**
208. * 是否画背景图片taab
209. * @return
210. */
211. private boolean
212. if(current [0] > 0 ) return true;
213. else return false;
214. }
215.
216. /**
217. * 设置默认选中
218. * @param tab
219. */
220. public void setDefaultTab(int
221. "ScrcoolTab", "setDefaultTab");
222. this.defaultTab = tab;
223. }
224.
225. @Override
226. protected void
227. super.onAttachedToWindow();
228. "ScrcoolTab", "onAttachedToWindow");
229. }
230.
231. /**
232. * 得到当前选中的项
233. * @return
234. */
235. public int
236. return
237. }
238.
239. /**
240. * 当点一项时 调用事件
241. * @param clickListener
242. */
243. public void
244. this.clickListener = clickListener;
245. }
246.
247. /**
248. * 事件接口
249. *
250. */
251. public interface
252. void onItemClickListener(View v , int
253. }
254. }


 

 

控件适配器类:


Java代码   ​


1. package
2.
3. public class
4.
5. private int
6.
7. private
8.
9. public int
10. return
11. }
12.
13. public void setResource(int
14. this.resource = resource;
15. }
16.
17. public
18. return
19. }
20.
21. public void
22. this.data = data;
23. }
24.
25. public ScrcoolTabAdapter(int
26. super();
27. this.resource = resource;
28. this.data = data;
29. }
30. }


 用法:

xml 布局文件:


Xml代码   ​




    1. <?xml version="1.0" encoding="utf-8"?>
    2. <LinearLayout xmlns:android="http:///apk/res/android"
    3. xmlns:control="http:///apk/res/com.test.scrolltab"
    4. android:orientation="vertical" android:layout_width="fill_parent"
    5. android:layout_height="fill_parent" >
    6. <com.test.scrolltab.control.ScrcoolTab
    7. android:id="@+id/scrcoolTab" android:layout_height="wrap_content"
    8. android:layout_width="fill_parent" android:gravity="center_vertical"
    9. control:tabpictrue="@drawable/bg_item_t" android:background="@drawable/bg_t"
    10. control:tabpicpadding="5dip" control:moveunit="15dip" control:duration="50">
    11.
    12. </com.test.scrolltab.control.ScrcoolTab>
    13.
    14. </LinearLayout>


      一个tab的布局:


    Xml代码   ​



    1. <?xml version="1.0" encoding="utf-8"?>
    2. <TextView android:layout_width="wrap_content"
    3. xmlns:android="http:///apk/res/android"
    4. android:layout_height="wrap_content" style="@style/text_style"
    5. android:onClick="itemOnclick" />


     activity调用代码:


    Java代码   ​



    1. package
    2.
    3. import
    4. import
    5. import
    6. import
    7. import
    8.
    9. import
    10. import
    11. import
    12.
    13. public class ScrollTabActivity extends
    14.
    15. private
    16.
    17. @Override
    18. public void
    19. super.onCreate(savedInstanceState);
    20. setContentView(R.layout.main);
    21. scrcoolTab = (ScrcoolTab) findViewById(.scrcoolTab);
    22. new ScrcoolTabAdapter(R.layout.tab_item,new String []{"进入首页","用户调研","下载中心","联系我们"}));
    23. new
    24.
    25. @Override
    26. public void onItemClickListener(View v, int
    27. // Toast.makeText(ScrollTabActivity.this, "点击了" + position, Toast.LENGTH_SHORT).show();
    28. }
    29. });
    30. // scrcoolTab.setDefaultTab(1);
    31. }
    32.
    33. public void
    34. ViewParent parent = v.getParent().getParent();
    35. if(parent instanceof
    36. ScrcoolTab tab = (ScrcoolTab) parent;
    37. tab.postInvalidate();
    38. }
    39. System.out.println(parent);
    40. }
    41.
    42. @Override
    43. public void
    44. super.finish();
    45. Process.killProcess(Process.myPid());
    46. }
    47.
    48. }