浏览 6143 次
锁定老帖子 主题:模仿移动MM Tab 点击 背景 滑动效果
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (3)
|
|
---|---|
作者 | 正文 |
发表时间:2011-07-02
最后修改:2011-07-02
在玩MM时看到里面的tab 很酷 就学着做了一个
上代码 现在我把他搞成了一个控件了 用法跟ListView 差不多 控件类:
package com.test.scrolltab.control; import java.util.HashMap; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import com.test.scrolltab.R; public class ScrcoolTab extends LinearLayout { private int top,bottom; // 该布局的top与bottom private LayoutInflater mInflater; // 控件xml 解析器 private OnItemClickListener clickListener; // 点击事件 private int defaultTab; // 默认选中第几个 private boolean move = false; //标识是否可以移动,主要为了实现一个项点击后,用户不能点击第二个 private HashMap<Integer, Integer []> childPointCache = new HashMap<Integer, Integer[]>(); int childWidth = 0; //因为要控件居中,所以计算出每个控件可以有多少宽度 private int gleft,currentwidth,currentleft; // 上一个选中项的左坐标 当前点击的控件的宽度 当前点击的控件的左坐标 private Integer [] current = {0,0}; //tab 背景的坐标 private Drawable tabpictrue; //tab 移动的背景图片 private int tabpicpadding ; //tab 背景图片大于控件多少 private int moveunit; // tab图片第次移动多少 private int duration;//移动速度 public ScrcoolTab(Context context, AttributeSet attrs) { super(context, attrs); mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ScrcoolTab); final int N = a.getIndexCount(); for (int i = 0; i < N; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.ScrcoolTab_tabpictrue: tabpictrue = (Drawable) a.getDrawable(i); break; case R.styleable.ScrcoolTab_tabpicpadding: tabpicpadding = a.getDimensionPixelSize(i, 5); break; case R.styleable.ScrcoolTab_moveunit: moveunit = a.getDimensionPixelSize(i, 5); break; case R.styleable.ScrcoolTab_duration: duration = a.getInt(i, 100); break; } } Log.i("ScrcoolTab", "construt"); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if( ! isDrawItem()) return; tabpictrue.setBounds(current[0] -tabpicpadding ,top , current[0] + currentwidth + tabpicpadding , bottom); tabpictrue.draw(canvas); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { Log.i("ScrcoolTab", "onLayout"); super.onLayout(changed, l, t, r, b); top = t; bottom = b; int count = getChildCount(); if(0 == count) return; int w = r- l; childWidth = w / count; View v =null; Integer [] points = null; for(int i = 0;i < count;i++){ v = getChildAt(i); points = scalcChildPoint(v, i); v.layout(points[0] ,((bottom - top) - v.getHeight()) /2 , points[1], ((bottom - top) - v.getHeight()) /2 + v.getHeight()); v.setTag(new Integer(i)); v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if( !move ){ move = true; itemOnclick(v ,((Integer)v.getTag()).intValue() ); } } }); } //set default tab View mDefaultTab = getChildAt(defaultTab); if(null != mDefaultTab){ itemOnclick(v , defaultTab); } } public synchronized void update(View v ,int position){ Log.i("ScrcoolTab", "update"); current = childPointCache.get(new Integer(position)); currentleft = current [0]; currentwidth = v.getWidth(); // 得到当前点击的控件的宽度 //如果重复点一个项,则不会移动 if(gleft == current [0]) { move = false; //下一个点击可以移动 return ; } clickListener.onItemClickListener(v, ((Integer)v.getTag()).intValue());//通知设置监听 Log.i("ScrcoolTab", "tab moved"); defaultTab = position; final boolean pathleft = gleft > current[0] ? true : false;//判断是向左还是向右 final int num = Math.abs((gleft - current[0]) / moveunit); int i = 0; while( i < num){ if( pathleft ){ gleft = gleft - moveunit; current [0] = gleft; }else{ gleft = gleft + moveunit; current [0] = gleft; } try { Thread.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); } Log.i("ScrcoolTab", "Thread: left"+current[0]); postInvalidate(); i++; } //校正 因为除数可能有精度损失 if(gleft != currentleft){ current [0] = currentleft; postInvalidate(); } gleft = current[0]; move = false; } /** * 当点击一项时,移动背景坐标 * @param v */ public synchronized void itemOnclick(final View v ,final int position){ Log.i("ScrcoolTab", "itemOnclick position:" + position); new Thread( new Runnable() { @Override public void run() { update (v , position); } }).start(); } /** * 设置数据适配器 * @param adapter */ public void setAdapter(ScrcoolTabAdapter adapter){ Log.i("ScrcoolTab", "setAdapter"); if(null != adapter && 0 != adapter.getResource() && null != adapter.getData()){ View view = null; for(String str : adapter.getData()){ view = mInflater.inflate(adapter.getResource(),this ,false); if(view instanceof TextView) ((TextView)view).setText(str); this.addView(view); } } } /** * 计算每个子控件的坐标 * @param view * @param position * @return */ public Integer [] scalcChildPoint(View view ,int position){ Integer[] points = new Integer [2]; points [0] = childWidth * position + (childWidth - view.getWidth())/2; points [1] = points [0] + view.getWidth(); Log.i("ScrcoolTab", "scalcChildPoint position :" + position + "left:" + points [0] + "right:" + points [1]); childPointCache.put(new Integer(position), points); return points; } /** * 是否画背景图片taab * @return */ private boolean isDrawItem(){ if(current [0] > 0 ) return true; else return false; } /** * 设置默认选中 * @param tab */ public void setDefaultTab(int tab){ Log.i("ScrcoolTab", "setDefaultTab"); this.defaultTab = tab; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); Log.i("ScrcoolTab", "onAttachedToWindow"); } /** * 得到当前选中的项 * @return */ public int getFocus() { return defaultTab; } /** * 当点一项时 调用事件 * @param clickListener */ public void setOnItemClickListener(OnItemClickListener clickListener){ this.clickListener = clickListener; } /** * 事件接口 * */ public interface OnItemClickListener { void onItemClickListener(View v , int position); } }
控件适配器类: package com.test.scrolltab.control; public class ScrcoolTabAdapter { private int resource; private String[] data; public int getResource() { return resource; } public void setResource(int resource) { this.resource = resource; } public String[] getData() { return data; } public void setData(String[] data) { this.data = data; } public ScrcoolTabAdapter(int resource, String[] data) { super(); this.resource = resource; this.data = data; } } 用法: xml 布局文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:control="http://schemas.android.com/apk/res/com.test.scrolltab" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <com.test.scrolltab.control.ScrcoolTab android:id="@+id/scrcoolTab" android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="center_vertical" control:tabpictrue="@drawable/bg_item_t" android:background="@drawable/bg_t" control:tabpicpadding="5dip" control:moveunit="15dip" control:duration="50"> </com.test.scrolltab.control.ScrcoolTab> </LinearLayout> 一个tab的布局: <?xml version="1.0" encoding="utf-8"?> <TextView android:layout_width="wrap_content" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" style="@style/text_style" android:onClick="itemOnclick" /> activity调用代码: package com.test.scrolltab; import android.app.Activity; import android.os.Bundle; import android.os.Process; import android.view.View; import android.view.ViewParent; import com.test.scrolltab.control.ScrcoolTab; import com.test.scrolltab.control.ScrcoolTabAdapter; import com.test.scrolltab.control.ScrcoolTab.OnItemClickListener; public class ScrollTabActivity extends Activity { private ScrcoolTab scrcoolTab; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); scrcoolTab = (ScrcoolTab) findViewById(R.id.scrcoolTab); scrcoolTab.setAdapter(new ScrcoolTabAdapter(R.layout.tab_item,new String []{"进入首页","用户调研","下载中心","联系我们"})); scrcoolTab.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClickListener(View v, int position) { // Toast.makeText(ScrollTabActivity.this, "点击了" + position, Toast.LENGTH_SHORT).show(); } }); // scrcoolTab.setDefaultTab(1); } public void itemOnclick(View v){ ViewParent parent = v.getParent().getParent(); if(parent instanceof ScrcoolTab){ ScrcoolTab tab = (ScrcoolTab) parent; tab.postInvalidate(); } System.out.println(parent); } @Override public void finish() { super.finish(); Process.killProcess(Process.myPid()); } }
有兴趣的可以看下 写的不好 不要见怪哦!!!
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-07-02
来电效果图呗 多直观啊
|
|
返回顶楼 | |
发表时间:2011-07-04
你的这个控件,如果数组长了就变形了
|
|
返回顶楼 | |
发表时间:2011-07-04
最后修改:2011-07-04
为什么一进入程序就会执行两次onLayout呢?
还有当只有2个汉字的时候,初始化后白色的底太大。 |
|
返回顶楼 | |
发表时间:2011-07-05
是呀,截几个图也好呀。
|
|
返回顶楼 | |
发表时间:2011-07-08
值得研究, 不错
|
|
返回顶楼 | |
发表时间:2011-07-17
没有图片 lz 最好来点图型哦
|
|
返回顶楼 | |
发表时间:2011-09-29
没有图,下载先RUN一下!
|
|
返回顶楼 | |