博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android自定义动画
阅读量:5281 次
发布时间:2019-06-14

本文共 8543 字,大约阅读时间需要 28 分钟。

前一篇说了实现过程,这次来写一个自己简单实现的3d动画

先来属性声明配置,方便使用xml 文件来定制动画

配置参数相关的一些解释

  dimension 像素值类型,包括有"px", "dip", "sp", "pt", "in", "mm", 一般用TypedValue.complexToDimension解析

  fraction 分数,一般用来表示占的百分比,"%", "%p"。 一般用TypedValue.complexToFraction解析 有时候和float类型功能通用
  float 浮点数。当确定是这个类型的时候,用TypedValue.getFloat解析
  integer 整数,TypedValue.data 就是这个值。
  后两者,如果参数只有确定的一个类型,直接用TypedArray 的 getInteger 或者 getFloat方法就可以获取

动画配置

 

含在集合内的动画配置

 

动画类的代码

public class CubeAnimation extends Animation {        private float mFromDegrees;    private float mToDegrees;        private int mFromXType = ABSOLUTE;;    private float mFromX = 0;    private int mFromXdata = 0;        private int mToXType = ABSOLUTE;    private float mToX = 0;    private int mToXData = 0;        private Camera mCamera;    private Resources mResources;    private float mAxisY = 0;    private int mAxisYType = ABSOLUTE;        public CubeAnimation(float fromX,float toX,float fromDegree,float toDegree,float axisY) {        this.mFromX = fromX;        this.mToX = toX;        this.mFromDegrees = fromDegree;        this.mToDegrees = toDegree;        this.mAxisY = axisY;                mFromXType = TypedValue.TYPE_FLOAT;        mToXType = TypedValue.TYPE_FLOAT;        mAxisYType = ABSOLUTE;            }    public CubeAnimation(Context context, AttributeSet attrs) {        super(context, attrs);        TypedArray a = context.obtainStyledAttributes(attrs,                R.styleable.CubeAnimation);        mResources = context.getResources();        TypedValue value = a.peekValue(R.styleable.CubeAnimation_fromX);        if(value.type==TypedValue.TYPE_FLOAT){            this.mFromX = value.getFloat();            this.mFromXType = value.type;        }else{            this.mFromXType = value.type;            this.mFromXdata = value.data;        }                value = a.peekValue(R.styleable.CubeAnimation_toX);        if(value.type==TypedValue.TYPE_FLOAT){
//FLOAT 类型的,必须在这里解析了,因为下边的resolveData 方法拿不到TypedValue,没法解析 this.mToX = value.getFloat(); this.mToXType = value.type; }else{ this.mToXType = value.type; this.mToXData = value.data; } boolean t = a.getBoolean(R.styleable.CubeAnimation_positive, true); if (!(t)) { this.mToDegrees = 0.0F; this.mFromDegrees = 90.0F; } this.mFromDegrees = a.getFloat(R.styleable.CubeAnimation_fromDegree, 0); this.mToDegrees = a.getFloat(R.styleable.CubeAnimation_toDegree, 90); value = a.peekValue(R.styleable.CubeAnimation_axisY); this.mAxisYType = value.type; //参数不同类型用来做什么用,按自己需求来设定和解析,我这里配置文件属性要求是两种
//如果是float类型,则做用来做组件的比例 如果是int型,认为是像素值 if(this.mAxisYType==TypedValue.TYPE_FLOAT){ this.mAxisY = value.getFloat(); this.mAxisYType = RELATIVE_TO_SELF; }else{ this.mAxisY = value.data; } a.recycle(); } public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); if(this.mFromXType!=TypedValue.TYPE_FLOAT){
//这里Float类型代表固定值,且已经解析过,不再解析 下同 this.mFromX = resolveData(this.mFromXType,this.mFromXdata, width, parentWidth); } if(mToXType!=TypedValue.TYPE_FLOAT){ this.mToX = resolveData(this.mToXType,this.mToXData,width,parentWidth); } this.mCamera = new Camera(); if(mAxisYType==RELATIVE_TO_SELF) {
//如果是相对自身的大小比例,则按比例计算获取对应值。否则,则为固定像素值 mAxisY = mAxisY*height; } System.out.println("mFromX="+mFromX+",mToX=="+mToX); } float resolveData( int type, int data, int size, int psize) { float value = 0; if (type == TypedValue.TYPE_FRACTION) { value = TypedValue.complexToFraction(data, size, psize); } else if (type == TypedValue.TYPE_DIMENSION) { value = TypedValue.complexToDimension(data, mResources.getDisplayMetrics()); } else{
//如果是由代码设置成的ABSOLUTE类型或者 配置文件本身就是int的固定值 value= data; } return value; } // 自定义动画主要要实现的方法 protected void applyTransformation(float interpolatedTime, Transformation t) { float fromDegrees = this.mFromDegrees; float degrees = fromDegrees + (this.mToDegrees - fromDegrees) * interpolatedTime; Camera camera = this.mCamera; Matrix matrix = t.getMatrix(); camera.save(); camera.rotateX(degrees); camera.getMatrix(matrix); camera.restore(); matrix.postTranslate(mFromX+(mToX-mFromX)*interpolatedTime, this.mAxisY); } // 因为用AnimationUtils无法解析出这个动画的属性,所以所有CubeAnimation的配置文件或者包含这个动画的set配置文件,必须用这个方法加载 public static Animation loadAnimation(Context context, int id) throws NotFoundException { XmlResourceParser parser = null; try { parser = context.getResources().getAnimation(id); return createAnimationFromXml(context, parser, null, Xml.asAttributeSet(parser)); } catch (XmlPullParserException ex) { NotFoundException rnf = new NotFoundException( "Can't load animation resource ID #0x" + Integer.toHexString(id)); rnf.initCause(ex); throw rnf; } catch (IOException ex) { NotFoundException rnf = new NotFoundException( "Can't load animation resource ID #0x" + Integer.toHexString(id)); rnf.initCause(ex); throw rnf; } finally { if (parser != null) parser.close(); } } private static Animation createAnimationFromXml(Context c, XmlPullParser parser, AnimationSet parent, AttributeSet attrs) throws XmlPullParserException, IOException { Animation anim = null; // Make sure we are on a start tag. int type; int depth = parser.getDepth(); while (((type = parser.next()) != XmlPullParser.END_TAG || parser .getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { if (type != XmlPullParser.START_TAG) { continue; } String name = parser.getName(); if (name.equals("set")) { anim = new AnimationSet(c, attrs); createAnimationFromXml(c, parser, (AnimationSet) anim, attrs); } else if (name.equals("alpha")) { anim = new AlphaAnimation(c, attrs); } else if (name.equals("scale")) { anim = new ScaleAnimation(c, attrs); } else if (name.equals("rotate")) { anim = new RotateAnimation(c, attrs); } else if (name.equals("translate")) { anim = new TranslateAnimation(c, attrs); } else if (name.equals("cube")) { anim = new CubeAnimation(c, attrs); } else { throw new RuntimeException( "not a cubeanimation animation name: " + parser.getName()); } } if (parent != null) { parent.addAnimation(anim); } return anim; }}
View Code

 

配置文件加载和动态构造两种方式创建对话实例以及调用

public class AnimateActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        this.setContentView(R.layout.activity_main);        View view = this.findViewById(R.id.tv);        view.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                Animation animation;                if(v.getTag()==null||(Boolean)v.getTag()){                    ((TextView)v).setText("配置文件加载");                    animation = CubeAnimation.loadAnimation(getApplicationContext(), R.anim.cubeanimation);                    v.setTag(false);                }else{                    ((TextView)v).setText("动态初始化");                    animation = new CubeAnimation(0, 400, 0, 360, 100);                    animation.setDuration(8000);                    v.setTag(true);                }                v.startAnimation(animation);            }        });    }}
View Code

 

 

ok 基本完成,希望没有什么遗漏

转载于:https://www.cnblogs.com/boliu/p/3296083.html

你可能感兴趣的文章
利用AMPScript获取Uber用户数据的访问权限
查看>>
vagrant 同时设置多个同步目录
查看>>
python接口自动化28-requests-html爬虫框架
查看>>
生成随机数的模板
查看>>
Mysql 数据库操作
查看>>
转:linux终端常用快捷键
查看>>
UVa 11059 最大乘积
查看>>
数组分割问题求两个子数组的和差值的小
查看>>
composer 报 zlib_decode(): data error
查看>>
hdu 3938 并查集
查看>>
《深入分析Java Web技术内幕》读书笔记之JVM内存管理
查看>>
python之GIL release (I/O open(file) socket time.sleep)
查看>>
软件开发与模型
查看>>
161017、SQL必备知识点
查看>>
kill新号专题
查看>>
MVC学习系列——Model验证扩展
查看>>
字符串
查看>>
vue2.x directive - 限制input只能输入正整数
查看>>
实现MyLinkedList类深入理解LinkedList
查看>>
自定义返回模型
查看>>