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

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

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

 

效果如下:

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

控件类:

 

Java代码  

  1. package com.test.scrolltab.control;  
  2.   
  3. import java.util.HashMap;  
  4.   
  5. import android.content.Context;  
  6. import android.content.res.TypedArray;  
  7. import android.graphics.Canvas;  
  8. import android.graphics.drawable.Drawable;  
  9. import android.util.AttributeSet;  
  10. import android.util.Log;  
  11. import android.view.LayoutInflater;  
  12. import android.view.View;  
  13. import android.widget.LinearLayout;  
  14. import android.widget.TextView;  
  15.   
  16. import com.test.scrolltab.R;  
  17.   
  18. public class ScrcoolTab extends LinearLayout {  
  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 HashMap<Integer, Integer[]>();  
  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 ScrcoolTab(Context context, AttributeSet attrs) {  
  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 N = a.getIndexCount();  
  51.         for (int i = 0; i < N; i++) {  
  52.             int attr = a.getIndex(i);  
  53.             switch (attr) {  
  54.                 case R.styleable.ScrcoolTab_tabpictrue:  
  55.                     tabpictrue = (Drawable) a.getDrawable(i);  
  56.                 break;  
  57.                 case R.styleable.ScrcoolTab_tabpicpadding:  
  58.                     tabpicpadding = a.getDimensionPixelSize(i, 5);  
  59.                 break;  
  60.                 case R.styleable.ScrcoolTab_moveunit:  
  61.                     moveunit = a.getDimensionPixelSize(i, 5);  
  62.                     break;  
  63.                 case R.styleable.ScrcoolTab_duration:  
  64.                     duration = a.getInt(i, 100);  
  65.                     break;  
  66.             }  
  67.         }  
  68.         Log.i("ScrcoolTab", "construt");  
  69.     }  
  70.   
  71.     @Override  
  72.     protected void onDraw(Canvas canvas) {  
  73.         super.onDraw(canvas);  
  74.         if( ! isDrawItem()) return;   
  75.         tabpictrue.setBounds(current[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 b) {  
  82.         Log.i("ScrcoolTab", "onLayout");  
  83.         super.onLayout(changed, l, t, r, b);  
  84.         top = t;  
  85.         bottom = b;  
  86.         int count = getChildCount();  
  87.         if(0 == count) return;  
  88.         int w = r- l;  
  89.         childWidth  = w / count;  
  90.          View v =null;  
  91.          Integer [] points = null;  
  92.         for(int i = 0;i < count;i++){  
  93.              v = getChildAt(i);  
  94.              points = scalcChildPoint(v, i);  
  95.              v.layout(points[0] ,((bottom - top) - v.getHeight()) /2  , points[1],  ((bottom - top) - v.getHeight()) /2 + v.getHeight());  
  96.              v.setTag(new Integer(i));  
  97.              v.setOnClickListener(new OnClickListener() {  
  98.                   
  99.                 @Override  
  100.                 public void onClick(View v) {  
  101.                     if( !move ){  
  102.                         move = 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 != mDefaultTab){  
  112.             itemOnclick(v , defaultTab);  
  113.         }  
  114.     }  
  115.       
  116.     public synchronized void update(View v ,int position){  
  117.         Log.i("ScrcoolTab", "update");  
  118.         current = childPointCache.get(new Integer(position));  
  119.         currentleft = current [0];  
  120.         currentwidth = v.getWidth(); // 得到当前点击的控件的宽度  
  121.         //如果重复点一个项,则不会移动  
  122.         if(gleft == current [0]) {  
  123.             move = false; //下一个点击可以移动  
  124.             return ;  
  125.         }  
  126.         clickListener.onItemClickListener(v, ((Integer)v.getTag()).intValue());//通知设置监听  
  127.         Log.i("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.                 current [0] =  gleft;  
  136.             }else{  
  137.                 gleft = gleft + moveunit;  
  138.                 current [0] =  gleft;  
  139.             }  
  140.             try {  
  141.                 Thread.sleep(duration);  
  142.             } catch (InterruptedException e) {  
  143.                 e.printStackTrace();  
  144.             }  
  145.             Log.i("ScrcoolTab", "Thread: left"+current[0]);  
  146.             postInvalidate();  
  147.             i++;  
  148.         }  
  149.         //校正 因为除数可能有精度损失  
  150.         if(gleft != currentleft){  
  151.             current [0] = currentleft;  
  152.             postInvalidate();  
  153.         }  
  154.         gleft = current[0];  
  155.         move = false;  
  156.     }  
  157.       
  158.     /** 
  159.      * 当点击一项时,移动背景坐标 
  160.      * @param v 
  161.      */  
  162.     public synchronized void itemOnclick(final View v ,final int position){  
  163.         Log.i("ScrcoolTab", "itemOnclick position:" + position);  
  164.           
  165.         new Thread( new  Runnable() {  
  166.               
  167.             @Override  
  168.             public void run() {  
  169.                 update (v , position);  
  170.             }  
  171.               
  172.         }).start();  
  173.           
  174.     }  
  175.       
  176.     /** 
  177.      * 设置数据适配器 
  178.      * @param adapter 
  179.      */  
  180.     public void setAdapter(ScrcoolTabAdapter adapter){  
  181.         Log.i("ScrcoolTab", "setAdapter");  
  182.         if(null != adapter && 0 != adapter.getResource() && null != adapter.getData()){  
  183.             View view = null;  
  184.             for(String str : adapter.getData()){  
  185.                 view = mInflater.inflate(adapter.getResource(),this ,false);  
  186.                 if(view instanceof TextView) ((TextView)view).setText(str);  
  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 position){  
  199.         Integer[] points = new Integer [2];  
  200.         points [0] =  childWidth * position  + (childWidth - view.getWidth())/2;  
  201.         points [1] =  points [0] + view.getWidth();  
  202.         Log.i("ScrcoolTab", "scalcChildPoint position :" + position + "left:" + points [0] + "right:" + points [1]);  
  203.         childPointCache.put(new Integer(position), points);  
  204.         return points;  
  205.     }  
  206.       
  207.     /** 
  208.      * 是否画背景图片taab 
  209.      * @return 
  210.      */  
  211.     private boolean isDrawItem(){  
  212.         if(current [0] > 0 ) return true;  
  213.         else return false;  
  214.     }  
  215.       
  216.     /** 
  217.      * 设置默认选中 
  218.      * @param tab 
  219.      */  
  220.     public void setDefaultTab(int tab){  
  221.         Log.i("ScrcoolTab", "setDefaultTab");  
  222.         this.defaultTab = tab;  
  223.     }  
  224.       
  225.     @Override  
  226.     protected void onAttachedToWindow() {  
  227.         super.onAttachedToWindow();  
  228.         Log.i("ScrcoolTab", "onAttachedToWindow");  
  229.     }  
  230.       
  231.     /** 
  232.      * 得到当前选中的项 
  233.      * @return 
  234.      */  
  235.     public int getFocus() {  
  236.         return defaultTab;  
  237.     }  
  238.   
  239.     /** 
  240.      * 当点一项时 调用事件 
  241.      * @param clickListener 
  242.      */  
  243.     public void setOnItemClickListener(OnItemClickListener clickListener){  
  244.         this.clickListener = clickListener;  
  245.     }  
  246.       
  247.     /** 
  248.      * 事件接口 
  249.      * 
  250.      */  
  251.     public interface OnItemClickListener {  
  252.         void onItemClickListener(View v , int position);  
  253.     }  
  254. }  

 

 

控件适配器类:

Java代码  

  1. package com.test.scrolltab.control;  
  2.   
  3. public class ScrcoolTabAdapter {  
  4.       
  5.     private int resource;  
  6.   
  7.     private String[] data;  
  8.   
  9.     public int getResource() {  
  10.         return resource;  
  11.     }  
  12.   
  13.     public void setResource(int resource) {  
  14.         this.resource = resource;  
  15.     }  
  16.   
  17.     public String[] getData() {  
  18.         return data;  
  19.     }  
  20.   
  21.     public void setData(String[] data) {  
  22.         this.data = data;  
  23.     }  
  24.   
  25.     public ScrcoolTabAdapter(int resource, String[] data) {  
  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://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.               
  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://schemas.android.com/apk/res/android"  
  4.     android:layout_height="wrap_content" style="@style/text_style"  
  5.     android:onClick="itemOnclick" />  

 activity调用代码:

Java代码  

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

android模仿移动MM Tab 点击 背景 滑动效果的相关文章

Android实现顶部导航栏可点击可滑动效果(仿微信仿豆瓣网)

使用ViewPager,PagerSlidingTabStrip,SwipeRefreshLayout打造一款可以点击可以侧滑的顶部导航栏. 先简单介绍一下所用的两个个开源库. PagerSlidingTabStrip Github地址 用法: 1.向app Module中的build.gradle中添加依赖 dependencies { compile 'com.astuetz:pagerslidingtabstrip:1.0.1' } 2.把PagerSlidingTabStrip这个控件添

如何在Android中实现渐显按钮的左右滑动效果_Android

先看下运行效果:    程序结构: MainActivity文件中代码: 复制代码 代码如下: package com.android.buttonpageflipper;import android.app.Activity;import android.graphics.PixelFormat;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.Gra

如何在Android中实现渐显按钮的左右滑动效果

先看下运行效果: 程序结构: MainActivity文件中代码: 复制代码 代码如下: package com.android.buttonpageflipper; import android.app.Activity; import android.graphics.PixelFormat; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.

Android 利用ViewPager实现图片可以左右循环滑动效果附代码下载_Android

首先给大家展示靓照,对效果图感兴趣的朋友可以继续往下阅读哦. ViewPager这个小demo实现的是可以左右循环滑动图片,下面带索引,滑到最后一页在往右滑动就要第一页,第一页往左滑动就到最后一页,上面是效果图,用美女图片是我一贯的作风,呵呵  1.    首先看一些layout下的xml <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width=&qu

Android实现顶部导航菜单左右滑动效果_Android

本文给大家介绍在Android中如何实现顶部导航菜单左右滑动效果,具体内容如下第一种解决方案: 实现原理是使用android-support-v4.jar包中ViewPager控件,在ViewPager控件中设置流布局,再在流布局中设置几项TextView,给每一个TextView设置相关参数,事件等.关于ViewPager控件可以设置全屏幕滑动效果,当然也可以实现局部滑动效果,下面介绍导航菜单. 关于导航菜单,相信大家对它并不陌生,比如在新闻客户端中就经常使用左右滑动菜单来显示不同类别的新闻.

Android实现顶部导航菜单左右滑动效果

本文给大家介绍在Android中如何实现顶部导航菜单左右滑动效果,具体内容如下 第一种解决方案: 实现原理是使用android-support-v4.jar包中ViewPager控件,在ViewPager控件中设置流布局,再在流布局中设置几项TextView,给每一个TextView设置相关参数,事件等.关于ViewPager控件可以设置全屏幕滑动效果,当然也可以实现局部滑动效果,下面介绍导航菜单. 关于导航菜单,相信大家对它并不陌生,比如在新闻客户端中就经常使用左右滑动菜单来显示不同类别的新闻

Android实现渐显按钮的左右滑动效果

本示例演示在Android中实现带渐显按钮的左右滑动效果. 关于滑动效果,在我的上一篇博文中提到过,有兴趣的朋友可以访问: http://www.cnblogs.com/hanyonglu/archive/2012/02/13/2349827.html 如果大家想实现带指引效果的左右滑动,请访问博文:http://www.cnblogs.com/hanyonglu/archive/2012/04/07/2435589.html 先看下运行效果: 程序结构: MainActivity文件中代码:

android点击背景颜色变化问题

问题描述 android点击背景颜色变化问题 我现在的情况是,点击一个视图背景颜色改变,但是由于代码5秒更新一次,更新后的代码,视图的背景颜色又变回点击前了,这不是我想要的,我想是代码更新不要影响到我点击视图后的背景颜色,注:代码更新一定要存在,因为在刷新数据.请大神指教帮帮忙,麻烦说的详细点,最好有代码贴出来,谢谢了 解决方案 你可以设置一个变量View保存你点击的view,每次点击的时候将view赋值给变量,然后在刷新的时候判断这个view是否为null,如果不为null,保存的view就是

Android编程简单实现ImageView点击时背景图修改的方法_Android

本文实例讲述了Android编程简单实现ImageView点击时背景图修改的方法.分享给大家供大家参考,具体如下: 在使用ImageView时,当被点击时,希望背景图修改一下,这样显示被点击效果明显一些.在这里,一个很简单的方法,最起码是个很清晰的方法.在res/drawable文件夹下创建一个xml文件.比如my.xml,内容如下: <?xml version="1.0" encoding="utf-8"?> <selector xmlns:an