属性动画绘制者Animator和自定义View

一、属性动画

1.Animator

         3.0之后的api,如果要在3.0之前使用需要导入NineOldAndroids。

 

2.ObjectAnimator

         改变对象(Object)的属性,需要目标对象中对属性有get/set的方法。

         如:

         //可以帮助视图修改显示宽度,以及显示高度的类型

   class ViewTool {

       View v;

       ViewTool(View v) {

           this.v = v;

       }

 

       public void setWidth(int width) {

           v.getLayoutParams().width = width;

           //刷新视图

           v.requestLayout();

       }

 

       public int getWidth() {

           return v.getLayoutParams().width;

       }

    }

         要对ViewTool这个对象改变width

         ViewToolvt = new ViewTool(view);

         ObjectAnimator.ofInt(vt,"width",vt.getWidth(),500).setDuration(3000).start();

 

3.ValueAnimator

         改变数值的对象,需要设置改变范围、设置改变监听

         privatevoid playAnimatorByValue(final int oldWidth) {

       //创建ValueAnimator

       ValueAnimator anim = ValueAnimator.ofInt(1, 100);

       //添加变化监听

       anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

           private IntEvaluator mEvaluator = new IntEvaluator();

           @Override

           public void onAnimationUpdate(ValueAnimator valueAnimator) {

                int current = (Integer)valueAnimator.getAnimatedValue();

                Log.e("m_tag","==>" + current);

                //取当前的宽度

         //                    //基于当前变化的值算出要加的量

         //                    int wantAdd = 380 * current/ 100;

         //                    int w = oldWidth+ wantAdd;

         //                    //改变显示的宽度

         //                   mBtn.getLayoutParams().width = w;

                float fraction = current /100f;

                int w =mEvaluator.evaluate(fraction, oldWidth, 500);

                mBtn.getLayoutParams().width =w;

                mBtn.requestLayout();

           }

       });

       anim.setDuration(3000).start();

    }


二、自定义View

(一) View的显示流程

         1、onMeasure,计算实际宽高

         2、onLayout,容器布置显示位置和大小

         3、onDraw,显示效果

(二)自定义属性

         可以再values下创建属性资源文件,如attrs.xml,然后在resource标签中添加属性的定义。

         <!--声明一系列属性集(属性数组)的标签 -->

   <declare-styleable name="MyTextView">

       <attr name="bigText" format="string"/>

       <attr name="bigTextSize" format="dimension"/>

        <attr name="bigTextColor"format="color"/>

       <attr name="smallText" format="string"/>

       <attr name="smallTextSize"format="dimension"/>

       <attr name="smallTextColor" format="color"/>

   </declare-styleable>

         format表示属性的类型string是字符串 dimension表示尺寸 color表示颜色。

        

(三)应用自定义属性

         需要在使用自定属性的布局中添加属性的命名空间(前缀)

         如:

         <LinearLayout

                ...

   xmlns:abc="http://schemas.android.com/apk/res-auto"

    ...>

 

   <com.xyy.viewdemo.MyTextView

           ...

       abc:bigText="@string/app_name"

       abc:bigTextSize="30sp"

       abc:bigTextColor="@color/colorAccent"

       abc:smallText="你好"

       abc:smallTextColor="#ff0000ff"

       abc:smallTextSize="20sp"/>

         </LinearLayout>

 

(四)解析自定义属性

         需要在自定义View的构造中获取属性值

         /**一般在xml布局中使用自定义标签(包名.类名)申明,会调用的构造方法

     *@param context 视图依赖的环境(如Activity)

     *@param attrs   属性域

    */

   public MyTextView(Context context, AttributeSet attrs) {

       super(context, attrs); //该父类构造的调用均可以解析基本属性:宽高背景边距

       //将AttributeSet转为TypeArray

       TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyTextView);

       //按照属性下标解析属性值

       bigTitle = ta.getString(R.styleable.MyTextView_bigText);

       bigTitleSize = ta.getDimensionPixelSize(R.styleable.MyTextView_bigTextSize,20);

       bigTitleColor = ta.getColor(R.styleable.MyTextView_bigTextColor,Color.BLACK);

       smallTitle = ta.getString(R.styleable.MyTextView_smallText);

       smallTitleSize =ta.getDimensionPixelSize(R.styleable.MyTextView_smallTextSize, 16);

       smallTitleColor = ta.getColor(R.styleable.MyTextView_smallTextColor,Color.RED);

       //这里解析完毕一定要回收掉TypedArray

       ta.recycle();

       init();

    }

 

(五)自定义宽高

         需要重写onMeasure方法通过setMeasuredDimension设置实际宽高。

          //视图需要测量宽高时触发(计算自身的宽高告诉父容器)

   @Override

   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

                   //获取高方向的模式

       int heightMode = MeasureSpec.getMode(heightMeasureSpec);

                   //获取参考的高度

       int height = MeasureSpec.getSize(heightMeasureSpec);

                   //如果模式为wrap_content方式,则计算精确的高度设置到MeasuredDimension

       if (heightMode == MeasureSpec.AT_MOST) {

           computeHeight();

           height = bigHeight + smallHeight + 15;

       }

       setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec), height);

    }

 

(六)画出效果

          //该视图显示的效果

   @Override

   protected void onDraw(Canvas canvas) {

       super.onDraw(canvas);

       mPaint.setTextSize(bigTitleSize);

       mPaint.setColor(bigTitleColor);

        //画文本

       Paint.FontMetrics fm = mPaint.getFontMetrics();

       int bigHeight = (int) (fm.bottom - fm.top);

       canvas.drawText(bigTitle,5,bigHeight,mPaint);

       mPaint.setTextSize(smallTitleSize);

       mPaint.setColor(smallTitleColor);

       fm = mPaint.getFontMetrics();

       int smallHeight = (int) (fm.bottom - fm.top);

       canvas.drawText(smallTitle,15,smallHeight+bigHeight+5,mPaint);

    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章