• 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();
    	}
    
    	
    }
    

  • 相关阅读:
    C# 函数参数object sender, EventArgs e
    Winform中利用委托实现窗体之间的传值
    Web前端学习笔记——Canvas
    js 删除 按钮所在的行
    box-sizing
    前端中关于HTML标签的属性for的理解
    apply和call的用法总结
    target 确定元素是谁??
    css3过渡和动画
    处理两端极限值的小技巧
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6469504.html
Copyright © 2020-2023  润新知