读书人

Android 兑现table切换动画

发布时间: 2012-07-15 20:20:05 作者: rapoo

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",生成mDrawablemDrawable = attr.getDrawable(R.styleable.MoveTab_move_drawable);if (mDrawable == null) {Log.e(TAG, "Errorr : mDrawable == null");}}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {//默认选择第一个table,把它的区域设置为mNowRectthis.getChildAt(0).getHitRect(mNowRect);super.onLayout(changed, l, t, r, b);}/** * 对外公开的接口,外部调用者应该在table被点击时调用它,将mDrawable移动到目标控件v * @param 目标控件 */public void selectTab(View v) {//将目标控件v的区域设置为mEndRectv.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; //向左}//更新mNowRectmNowRect.left += SPEED * direction;mNowRect.right += SPEED * direction;//请求onDraw()invalidate();return false;}@Overrideprotected 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);    }    }@Overridepublic void onClick(View v) {//点击后,开始动画mMoveTab.selectTab(v); }}


全部代码请查看附件

读书人网 >Android

热点推荐