一个可以自己移动的自定义imageview

代码如下:

public class MovingImageView extends ImageView {

    private float canvasWidth, canvasHeight;
    private float imageWidth, imageHeight;
    private float offsetWidth, offsetHeight;
    /**
     * 移动类型
     */
    private int movementType;

    /**
     * 限定最大比值
     * canvasHeight/drawableHeight 或者 canvasWidth/drawableWidth
     */
    private float maxRelativeSize;
    /**
     * 最小相对偏移值,图片最起码可以位移图*0.2的距离
     */
    private float minRelativeOffset;
    private int mSpeed;
    private long startDelay;
    private int mRepetitions;
    private boolean loadOnCreate;//load完毕后是否移动

    private MovingViewAnimator mAnimator;

    public MovingImageView(Context context) {
        this(context, null);
    }

    public MovingImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MovingImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        TypedArray ta = context.getTheme().obtainStyledAttributes(attrs,
                R.styleable.MovingImageView, defStyle, 0);

        try {
            maxRelativeSize = ta.getFloat(R.styleable.MovingImageView_miv_max_relative_size, 3.0f);
            minRelativeOffset = ta.getFloat(R.styleable.MovingImageView_miv_min_relative_offset,
                    0.2f);
            mSpeed = ta.getInt(R.styleable.MovingImageView_miv_speed, 50);
            mRepetitions = ta.getInt(R.styleable.MovingImageView_miv_repetitions, -1);
            startDelay = ta.getInt(R.styleable.MovingImageView_miv_start_delay, 0);
            loadOnCreate = ta.getBoolean(R.styleable.MovingImageView_miv_load_on_create, true);
        } finally {
            ta.recycle();
        }

        init();
    }

    private void init() {
        super.setScaleType(ScaleType.MATRIX);
        mAnimator = new MovingViewAnimator(this);
    }

    /**
     * 更新canvas size
     *
     * @param w    new width.
     * @param h    new height.
     * @param oldW old width.
     * @param oldH old height.
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldW, int oldH) {
        super.onSizeChanged(w, h, oldW, oldH);
        canvasWidth = (float) w - (float) (getPaddingLeft() + getPaddingRight());
        canvasHeight = (float) h - (float) (getPaddingTop() + getPaddingBottom());
        updateAll();
    }

    private void updateAll() {
        if (getDrawable() != null) {
            updateImageSize();
            updateOffsets();
            updateAnimatorValues();
        }
    }

    /**
     * 更新图片Size
     */
    private void updateImageSize() {
        imageWidth = getDrawable().getIntrinsicWidth();//获取图片高度
        imageHeight = getDrawable().getIntrinsicHeight();//获取图片宽度
    }

    /**
     * 更新偏移量,确定动画范围
     */
    private void updateOffsets() {
        float minSizeX = imageWidth * minRelativeOffset;
        float minSizeY = imageHeight * minRelativeOffset;
        offsetWidth = (imageWidth - canvasWidth - minSizeX) > 0 ? imageWidth - canvasWidth : 0;
        offsetHeight = (imageHeight - canvasHeight - minSizeY) > 0 ? imageHeight - canvasHeight : 0;
    }

    /**
     * 更新动画基本数据
     */
    private void updateAnimatorValues() {
        if (canvasHeight == 0 && canvasWidth == 0)
            return;

        float scale = calculateTypeAndScale();
        if (scale == 0)
            return;

        float w = (imageWidth * scale) - canvasWidth;
        float h = (imageHeight * scale) - canvasHeight;

        mAnimator.updateValues(movementType, w, h);
        mAnimator.setStartDelay(startDelay);
        mAnimator.setSpeed(mSpeed);
        mAnimator.setRepetition(mRepetitions);

        if (loadOnCreate) {
            startMoving();
        }
    }

    /**
     * 设置最佳的运动类型
     * 计算缩放比例
     *
     * @return image scale.
     */
    private float calculateTypeAndScale() {
        movementType = MovingViewAnimator.AUTO_MOVE;
        float scale = 1f;
        float scaleByImage = Math.max(imageWidth / canvasWidth, imageHeight / canvasHeight);
        Matrix matrix = new Matrix();

        if (offsetWidth == 0 && offsetHeight == 0) {//图片太小,无法动画,需要放大
            //画布宽度/图片宽度
            float sW = canvasWidth / imageWidth;
            //画布高度/图片高度
            float sH = canvasHeight / imageHeight;

            if (sW > sH) {
                scale = Math.min(sW, maxRelativeSize);//限定最大缩放值
                matrix.setTranslate((canvasWidth - imageWidth * scale) / 2f, 0);
                movementType = MovingViewAnimator.VERTICAL_MOVE;//垂直移动

            } else if (sW < sH) {
                scale = Math.min(sH, maxRelativeSize);//限定最大缩放值
                matrix.setTranslate(0, (canvasHeight - imageHeight * scale) / 2f);
                movementType = MovingViewAnimator.HORIZONTAL_MOVE;//水平移动

            } else {
                scale = Math.max(sW, maxRelativeSize);//限定最大缩放值
                movementType = (scale == sW) ? MovingViewAnimator.NONE_MOVE :
                        MovingViewAnimator.DIAGONAL_MOVE;//对角线移动
            }
        } else if (offsetWidth == 0) {//宽度太小,无法执行水平动画,放大宽度
            scale = canvasWidth / imageWidth;
            movementType = MovingViewAnimator.VERTICAL_MOVE;

        } else if (offsetHeight == 0) {//高度太小,无法执行垂直动画,放大高度
            scale = canvasHeight / imageHeight;//求出画布高度和图片高度的比值用于确定画布起始坐标
            movementType = MovingViewAnimator.HORIZONTAL_MOVE;

        } else if (scaleByImage > maxRelativeSize) {//图片太大,根据最大比值设定图片缩放值
            scale = maxRelativeSize / scaleByImage;
            if (imageWidth * scale < canvasWidth || imageHeight * scale < canvasHeight) {
                scale = Math.max(canvasWidth / imageWidth, canvasHeight / imageHeight);
            }
        }

        matrix.preScale(scale, scale);
        setImageMatrix(matrix);
        return scale;
    }

    /**
     * 禁止设置ScaleType
     *
     * @param scaleType
     */
    @Override
    @Deprecated
    public void setScaleType(ScaleType scaleType) {
        //super.setScaleType(scaleType);
    }

    @Override
    public void setImageResource(int resId) {
        super.setImageResource(resId);
        updateAll();
    }

    @Override
    public void setImageURI(Uri uri) {
        super.setImageURI(uri);
        updateAll();
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        super.setImageDrawable(drawable);
        updateAll();
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        super.setImageBitmap(bm);
        updateAll();
    }

    /**
     * 获取animator
     *
     * @return
     */
    public MovingViewAnimator getMovingAnimator() {
        return mAnimator;
    }

    public float getMaxRelativeSize() {
        return maxRelativeSize;
    }

    public void setMaxRelativeSize(float max) {
        maxRelativeSize = max;
        updateAnimatorValues();
    }

    public float getMinRelativeOffset() {
        return minRelativeOffset;
    }

    public void setMinRelativeOffset(float min) {
        minRelativeOffset = min;
        updateAnimatorValues();
    }

    public boolean isLoadOnCreate() {
        return loadOnCreate;
    }

    public void setLoadOnCreate(boolean loadOnCreate) {
        this.loadOnCreate = loadOnCreate;
    }

    /**
     * 开始移动
     * 默认不停的移动
     */
    public void startMoving() {
        startMoving(-1);
    }

    /**
     * 开始移动
     *
     * @param repetition 循环模式
     */
    public void startMoving(int repetition) {
        mAnimator.setRepetition(repetition);
        mAnimator.start();
    }

    /**
     * 恢复移动
     */
    public void resumeMoving() {
        mAnimator.resume();
    }

    /**
     * 暂停移动
     */
    public void pauseMoving() {
        mAnimator.pause();
    }

    /**
     * 停止移动
     */
    public void stopMoving() {
        mAnimator.stop();
    }

    /**
     * 获取当前状态
     *
     * @return
     */
    public MovingViewAnimator.MovingState getMovingState() {
        return mAnimator.getMovingState();
    }
}
public class MovingViewAnimator {
    /**
     * 水平移动
     */
    public static final int HORIZONTAL_MOVE = 1;
    /**
     * 垂直移动
     */
    public static final int VERTICAL_MOVE = 2;
    /**
     * 对角线移动
     */
    public static final int DIAGONAL_MOVE = 3;
    /**
     * 自动移动
     */
    public static final int AUTO_MOVE = 0;
    /**
     * 不移动
     */
    public static final int NONE_MOVE = -1;

    private AnimatorSet mAnimatorSet;
    private View mView;

    private boolean isRunning;
    private int currentLoop;
    private boolean infiniteRepetition = true;
    private ArrayList pathDistances;

    private int loopCount = -1;
    private int movementType;
    private float offsetWidth, offsetHeight;
    private int mSpeed = 50;
    private long mDelay = 0;
    private Interpolator mInterpolator;

    private MovingState currentState = MovingState.stop;

    public enum MovingState {
        stop,
        moving,
        pause
    }

    private Animator.AnimatorListener animatorListener = new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(final Animator animation) {
            //super.onAnimationEnd(animation);
            //运行在主线程
            mView.post((new Runnable() {
                public void run() {
                    if (isRunning) {
                        if (infiniteRepetition) {
                            mAnimatorSet.start();
                        } else {
                            currentLoop--;
                            if (currentLoop > 0) {
                                mAnimatorSet.start();
                            }
                        }
                    }
                }
            }));
        }
    };

    public MovingViewAnimator(View imgView) {
        mView = imgView;
        isRunning = false;
        mAnimatorSet = new AnimatorSet();
        pathDistances = new ArrayList<>();
        mInterpolator = new AccelerateDecelerateInterpolator();
    }

    public MovingViewAnimator(View imgView, int type, float width, float height) {
        this(imgView);
        updateValues(type, width, height);
    }

    private void init() {
        setUpAnimator();
        setUpValues();
    }

    /**
     * 根据移动类型设置不同的动画
     */
    private void setUpAnimator() {
        AnimatorSet animatorSet = new AnimatorSet();
        pathDistances.clear();

        switch (movementType) {
            case HORIZONTAL_MOVE:
                animatorSet.playSequentially(createHorizontalAnimator(0, offsetWidth),
                        createHorizontalAnimator(offsetWidth, 0));
                break;
            case VERTICAL_MOVE:
                animatorSet.playSequentially(createVerticalAnimator(0, offsetHeight),
                        createVerticalAnimator(offsetHeight, 0));
                break;
            case DIAGONAL_MOVE:
                animatorSet.playSequentially(createDiagonalAnimator(0, offsetWidth, 0,
                        offsetHeight),
                        createDiagonalAnimator(offsetWidth, 0, offsetHeight, 0));
                break;
            case AUTO_MOVE:
                animatorSet.playSequentially(
                        createVerticalAnimator(0, offsetHeight),
                        createDiagonalAnimator(0, offsetWidth, offsetHeight, 0),
                        createHorizontalAnimator(offsetWidth, 0),
                        createDiagonalAnimator(0, offsetWidth, 0, offsetHeight),
                        createHorizontalAnimator(offsetWidth, 0),
                        createVerticalAnimator(offsetHeight, 0));
        }

        if (mAnimatorSet != null) {
            mAnimatorSet.removeAllListeners();
            stop();
        }
        mAnimatorSet = animatorSet;
    }

    /**
     * 设置参数数据
     */
    private void setUpValues() {
        setSpeed(mSpeed);
        setStartDelay(mDelay);
        setRepetition(loopCount);
        setInterpolator(mInterpolator);
    }

    private void setListener() {
        mAnimatorSet.addListener(animatorListener);
    }

    /**
     * 更新动画值.
     *
     * @param type
     * @param w
     * @param h
     */
    public void updateValues(int type, float w, float h) {
        this.movementType = type;
        this.offsetWidth = w;
        this.offsetHeight = h;
        init();
    }

    public void setMovementType(int type) {
        updateValues(type, offsetWidth, offsetHeight);
    }

    public void setOffsets(float w, float h) {
        updateValues(movementType, w, h);
    }

    public void start() {
        //Log.e("tag", "start.");
        if (movementType != NONE_MOVE) {
            isRunning = true;
            if (!infiniteRepetition)
                currentLoop = loopCount;
            setListener();
            mAnimatorSet.start();
            currentState = MovingState.moving;
        }
    }

    public void cancel() {
        if (isRunning) {
            mAnimatorSet.removeListener(animatorListener);
            mAnimatorSet.cancel();
            currentState = MovingState.stop;
        }
    }

    @TargetApi(19)
    public void pause() {
        //Log.e("tag", "pause.");
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
            return;

        if (mAnimatorSet.isStarted()) {
            mAnimatorSet.pause();
            currentState = MovingState.pause;
        }
    }

    @TargetApi(19)
    public void resume() {
        //Log.e("tag", "resume.");
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
            return;

        if (mAnimatorSet.isPaused()) {
            mAnimatorSet.resume();
            currentState = MovingState.moving;
        }
    }

    public void stop() {
        //Log.e("tag", "stop.");
        isRunning = false;
        mAnimatorSet.removeListener(animatorListener);
        mAnimatorSet.end();
        mView.clearAnimation();
        currentState = MovingState.stop;
    }

    /**
     * 设置重复模式
     *
     * @param repetition repetition < 0 循环播放
     *                   repetition > 0 循环repetition次
     */
    public void setRepetition(int repetition) {
        if (repetition < 0)
            infiniteRepetition = true;
        else {
            loopCount = repetition;
            currentLoop = loopCount;
            infiniteRepetition = false;
        }
    }

    public Builder addCustomMovement() {
        return new Builder();
    }

    public void clearCustomMovement() {
        init();
        start();
    }

    public int getMovementType() {
        return movementType;
    }

    public int getRemainingRepetitions() {
        return (infiniteRepetition) ? -1 : currentLoop;
    }

    public void setInterpolator(Interpolator interpolator) {
        mInterpolator = interpolator;
        mAnimatorSet.setInterpolator(interpolator);
    }

    /**
     * 设置动画播放之前的延时时间
     *
     * @param time
     */
    public void setStartDelay(long time) {
        mDelay = time;
        mAnimatorSet.setStartDelay(time);
    }

    /**
     * 设置每个动画对应的持续时间
     *
     * @param speed
     */
    public void setSpeed(int speed) {
        mSpeed = speed;
        List listAnimator = mAnimatorSet.getChildAnimations();
        for (int i = 0; i < listAnimator.size(); i++) {
            Animator a = listAnimator.get(i);
            a.setDuration(parseSpeed(pathDistances.get(i)));
        }
    }

    /**
     * 将速度设置值转换成秒
     *
     * @param distance
     * @return
     */
    private long parseSpeed(float distance) {
        return (long) ((distance / (float) mSpeed) * 1000f);
    }

    /**
     * 创建水平移动动画
     *
     * @param startValue
     * @param endValue
     * @return
     */
    private ObjectAnimator createHorizontalAnimator(float startValue, float endValue) {
        pathDistances.add(Math.abs(startValue - endValue));
        return createObjectAnimation("scrollX", startValue, endValue);
    }

    /**
     * 创建垂直移动动画
     *
     * @param startValue
     * @param endValue
     * @return
     */
    private ObjectAnimator createVerticalAnimator(float startValue, float endValue) {
        pathDistances.add(Math.abs(startValue - endValue));
        return createObjectAnimation("scrollY", startValue, endValue);
    }

    /**
     * 创建对角线移动动画
     *
     * @param startW
     * @param endW
     * @param startH
     * @param endH
     * @return
     */
    private ObjectAnimator createDiagonalAnimator(float startW, float endW, float startH, float
            endH) {
        float diagonal = Pythagoras(Math.abs(startW - endW), Math.abs(startH - endH));
        pathDistances.add(diagonal);
        PropertyValuesHolder pvhX = createPropertyValuesHolder("scrollX", startW, endW);
        PropertyValuesHolder pvhY = createPropertyValuesHolder("scrollY", startH, endH);
        return ObjectAnimator.ofPropertyValuesHolder(mView, pvhX, pvhY);
    }

    private ObjectAnimator createObjectAnimation(String prop, float startValue, float endValue) {
        return ObjectAnimator.ofInt(mView, prop, (int) startValue, (int) endValue);
    }

    private PropertyValuesHolder createPropertyValuesHolder(String prop, float startValue, float
            endValue) {
        return PropertyValuesHolder.ofInt(prop, (int) startValue, (int) endValue);
    }

    private static float Pythagoras(float a, float b) {
        return (float) Math.sqrt((a * a) + (b * b));
    }

    /**
     * 自定义自动移动方式
     */
    public class Builder {

        private ArrayList mList;

        private Builder() {
            mList = new ArrayList<>();
            pathDistances.clear();
        }

        public Builder addHorizontalMoveToRight() {
            mList.add(createHorizontalAnimator(0, offsetWidth));
            return this;
        }

        public Builder addHorizontalMoveToLeft() {
            mList.add(createHorizontalAnimator(offsetWidth, 0));
            return this;
        }

        public Builder addVerticalMoveToDown() {
            mList.add(createVerticalAnimator(0, offsetHeight));
            return this;
        }

        public Builder addVerticalMoveToUp() {
            mList.add(createVerticalAnimator(offsetHeight, 0));
            return this;
        }

        public Builder addDiagonalMoveToDownRight() {
            mList.add(createDiagonalAnimator(0, offsetWidth, 0, offsetHeight));
            return this;
        }

        public Builder addDiagonalMoveToDownLeft() {
            mList.add(createDiagonalAnimator(offsetWidth, 0, 0, offsetHeight));
            return this;
        }

        public Builder addDiagonalMoveToUpRight() {
            mList.add(createDiagonalAnimator(0, offsetWidth, offsetHeight, 0));
            return this;
        }

        public Builder addDiagonalMoveToUpLeft() {
            mList.add(createDiagonalAnimator(offsetWidth, 0, offsetHeight, 0));
            return this;
        }

        public void start() {
            mAnimatorSet.removeAllListeners();
            stop();
            mAnimatorSet = new AnimatorSet();
            mAnimatorSet.playSequentially(mList);
            setListener();
            setUpValues();
            MovingViewAnimator.this.start();
        }
    }

    /**
     * 获取当前状态
     *
     * @return
     */
    public MovingState getMovingState() {
        return currentState;
    }
}

最后记得在res--values--attrs.xml文件中,写入如下代码:

 
        
        
        
        
        
        
    

你可能感兴趣的:(一个可以自己移动的自定义imageview)