屬性動畫繪製者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);

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