当前位置: 代码迷 >> Android >> Android 兑现table切换动画
  详细解决方案

Android 兑现table切换动画

热度:32   发布时间:2016-05-01 19:28:56.0
Android 实现table切换动画
    参考博客http://yanweimin7.iteye.com/blog/1126570 实现,把mNowRect的更新放到Handler里,逻辑更简单。
    实现效果如下图:在“首页”和“我的信息”之间切换时,后面的背景从“首页”以动画形式滚动到“我的信息”。
 
    思路:自定义一个控件MoveTab,继承LinearLayout。假设当前选中的控件区域为mNowRect,目标控件区域为mEndRect。我们还需要一个Drawable mDrawable(就是切换过程中移动的图片)。使用Handler更新mNowRect,重写onDraw(),在onDraw()里将Drawable画在mEndRect里,直到mNowRect和mEndRect重合。

    因为这里的mDrawable和MoveTab相关性比较大,为了使MoveTab更加通用,我们还使用了attrs.xml,并在其中定义属性move_drawable,和mDrawable相关联。
    res/values/attrs.xml


<?xml version="1.0" encoding="utf-8"?><resources>	<declare-styleable name="MoveTab">	    <attr name="move_drawable" format="reference" />	</declare-styleable></resources>


在res/layout/main.xml中定义MoveTab时,可以通过下面xml代码指定mDrawable
xmlns:demo="http://schemas.android.com/apk/res/com.ipjmc.demo"...demo:move_drawable="@drawable/home_btn_bg_d"  <!--指定mDrawable-->


    在布局文件main.xml中,我们使用<com.ipjmc.demo.view.MoveTab></com.ipjmc.demo.view.MoveTab>来指定MoveTab,并在其中添加了5个Button,在外观上和新浪微博的一样
res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:demo="http://schemas.android.com/apk/res/com.ipjmc.demo"    android:layout_width="fill_parent" android:layout_height="fill_parent"    android:orientation="vertical" >    <TextView android:text="@string/hello"         android:layout_width="fill_parent" android:layout_height="0px"        android:layout_weight="1"/>    <com.ipjmc.demo.view.MoveTab android:id="@+id/move_tab" android:background="@drawable/home_btn_bg_n"        android:orientation="horizontal" demo:move_drawable="@drawable/home_btn_bg_d"		android:layout_width="fill_parent" android:layout_height="wrap_content" >	    <Button android:tag="radio_button0" android:text="@string/main_home" android:drawableTop="@drawable/icon_home" style="@style/main_tab_bottom" />	    <Button android:tag="radio_button1" android:text="@string/main_news" android:drawableTop="@drawable/icon_meassage" style="@style/main_tab_bottom" />	    <Button android:tag="radio_button2" android:text="@string/main_my_info" android:drawableTop="@drawable/icon_selfinfo" style="@style/main_tab_bottom" />	    <Button android:tag="radio_button3" android:text="@string/menu_search" android:drawableTop="@drawable/icon_square" style="@style/main_tab_bottom" />	    <Button android:tag="radio_button4" android:text="@string/more" android:drawableTop="@drawable/icon_more" style="@style/main_tab_bottom" />    </com.ipjmc.demo.view.MoveTab></LinearLayout>

MoveTab的定义,具体代码如下:

package com.ipjmc.demo.view;import com.ipjmc.demo.R;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.widget.LinearLayout;public class MoveTab extends LinearLayout {	private static final int DELAY = 10;	private static final int SPEED = 16;	private static final int MOVE = 1;	private static final String TAG = "MoveTab";		private Context mContext;	private Drawable mDrawable;//移动的背景图	private final Rect mNowRect = new Rect();//当前的区域    private final Rect mEndRect = new Rect();//结束的区域    private final Handler mHandler = new Handler() {    	public void handleMessage(Message msg) {    		if (msg.what == MOVE) {    			//如果还没有到达目标区域,就延迟DELAY后,重新绘图    			if (!move()) {     				this.sendEmptyMessageDelayed(MOVE, DELAY);    			}    		}    	};    };    	public MoveTab(Context context) {		super(context);		init(context, null);	}		public MoveTab(Context context, AttributeSet attrs) {		super(context, attrs);		init(context, attrs);	}	private void init(Context context, AttributeSet attrs) {		mContext = context;		TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.MoveTab);				//通过XML中定义的属性"move_drawable",生成mDrawable		mDrawable = attr.getDrawable(R.styleable.MoveTab_move_drawable);		if (mDrawable == null) {			Log.e(TAG, "Errorr : mDrawable == null");		}	}		@Override	protected void onLayout(boolean changed, int l, int t, int r, int b) {		//默认选择第一个table,把它的区域设置为mNowRect		this.getChildAt(0).getHitRect(mNowRect);		super.onLayout(changed, l, t, r, b);	}		/**	 * 对外公开的接口,外部调用者应该在table被点击时调用它,将mDrawable移动到目标控件v	 * @param 目标控件	 */	public void selectTab(View v) {		//将目标控件v的区域设置为mEndRect		v.getHitRect(mEndRect);				if (mNowRect.right != mEndRect.right) {			mHandler.sendEmptyMessage(MOVE); //向Handler发送消息,开始移动mDrawable		}	}		/**	 * 重新计算图片的位置	 * @return 动画是否结束	 */	private boolean move() {		int direction = 0;		//已非常接近目标控件, 直接让mNowRect和mEndRect重合		if (Math.abs(mNowRect.left - mEndRect.left) <= SPEED) {			mNowRect.left = mEndRect.left;			mNowRect.right = mEndRect.right;			invalidate();			return true;		}				if (mNowRect.left < mEndRect.left) {			direction = 1; //向右		} else {			direction = -1; //向左		}		//更新mNowRect		mNowRect.left += SPEED * direction;		mNowRect.right += SPEED * direction;				//请求onDraw()		invalidate();		return false;	}		@Override	protected void onDraw(Canvas canvas) {		super.onDraw(canvas);		if (null != mDrawable) {			//将mDrawable画到mNowRect上			mDrawable.setBounds(mNowRect);			mDrawable.draw(canvas);			Log.i(TAG, "onDraw : " + mNowRect.left + ", " + mNowRect.right + ", " + mNowRect.top + ", " + mNowRect.bottom);		} else {			Log.e(TAG, "Errorr : mDrawable == null");		}	}}

MoveDrawableActivity.java 文件

package com.ipjmc.demo;import com.ipjmc.demo.view.MoveTab;import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.CompoundButton;import android.widget.CompoundButton.OnCheckedChangeListener;import android.widget.RadioButton;import android.widget.RadioGroup;public class MoveDrawableActivity extends Activity implements OnClickListener{    	private static final String TAG = "MoveTab";		private RadioGroup mRadioGroup;	private Button mButton[];	private MoveTab mMoveTab;	    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                Log.i(TAG, "onCreate");        setContentView(R.layout.main);        mMoveTab = (MoveTab) findViewById(R.id.move_tab);        initRadios();    }        private void initRadios() {    	mButton = new Button[5];    	String tag = "radio_button";    	for (int i = 0; i < mButton.length; i++) {    		mButton[i] = (Button) mMoveTab.findViewWithTag(tag+i); //通过tag查找View    		mButton[i].setOnClickListener(this);    	}    }	@Override	public void onClick(View v) {		//点击后,开始动画		mMoveTab.selectTab(v); 	}}


全部代码请查看附件
  相关解决方案