http://ouyangfeng521.iteye.com/blog/1112905
在玩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());
- }
- }
- ScrollTab.rar (63.1 KB)
- 下载次数: 632