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

Android中自定义View和自定义动画的更多相关文章

  1. Android中使用ListView绘制自定义表格(2)

    上回再写了<Android中使用ListView绘制自定义表格>后,很多人留言代码不全和没有数据样例.但因为项目原因,没法把源码全部贴上来.近两天,抽空简化了一下,做了一个例子. 效果图如 ...

  2. Dialog详解(包括进度条、PopupWindow、自定义view、自定义样式的对话框)

    Dialog详解(包括进度条.PopupWindow.自定义view.自定义样式的对话框)   Android中提供了多种对话框,在实际应用中我们可能会需要修改这些已有的对话框.本实例就是从实际出发, ...

  3. 详解实现Android中实现View滑动的几种方式

    注: 本文提到的所有三种滑动方式的完整demo:ScrollDemo 1. 关于View我们需要知道的 (1)什么是View? Android中的View类是所有UI控件的基类(Base class) ...

  4. android中实现view可以滑动的六种方法续篇(二)

    承接上一篇,上一篇中讲解了实现滑动的第五种方法,如果你还没读过,可点击下面链接: http://www.cnblogs.com/fuly550871915/p/4985482.html 这篇文章现在来 ...

  5. Android 中的View与ViewGroup

    Android重点知识--View和ViewGroup与自定义控件 作者:丁明祥 邮箱:2780087178@qq.com 一.基础 ViewGroup 参考资料: Android 手把手教您自定义V ...

  6. Android中四种补间动画的使用示例(附代码下载)

    场景 Android中四种补间动画. 透明度渐变动画 旋转动画 缩放动画 平移动画 注: 博客: https://blog.csdn.net/badao_liumang_qizhi关注公众号 霸道的程 ...

  7. Android 自定义View修炼-自定义可动画展开收缩View的实现

    有时候需要点击一个view可以动画展开和收缩折叠一个View这样的效果,这样就可以直接自定义View来实现. 本例中,采用继承FrameLayout来实现自定义的ExpandView.下面将详细介绍各 ...

  8. Android 自定义View修炼-自定义加载进度动画XCLoadingImageView

    一.概述 本自定义View,是加载进度动画的自定义View,继承于ImageView来实现,主要实现蒙层加载进度的加载进度效果. 支持水平左右加载和垂直上下加载四个方向,同时也支持自定义蒙层进度颜色. ...

  9. Android 自定义View修炼-自定义弹幕效果View

    一.概述 现在有个很流行的效果就是弹幕效果,满屏幕的文字从右到左飘来飘去.看的眼花缭乱,看起来还蛮cool的 现在就是来实现这一的一个效果,大部分的都是从右向左移动漂移,本文的效果中也支持从左向右的漂 ...

随机推荐

  1. Costura.Fody

    使用Costura.Fody将源DLL合并到目标EXE 本文为原创文章,如转载,请在网页明显位置标明原文名称.作者及网址,谢谢! 一.本文主要是使用Costura.Fody工具将源DLL合并到目标EX ...

  2. (win7/8/10)鼠标右键添加按下SHIFT键时弹出带管理员权限的“在此处打开命令窗口”

    Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Directory\Background\shell\runas]@="@sh ...

  3. Android原生生成JSON与解析JSON

    JSON数据是一种轻量级的数据交换格式,在Android中通常应用于client与server交互之间的传输数据.像如今在网上有非常多解析JSON数据的jar包,可是归根究竟用的都是Android原生 ...

  4. python3中numpy函数tile的用法

    tile函数位于python模块 numpy.lib.shape_base中,他的功能是重复某个数组.比如tile(A,n),功能是将数组A重复n次,构成一个新的数组,我们还是使用具体的例子来说明问题 ...

  5. 10.9 android输入系统_APP跟输入系统建立联系和Dispatcher线程_分发dispatch

    12. 输入系统_APP跟输入系统建立联系_InputChannel和Connection核心: socketpair // 第9课第3节_输入系统_必备Linux编程知识_任意进程双向通信(scok ...

  6. Spring Boot 静态资源处理(转)

    Spring Boot 静态资源处理 Spring Boot 系列 Spring Boot 入门 Spring Boot 属性配置和使用 Spring Boot 集成MyBatis Spring Bo ...

  7. MAVEN Error: Using platform encoding (GBK actually) to copy filtered resources.....

    环境:Maven3.2.5+MyEclipse 2015CI 现象:在Maven编译过程中出现错误信息:Using platform encoding (GBK actually) to copy f ...

  8. squeeze() 函数——MATLAB

    B=squeeze(A) 移除张量A的单一维,即返回和矩阵A元素相同,但所有单一维都移除的矩阵B,单一维是满足size(A,dim)=1的维. squeeze命令对二维数组是不起作用的; 如果A是一行 ...

  9. JavaScript中的一些细节 分类: C1_HTML/JS/JQUERY 2014-08-05 16:45 384人阅读 评论(0) 收藏

    1.设置id / class等属性 用 setAttribute 设置一些常规属性如 id ,className 的时候经常不起作用,只能用 object.id = value 这样来设置 news_ ...

  10. http500:服务器内部错误案例详解(服务器代码语法错误或者逻辑错误)

    http500:服务器内部错误案例详解(服务器代码语法错误或者逻辑错误) 一.总结 服务器内部错误可能是服务器中代码运行的时候的语法错误或者逻辑错误 二.http500:服务器内部错误案例详解 只是一 ...