Android中自定義View和自定義動畫

Android FrameWork 層給我們提供了很多界面組件,但是在實際的商業開發中這些組件往往並不能完全滿足我們的需求,這時候我們就需要自定義我們自己的視圖和動畫。

我們要重寫系統的View就必須瞭解View的基本用法和結構,如下圖所示是Android官方指導中的View結構圖:


Android應用的絕大部分UI組件都放在android.widget包及其子包、android.view包及其子包中,Android應用的所有UI組件都繼承了View類,View組件非常類似於Swing編程的JPanel,它是所有UI組件的父類,代表一個區域。

View類有一個非常重要的子類叫做ViewGroup,ViewGroup相當於一個專門用來放置View的容器,同樣的ViewGroup也繼承自View基類,這是一種“組合器”的設計模式。由於ViewGroup也是View的子類,所以ViewGroup內也可以放置ViewGroup,用直觀一點的方式解釋這句話就如下面的xml文件(LinarLayout就是一個ViewGroup,TextView就是一個View)。

<LinearLayout>

<TextView></TextView>

<LinearLayout></LinearLayout>

</LinearLayout>

下面來介紹一下View和ViewGroup中的幾個重要的方法

(1)onDraw :繪製自己

(2)onLayout:View中佈局發生改變時會調用此方法

(3)dispatchDraw:用於控制子View的繪製分發

(4)drawChild:直接控制具體的子View

 重寫一個View的步驟如下:

(1)新建一個View子類,並實現構造

package com.example.testmyanimation;  
  
import android.content.Context;  
import android.util.AttributeSet;  
import android.view.MotionEvent;  
import android.view.WindowManager;  
import android.view.animation.AccelerateInterpolator;  
import android.view.animation.Animation;  
import android.view.animation.AnimationSet;  
import android.view.animation.LinearInterpolator;  
import android.view.animation.TranslateAnimation;  
import android.widget.Button;  
import android.widget.LinearLayout;  
import android.widget.LinearLayout.LayoutParams;  
  
public class MyButton extends Button{  
    private Context context;  
    private LayoutParams params;  
    public MyButton(Context context) {  
        super(context);  
        this.context = context;  
        //setOnClickListener(this);  
        // TODO Auto-generated constructor stub  
    }  
  
    public MyButton(Context context, AttributeSet attrs, int defStyle) {  
        super(context, attrs, defStyle);  
        this.context = context;  
        //setOnClickListener(this);  
        // TODO Auto-generated constructor stub  
    }  
  
    public MyButton(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        this.context = context;  
        //setOnClickListener(this);  
        // TODO Auto-generated constructor stub  
    }  
  
    /*@Override 
    public void onClick(View v) { 
        //加載動畫資源 
        //final Animation anim = AnimationUtils.loadAnimation(context, R.anim.myanim); 
        startAnimation(new MyAnimation()); 
        System.out.println("我點了"); 
    }*/  
      
    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
        if(event.getAction() == MotionEvent.ACTION_DOWN){  
            WindowManager windowManager = (WindowManager) getContext()  
                    .getSystemService(Context.WINDOW_SERVICE);  
            int width = windowManager.getDefaultDisplay().getWidth();  
            int height = windowManager.getDefaultDisplay().getHeight();  
              
            float x = event.getRawX() - event.getX();  
            float y = event.getRawY() -event.getY();  
              
            //MyAnimation mAnimation = new MyAnimation(width - x , height - y, 1000);  
             AnimationSet mAnimation=new AnimationSet(false);  
            TranslateAnimation translateAnimationX=new TranslateAnimation(0, width - x, 0, 0);  
            translateAnimationX.setInterpolator(new LinearInterpolator());  
           // translateAnimationX.setRepeatCount(200);  
            TranslateAnimation translateAnimationY=new TranslateAnimation(0, 0, 0, height - y);  
            translateAnimationY.setInterpolator(new AccelerateInterpolator());  
           // translateAnimationY.setRepeatCount(200);  
            mAnimation.addAnimation(translateAnimationY);  
            mAnimation.addAnimation(translateAnimationX);  
            mAnimation.setDuration(500);  
            mAnimation.setAnimationListener(new Animation.AnimationListener(){  
            @Override  
            public void onAnimationEnd(Animation animation) {  
                // TODO Auto-generated method stub  
                //LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(20, 20);  
                setLayoutParams(params);  
                setBackgroundResource(R.drawable.ic_launcher);  
            }  
  
            @Override  
            public void onAnimationRepeat(Animation animation) {  
                // TODO Auto-generated method stub  
                  
            }  
  
            @Override  
            public void onAnimationStart(Animation animation) {  
                params = (LayoutParams) getLayoutParams();  
                LinearLayout.LayoutParams layout_params = new LinearLayout.LayoutParams(20, 20);  
                setLayoutParams(layout_params);  
                setBackgroundResource(R.drawable.b1);  
                  
            }});  
            startAnimation(mAnimation);  
              
              
        }  
        return true;  
    }  
      
}  


(2)在xml文件中使用如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:orientation="vertical" >  
    <com.example.testmyanimation.MyButton  
        android:id="@+id/mybutton"  
        android:layout_width="40dip"  
        android:layout_height="30dip"/>  
    <com.example.testmyanimation.MyButton  
          
        android:layout_width="40dip"  
        android:layout_height="30dip"/>  
    <com.example.testmyanimation.MyButton  
          
        android:layout_width="30dip"  
        android:layout_height="30dip"/>  
</LinearLayout> 



下面來介紹一下Animation及重寫Animation,在Android中使用Animation代表抽象的動畫類,它包括如下幾個子類:

(1)AlphaAnimation :透明度改變的動畫。

(2)ScaleAnimation:大小縮放的動畫。

(3)TranslateAnimation:位移變化的動畫。

(4)RotateAnimation:旋轉動畫。

然而在實際項目中透明度、縮放、位移、旋轉這幾種動畫並不能滿足我們的需求,這時候就需要用到自定義動畫,自定義動畫需要繼承Animation,並重寫applyTransformation(float interpolatedTime, Transformation t)方法,該方法中的兩個參數說明:

interpolatedTime:該參數代表了時間的進行程度(如:你設置的時間是1000ms, 那麼interploatedTime就會從0開始一直到1)

Transformation:代表補間動畫在不同時刻對圖形或組建的變形程度。該對象中封裝了一個Matrix對象,對它所包含的Matrix對象進行位移、傾斜、旋轉等變換時,Transformation將會控制對應的圖片或視圖進行相應的變換。

爲了控制圖片或View進行三維空間的變換,還需要藉助於Android提供的一個Camera類,該類是一個空間變換工具,作用有點類似於Matrix,提供瞭如下常用的方法。

getMatrix(Matrix matrix) :將Camera所做的變換應用到指定的maxtrix上

rotateX(float deg):將目標組件沿X軸旋轉

rotateY(float deg)、rotateZ(float deg)

translate(float x, float y, float z):把目標組件在三維空間類進行位移變換。

applyToCanvas(Canvas canvas):把Camera所做的變換應用到Canvas上。

具體自定義實現如下:

  1. package com.example.testmyanimation;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Camera;  
  5. import android.graphics.Matrix;  
  6. import android.util.AttributeSet;  
  7. import android.view.animation.AccelerateDecelerateInterpolator;  
  8. import android.view.animation.AccelerateInterpolator;  
  9. import android.view.animation.Animation;  
  10. import android.view.animation.Transformation;  
  11.   
  12. public class MyAnimation extends Animation{  
  13.     private float moveX;  
  14.     private float moveY;  
  15.     private int duration;  
  16.     private Camera camera = new Camera();  
  17.     public MyAnimation(float moveX, float moveY, int duration) {  
  18.         this.moveX = moveX;  
  19.         this.moveY = moveY;  
  20.         this.duration = duration;  
  21.     }  
  22.       
  23.       
  24.   
  25.     public MyAnimation(Context context, AttributeSet attrs) {  
  26.         super(context, attrs);  
  27.     }  
  28.   
  29.     @Override  
  30.     public void initialize(int width, int height, int parentWidth,  
  31.             int parentHeight) {  
  32.         super.initialize(width, height, parentWidth, parentHeight);  
  33.         //設置動畫的持續時間  
  34.         setDuration(duration);  
  35.         //設置動畫結束後保留效果  
  36.         setFillAfter(false);  
  37.           
  38.         //setRepeatCount(2);  
  39.         //setRepeatMode(2);  
  40.   
  41.         //播放速度  
  42.         setInterpolator(new MyInterprolator());  
  43.     }  
  44.       
  45.     @Override  
  46.     protected void applyTransformation(float interpolatedTime, Transformation t) {  
  47.         camera.save();  
  48.         camera.translate(0f + moveX * interpolatedTime,  
  49.                 0f - moveY * interpolatedTime,   
  50.                 0f);  
  51.         //camera.rotateY(360 * (interpolatedTime) * 2);  
  52.         //camera.rotateX(360 * (interpolatedTime));  
  53.         //camera.rotateZ(360 * (interpolatedTime));  
  54.         Matrix matrix = t.getMatrix();  
  55.         camera.getMatrix(matrix);  
  56.         //matrix.preTranslate(-centerX, -centerY);  
  57.         //matrix.postTranslate(centerX, centerY);  
  58.         camera.restore();  
  59.     }  
  60.   
  61.       
  62. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章