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


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

效果如下:

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

控件类:

Java代码
  1. packagecom.test.scrolltab.control;
  2. importjava.util.HashMap;
  3. importandroid.content.Context;
  4. importandroid.content.res.TypedArray;
  5. importandroid.graphics.Canvas;
  6. importandroid.graphics.drawable.Drawable;
  7. importandroid.util.AttributeSet;
  8. importandroid.util.Log;
  9. importandroid.view.LayoutInflater;
  10. importandroid.view.View;
  11. importandroid.widget.LinearLayout;
  12. importandroid.widget.TextView;
  13. importcom.test.scrolltab.R;
  14. publicclassScrcoolTabextendsLinearLayout{
  15. privateinttop,bottom;//该布局的top与bottom
  16. privateLayoutInflatermInflater;//控件xml解析器
  17. privateOnItemClickListenerclickListener;//点击事件
  18. privateintdefaultTab;//默认选中第几个
  19. privatebooleanmove=false;//标识是否可以移动,主要为了实现一个项点击后,用户不能点击第二个
  20. privateHashMap<Integer,Integer[]>childPointCache=newHashMap<Integer,Integer[]>();
  21. intchildWidth=0;//因为要控件居中,所以计算出每个控件可以有多少宽度
  22. privateintgleft,currentwidth,currentleft;//上一个选中项的左坐标当前点击的控件的宽度当前点击的控件的左坐标
  23. privateInteger[]current={0,0};//tab背景的坐标
  24. privateDrawabletabpictrue;//tab移动的背景图片
  25. privateinttabpicpadding;//tab背景图片大于控件多少
  26. privateintmoveunit;//tab图片第次移动多少
  27. privateintduration;//移动速度
  28. publicScrcoolTab(Contextcontext,AttributeSetattrs){
  29. super(context,attrs);
  30. mInflater=(LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  31. TypedArraya=context.obtainStyledAttributes(attrs,R.styleable.ScrcoolTab);
  32. finalintN=a.getIndexCount();
  33. for(inti=0;i<N;i++){
  34. intattr=a.getIndex(i);
  35. switch(attr){
  36. caseR.styleable.ScrcoolTab_tabpictrue:
  37. tabpictrue=(Drawable)a.getDrawable(i);
  38. break;
  39. caseR.styleable.ScrcoolTab_tabpicpadding:
  40. tabpicpadding=a.getDimensionPixelSize(i,5);
  41. break;
  42. caseR.styleable.ScrcoolTab_moveunit:
  43. moveunit=a.getDimensionPixelSize(i,5);
  44. break;
  45. caseR.styleable.ScrcoolTab_duration:
  46. duration=a.getInt(i,100);
  47. break;
  48. }
  49. }
  50. Log.i("ScrcoolTab","construt");
  51. }
  52. @Override
  53. protectedvoidonDraw(Canvascanvas){
  54. super.onDraw(canvas);
  55. if(!isDrawItem())return;
  56. tabpictrue.setBounds(current[0]-tabpicpadding,top,current[0]+currentwidth+tabpicpadding,bottom);
  57. tabpictrue.draw(canvas);
  58. }
  59. @Override
  60. protectedvoidonLayout(booleanchanged,intl,intt,intr,intb){
  61. Log.i("ScrcoolTab","onLayout");
  62. super.onLayout(changed,l,t,r,b);
  63. top=t;
  64. bottom=b;
  65. intcount=getChildCount();
  66. if(0==count)return;
  67. intw=r-l;
  68. childWidth=w/count;
  69. Viewv=null;
  70. Integer[]points=null;
  71. for(inti=0;i<count;i++){
  72. v=getChildAt(i);
  73. points=scalcChildPoint(v,i);
  74. v.layout(points[0],((bottom-top)-v.getHeight())/2,points[1],((bottom-top)-v.getHeight())/2+v.getHeight());
  75. v.setTag(newInteger(i));
  76. v.setOnClickListener(newOnClickListener(){
  77. @Override
  78. publicvoidonClick(Viewv){
  79. if(!move){
  80. move=true;
  81. itemOnclick(v,((Integer)v.getTag()).intValue());
  82. }
  83. }
  84. });
  85. }
  86. //setdefaulttab
  87. ViewmDefaultTab=getChildAt(defaultTab);
  88. if(null!=mDefaultTab){
  89. itemOnclick(v,defaultTab);
  90. }
  91. }
  92. publicsynchronizedvoidupdate(Viewv,intposition){
  93. Log.i("ScrcoolTab","update");
  94. current=childPointCache.get(newInteger(position));
  95. currentleft=current[0];
  96. currentwidth=v.getWidth();//得到当前点击的控件的宽度
  97. //如果重复点一个项,则不会移动
  98. if(gleft==current[0]){
  99. move=false;//下一个点击可以移动
  100. return;
  101. }
  102. clickListener.onItemClickListener(v,((Integer)v.getTag()).intValue());//通知设置监听
  103. Log.i("ScrcoolTab","tabmoved");
  104. defaultTab=position;
  105. finalbooleanpathleft=gleft>current[0]?true:false;//判断是向左还是向右
  106. finalintnum=Math.abs((gleft-current[0])/moveunit);
  107. inti=0;
  108. while(i<num){
  109. if(pathleft){
  110. gleft=gleft-moveunit;
  111. current[0]=gleft;
  112. }else{
  113. gleft=gleft+moveunit;
  114. current[0]=gleft;
  115. }
  116. try{
  117. Thread.sleep(duration);
  118. }catch(InterruptedExceptione){
  119. e.printStackTrace();
  120. }
  121. Log.i("ScrcoolTab","Thread:left"+current[0]);
  122. postInvalidate();
  123. i++;
  124. }
  125. //校正因为除数可能有精度损失
  126. if(gleft!=currentleft){
  127. current[0]=currentleft;
  128. postInvalidate();
  129. }
  130. gleft=current[0];
  131. move=false;
  132. }
  133. /**
  134. *当点击一项时,移动背景坐标
  135. *@paramv
  136. */
  137. publicsynchronizedvoiditemOnclick(finalViewv,finalintposition){
  138. Log.i("ScrcoolTab","itemOnclickposition:"+position);
  139. newThread(newRunnable(){
  140. @Override
  141. publicvoidrun(){
  142. update(v,position);
  143. }
  144. }).start();
  145. }
  146. /**
  147. *设置数据适配器
  148. *@paramadapter
  149. */
  150. publicvoidsetAdapter(ScrcoolTabAdapteradapter){
  151. Log.i("ScrcoolTab","setAdapter");
  152. if(null!=adapter&&0!=adapter.getResource()&&null!=adapter.getData()){
  153. Viewview=null;
  154. for(Stringstr:adapter.getData()){
  155. view=mInflater.inflate(adapter.getResource(),this,false);
  156. if(viewinstanceofTextView)((TextView)view).setText(str);
  157. this.addView(view);
  158. }
  159. }
  160. }
  161. /**
  162. *计算每个子控件的坐标
  163. *@paramview
  164. *@paramposition
  165. *@return
  166. */
  167. publicInteger[]scalcChildPoint(Viewview,intposition){
  168. Integer[]points=newInteger[2];
  169. points[0]=childWidth*position+(childWidth-view.getWidth())/2;
  170. points[1]=points[0]+view.getWidth();
  171. Log.i("ScrcoolTab","scalcChildPointposition:"+position+"left:"+points[0]+"right:"+points[1]);
  172. childPointCache.put(newInteger(position),points);
  173. returnpoints;
  174. }
  175. /**
  176. *是否画背景图片taab
  177. *@return
  178. */
  179. privatebooleanisDrawItem(){
  180. if(current[0]>0)returntrue;
  181. elsereturnfalse;
  182. }
  183. /**
  184. *设置默认选中
  185. *@paramtab
  186. */
  187. publicvoidsetDefaultTab(inttab){
  188. Log.i("ScrcoolTab","setDefaultTab");
  189. this.defaultTab=tab;
  190. }
  191. @Override
  192. protectedvoidonAttachedToWindow(){
  193. super.onAttachedToWindow();
  194. Log.i("ScrcoolTab","onAttachedToWindow");
  195. }
  196. /**
  197. *得到当前选中的项
  198. *@return
  199. */
  200. publicintgetFocus(){
  201. returndefaultTab;
  202. }
  203. /**
  204. *当点一项时调用事件
  205. *@paramclickListener
  206. */
  207. publicvoidsetOnItemClickListener(OnItemClickListenerclickListener){
  208. this.clickListener=clickListener;
  209. }
  210. /**
  211. *事件接口
  212. *
  213. */
  214. publicinterfaceOnItemClickListener{
  215. voidonItemClickListener(Viewv,intposition);
  216. }
  217. }

控件适配器类:

Java代码
  1. packagecom.test.scrolltab.control;
  2. publicclassScrcoolTabAdapter{
  3. privateintresource;
  4. privateString[]data;
  5. publicintgetResource(){
  6. returnresource;
  7. }
  8. publicvoidsetResource(intresource){
  9. this.resource=resource;
  10. }
  11. publicString[]getData(){
  12. returndata;
  13. }
  14. publicvoidsetData(String[]data){
  15. this.data=data;
  16. }
  17. publicScrcoolTabAdapter(intresource,String[]data){
  18. super();
  19. this.resource=resource;
  20. this.data=data;
  21. }
  22. }

用法:

xml 布局文件:

Xml代码
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:control="http://schemas.android.com/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. </com.test.scrolltab.control.ScrcoolTab>
  12. </LinearLayout>

一个tab的布局:

Xml代码
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <TextViewandroid:layout_width="wrap_content"
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_height="wrap_content"style="@style/text_style"
  5. android:onClick="itemOnclick"/>

activity调用代码:

Java代码
  1. packagecom.test.scrolltab;
  2. importandroid.app.Activity;
  3. importandroid.os.Bundle;
  4. importandroid.os.Process;
  5. importandroid.view.View;
  6. importandroid.view.ViewParent;
  7. importcom.test.scrolltab.control.ScrcoolTab;
  8. importcom.test.scrolltab.control.ScrcoolTabAdapter;
  9. importcom.test.scrolltab.control.ScrcoolTab.OnItemClickListener;
  10. publicclassScrollTabActivityextendsActivity{
  11. privateScrcoolTabscrcoolTab;
  12. @Override
  13. publicvoidonCreate(BundlesavedInstanceState){
  14. super.onCreate(savedInstanceState);
  15. setContentView(R.layout.main);
  16. scrcoolTab=(ScrcoolTab)findViewById(R.id.scrcoolTab);
  17. scrcoolTab.setAdapter(newScrcoolTabAdapter(R.layout.tab_item,newString[]{"进入首页","用户调研","下载中心","联系我们"}));
  18. scrcoolTab.setOnItemClickListener(newOnItemClickListener(){
  19. @Override
  20. publicvoidonItemClickListener(Viewv,intposition){
  21. //Toast.makeText(ScrollTabActivity.this,"点击了"+position,Toast.LENGTH_SHORT).show();
  22. }
  23. });
  24. //scrcoolTab.setDefaultTab(1);
  25. }
  26. publicvoiditemOnclick(Viewv){
  27. ViewParentparent=v.getParent().getParent();
  28. if(parentinstanceofScrcoolTab){
  29. ScrcoolTabtab=(ScrcoolTab)parent;
  30. tab.postInvalidate();
  31. }
  32. System.out.println(parent);
  33. }
  34. @Override
  35. publicvoidfinish(){
  36. super.finish();
  37. Process.killProcess(Process.myPid());
  38. }
  39. }


  • ScrollTab.rar(63.1 KB)
  • 下载次数: 632

更多相关文章

  1. Android:LayoutInflater的使用
  2. Android控件之ListView
  3. android 自动化测试之MonkeyRunner学习(二)
  4. 【Java&Android开源库代码剖析】のAndroid-Universal-Image-Load
  5. Android的GridView简单使用实例(附Demo)
  6. android2.3修改ethernet默认为不选中状态
  7. 【Android(安卓)Native Code开发系列】六 一个Native Service的
  8. Android中EditText控件的几种使用方法
  9. android开发实例06:popwindow实现下拉菜单

随机推荐

  1. android 软键盘隐藏 activity初始化时edi
  2. Android(安卓)远程链接 daemon not runni
  3. android中的内存泄露
  4. android studio升级时提示 Connection fa
  5. webrtc 针对 android 平台的编译和运行
  6. android开发BUG集
  7. [置顶] 自定义的解压进度条 关于Progress
  8. Android自定义Toast,并解决toast不重复显
  9. Windows下搭建Android(安卓)SDK开发环境
  10. android : px dip