<repo_name>wssongwenming/view-practice<file_sep>/propertyanime/src/main/java/com/wondertwo/propertyanime/CustomPointActivity.java
package com.wondertwo.propertyanime;

import android.app.Activity;
import android.os.Bundle;

/**
 * CustomPointActivity
 * Created by wondertwo on 2016/3/27.
 */
public class CustomPointActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 设置包含属性动画的自定义view
        setContentView(R.layout.activity_custom_point);
    }
}
<file_sep>/propertyanime/src/main/java/com/wondertwo/propertyanime/BuleToRed.java
package com.wondertwo.propertyanime;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

/**
 * ColorShade实现目标对象背景色的渐变
 * Created by wondertwo on 2016/3/23.
 */
public class BuleToRed extends Activity {

    private Button targetView;
    private int mCurrentRed = -1;
    private int mCurrentGreen = -1;
    private int mCurrentBlue = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_blue_to_red);

        targetView = (Button) findViewById(R.id.tv_color_backgroound);

        /**
         * 注册点击事件，展示效果
         */
        targetView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                displayResult(targetView, "#0000ff", "#ff0000");
            }
        });
    }

    /**
     * displayResult()展示结果
     */
    private void displayResult(final View target, final String start, final String end) {
        // 创建ValueAnimator对象，实现颜色渐变
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f, 100f);

        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 获取当前动画的进度值，1~100
                float currentValue = (float) animation.getAnimatedValue();
                Log.d("当前动画值", "current value : " + currentValue);

                // 获取动画当前时间流逝的百分比，范围在0~1之间
                float fraction = animation.getAnimatedFraction();
                // 直接调用evaluateForColor()方法，通过百分比计算出对应的颜色值
                String colorResult = evaluateForColor(fraction, start, end);

                /**
                 * 通过Color.parseColor(colorResult)解析字符串颜色值，传给ColorDrawable，创建ColorDrawable对象
                 */
                /*LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) target.getLayoutParams();*/
                ColorDrawable colorDrawable = new ColorDrawable(Color.parseColor(colorResult));
                // 把ColorDrawable对象设置为target的背景
                target.setBackground(colorDrawable);
                target.invalidate();
            }
        });
        valueAnimator.setDuration(6 * 1000);


        // 组装缩放动画
        ValueAnimator animator_1 = ObjectAnimator.ofFloat(target, "scaleX", 1f, 0.5f);
        ValueAnimator animator_2 = ObjectAnimator.ofFloat(target, "scaleY", 1f, 0.5f);
        ValueAnimator animator_3 = ObjectAnimator.ofFloat(target, "scaleX", 0.5f, 1f);
        ValueAnimator animator_4 = ObjectAnimator.ofFloat(target, "scaleY", 0.5f, 1f);
        AnimatorSet set_1 = new AnimatorSet();
        set_1.play(animator_1).with(animator_2);
        AnimatorSet set_2 = new AnimatorSet();
        set_2.play(animator_3).with(animator_4);
        AnimatorSet set_3 = new AnimatorSet();
        set_3.play(set_1).before(set_2);
        set_3.setDuration(3 * 1000);

        // 组装颜色动画和缩放动画，并启动动画
        AnimatorSet set_4 = new AnimatorSet();
        set_4.play(valueAnimator).with(set_3);
        set_4.start();
    }

    /**
     * evaluateForColor()计算颜色值并返回
     */
    private String evaluateForColor(float fraction, String startValue, String endValue) {

        String startColor = startValue;
        String endColor = endValue;
        int startRed = Integer.parseInt(startColor.substring(1, 3), 16);
        int startGreen = Integer.parseInt(startColor.substring(3, 5), 16);
        int startBlue = Integer.parseInt(startColor.substring(5, 7), 16);
        int endRed = Integer.parseInt(endColor.substring(1, 3), 16);
        int endGreen = Integer.parseInt(endColor.substring(3, 5), 16);
        int endBlue = Integer.parseInt(endColor.substring(5, 7), 16);

        // 初始化颜色的值
        if (mCurrentRed == -1) {
            mCurrentRed = startRed;
        }
        if (mCurrentGreen == -1) {
            mCurrentGreen = startGreen;
        }
        if (mCurrentBlue == -1) {
            mCurrentBlue = startBlue;
        }

        // 计算初始颜色和结束颜色之间的差值
        int redDiff = Math.abs(startRed - endRed);
        int greenDiff = Math.abs(startGreen - endGreen);
        int blueDiff = Math.abs(startBlue - endBlue);
        int colorDiff = redDiff + greenDiff + blueDiff;
        if (mCurrentRed != endRed) {
            mCurrentRed = getCurrentColor(startRed, endRed, colorDiff, 0, fraction);
        } else if (mCurrentGreen != endGreen) {
            mCurrentGreen = getCurrentColor(startGreen, endGreen, colorDiff, redDiff, fraction);
        } else if (mCurrentBlue != endBlue) {
            mCurrentBlue = getCurrentColor(startBlue, endBlue, colorDiff,
                    redDiff + greenDiff, fraction);
        }

        // 将计算出的当前颜色的值组装返回
        String currentColor = "#" + getHexString(mCurrentRed)
                + getHexString(mCurrentGreen) + getHexString(mCurrentBlue);
        return currentColor;
    }

    /**
     * 根据fraction值来计算当前的颜色。
     */
    private int getCurrentColor(int startColor, int endColor, int colorDiff,
                                int offset, float fraction) {
        int currentColor;
        if (startColor > endColor) {
            currentColor = (int) (startColor - (fraction * colorDiff - offset));
            if (currentColor < endColor) {
                currentColor = endColor;
            }
        } else {
            currentColor = (int) (startColor + (fraction * colorDiff - offset));
            if (currentColor > endColor) {
                currentColor = endColor;
            }
        }
        return currentColor;
    }

    /**
     * 将10进制颜色值转换成16进制。
     */
    private String getHexString(int value) {
        String hexString = Integer.toHexString(value);
        if (hexString.length() == 1) {
            hexString = "0" + hexString;
        }
        return hexString;
    }
}
<file_sep>/propertyanime/src/main/java/com/wondertwo/propertyanime/PositionView.java
package com.wondertwo.propertyanime;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;

/**
 *
 * Created by wondertwo on 2016/3/27.
 */
public class PositionView extends View {

    public static final float RADIUS = 20f;
    private PositionPoint currentPoint;
    private Paint mPaint;
    // 轨迹起始点坐标(160,20)
    private float startX = 160f;
    private float startY = 20f;
    Bitmap bmSource = BitmapFactory.decodeResource(getResources(), R.drawable.bm_round);

    public PositionView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (currentPoint == null) {
            currentPoint = new PositionPoint(RADIUS, RADIUS);
            drawCircle(canvas);
            startPropertyAni();
        } else {
            drawCircle(canvas);
        }
    }

    private void drawCircle(Canvas canvas) {
        float x = currentPoint.getX();
        float y = currentPoint.getY();
        canvas.drawCircle(x, y, RADIUS, mPaint);
    }

    /**
     * 启动动画
     */
    private void startPropertyAni() {
        ValueAnimator animator = ValueAnimator.ofObject(
                new PositionEvaluator(),
                createPoint(RADIUS, RADIUS),
                createPoint(getWidth() - RADIUS, getHeight() - RADIUS));
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentPoint = (PositionPoint) animation.getAnimatedValue();
                // 获取当前坐标
                float currentX = currentPoint.getX();
                float currentY = currentPoint.getY();
                // 绘制轨迹
                Drawable drawable = drawRound(startX, startY, currentX, currentY);
                setBackground(drawable);
                // 重置起始点坐标
                startX = currentX;
                startY = currentY;
                // 刷新view
                invalidate();
            }
        });
        animator.setInterpolator(new DeceAcceInterpolator());
        animator.setDuration(10 * 1000).start();
        /*Log.d("自定义view中开启动画", "startPropertyAni()");*/
    }

    /**
     * 绘制轨迹
     */
    private Drawable drawRound(float startX, float startY, float endX, float endY) {
        // 加载轨迹背景
        Bitmap bmRound = Bitmap.createBitmap(bmSource.getWidth(), bmSource.getHeight(), bmSource.getConfig());
        bmRound.isMutable();
        Canvas canvas = new Canvas(bmRound);
        Paint roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        roundPaint.setColor(Color.RED);
        roundPaint.setStrokeWidth(5);
        canvas.drawLine(startX, startY, endX, endY, roundPaint);
        canvas.save();
        Drawable drawable = new BitmapDrawable(bmRound);
        return drawable;
    }

    /**
     * createPoint()创建PositionPointView对象
     */
    public PositionPoint createPoint(float x, float y) {
        return new PositionPoint(x, y);
    }

    /**
     * 小圆点内部类
     */
    class PositionPoint {
        private float x;
        private float y;

        public PositionPoint(float x, float y) {
            this.x = x;
            this.y = y;
        }

        public float getX() {
            return x;
        }

        public float getY() {
            return y;
        }
    }
}
<file_sep>/settings.gradle
include ':wallpaper', ':propertyanime', ':praclistview', ':pracdownload', ':swipedemo', ':pracrecyclerview', ':imageloader'
include ':ImageLoaderDemo'
<file_sep>/propertyanime/src/main/java/com/wondertwo/propertyanime/PositionDeAcActivity.java
package com.wondertwo.propertyanime;

import android.app.Activity;
import android.os.Bundle;

/**
 * PositionDeAcActivity自定义减速加速插值器测试类
 * Created by wondertwo on 2016/3/25.
 */
public class PositionDeAcActivity extends Activity {

    // public static PositionView positionView;// 定义PositionView自定义view对象
    // private float screenWidth, screenHeight;// 屏幕宽高
    public static Activity mainActivity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dece_acce);

        // 获取PositionDeAcActivity上下文对象
        mainActivity = PositionDeAcActivity.this;

        /*// 创建PositionView自定义view对象
        positionView = new PositionView(PositionDeAcActivity.this, null);
        // 获取屏幕宽高
        screenWidth = getWindowManager().getDefaultDisplay().getWidth();
        screenHeight = getWindowManager().getDefaultDisplay().getHeight();

        // 注册按钮事件
        Button start = (Button) findViewById(R.id.btn_start_ani);
        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startPropertyAni();
            }
        });*/
    }

    /*private void startPropertyAni() {
        *//*PositionView.PositionPoint point_1 = positionView.createPoint(screenWidth / 2, 20f);
        PositionView.PositionPoint point_2 = positionView.createPoint(screenWidth / 2, screenHeight);*//*
        ValueAnimator animator = ValueAnimator.ofObject(
                new PositionEvaluator(),
                positionView.createPoint(screenWidth / 2, 40f),
                positionView.createPoint(screenWidth / 2, screenHeight));
        animator.setDuration(10 * 1000).start();
    }*/
}
