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上。

具體自定義實現如下:

    package com.example.testmyanimation;
     
    import android.content.Context;
    import android.graphics.Camera;
    import android.graphics.Matrix;
    import android.util.AttributeSet;
    import android.view.animation.AccelerateDecelerateInterpolator;
    import android.view.animation.AccelerateInterpolator;
    import android.view.animation.Animation;
    import android.view.animation.Transformation;
     
    public class MyAnimation extends Animation{
        private float moveX;
        private float moveY;
        private int duration;
        private Camera camera = new Camera();
        public MyAnimation(float moveX, float moveY, int duration) {
            this.moveX = moveX;
            this.moveY = moveY;
            this.duration = duration;
        }
        
        
     
        public MyAnimation(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
     
        @Override
        public void initialize(int width, int height, int parentWidth,
                int parentHeight) {
            super.initialize(width, height, parentWidth, parentHeight);
            //設置動畫的持續時間
            setDuration(duration);
            //設置動畫結束后保留效果
            setFillAfter(false);
            
            //setRepeatCount(2);
            //setRepeatMode(2);
     
            //播放速度
            setInterpolator(new MyInterprolator());
        }
        
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            camera.save();
            camera.translate(0f + moveX * interpolatedTime,
                    0f - moveY * interpolatedTime,
                    0f);
            //camera.rotateY(360 * (interpolatedTime) * 2);
            //camera.rotateX(360 * (interpolatedTime));
            //camera.rotateZ(360 * (interpolatedTime));
            Matrix matrix = t.getMatrix();
            camera.getMatrix(matrix);
            //matrix.preTranslate(-centerX, -centerY);
            //matrix.postTranslate(centerX, centerY);
            camera.restore();
        }
     
        
    }



---------------------
作者:新博客dp2px.com
來源:CSDN
原文:https://blog.csdn.net/dawanganban/article/details/17261379
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM