Android Open Source - MovingImageView Moving View Animator






From Project

Back to project page MovingImageView.

License

The source code is released under:

Apache License

If you think the Android project MovingImageView listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2014 Albert Grobas/* w w  w  . j  a  v  a 2  s  .c  o m*/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.grobas.animation;

import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;

import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorListenerAdapter;
import com.nineoldandroids.animation.AnimatorSet;
import com.nineoldandroids.animation.ObjectAnimator;
import com.nineoldandroids.animation.PropertyValuesHolder;

import java.util.ArrayList;
import java.util.List;

/**
 * Create a custom animation using <code>NineOldAndroids</code> for back compatibility.
 * There are 4 types: horizontal, vertical, diagonal and auto.
 * Auto adds all other 3 types.
 * Very beta stage yet!
 */
public class MovingViewAnimator {
    //movement type vars
    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;
    //Animators and view vars
    private AnimatorSet mAnimatorSet;
    private Animator.AnimatorListener animatorListener;
    private View mView;
    //helper vars
    private boolean isRunning;
    private int movementType;
    private float offsetWidth, offsetHeight;
    private ArrayList<Float> pathDistances;
    //user vars
    private int loopCount = -1;
    private int currentLoop;
    private int mSpeed = 50;
    private long mDelay = 0;
    private boolean infiniteRepetition = true;
    private Interpolator mInterpolator;

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

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

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

    /**
     * Sets the animation travel types.
     */
    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() {
        addListener(animatorListener);
        setSpeed(mSpeed);
        setStartDelay(mDelay);
        setRepetition(loopCount);
        setInterpolator(mInterpolator);
    }

    /**
     * <code>AnimatorSet</code> doesn't have a reverse mode...
     * Tricky but works.
     */
    private void updateListener() {
        mAnimatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                //View always in UI threat!
                mView.post((new Runnable() {
                    public void run() {
                        if(isRunning) {
                            if(infiniteRepetition) {
                                mAnimatorSet.start();
                            } else {
                                currentLoop--;
                                if (currentLoop > 0) {
                                    mAnimatorSet.start();
                                }
                            }
                        }
                    }
                }));
            }
        });
    }

    /**
     * Update animation base vars.
     *
     * @param type new movement type.
     * @param w new width offset.
     * @param h new height offset.
     */

    public void updateValues(int type, float w, float h) {
        this.movementType = type;
        this.offsetWidth = w;
        this.offsetHeight = h;
        init();
    }

    public void start() {
        if(movementType != NONE_MOVE) {
            isRunning = true;
            if(!infiniteRepetition)
                currentLoop = loopCount;
            mAnimatorSet.start();
        }
    }

    public void stop() {
        isRunning = false;
        mAnimatorSet.end();
        mView.clearAnimation();
    }

    public void setRepetition(int repetition) {
        if(repetition < 0)
            infiniteRepetition = true;
        else {
            loopCount = repetition;
            currentLoop = loopCount;
            infiniteRepetition = false;
        }
    }

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

    public int getMovementType() {
        return movementType;
    }

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

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

    public void setStartDelay(long time) {
        mDelay = time;
        mAnimatorSet.setStartDelay(time);
    }

    /**
     * For each animation child sets their duration using length/speed operation.
     *
     * @param speed new speed.
     */
    public void setSpeed(int speed) {
        mSpeed = speed;
        List<Animator> listAnimator = mAnimatorSet.getChildAnimations();
        for(int i = 0; i < listAnimator.size(); i++) {
            Animator a = listAnimator.get(i);
            a.setDuration(parseSpeed(pathDistances.get(i)));
        }
    }

    public void addListener(Animator.AnimatorListener listener) {
        clearListener();
        if(listener != null) {
            animatorListener = listener;
            mAnimatorSet.addListener(animatorListener);
        }
    }

    public void clearListener() {
        if(animatorListener != null) {
            mAnimatorSet.removeListener(animatorListener);
            animatorListener = null;
        }
    }

    private long parseSpeed(float distance) {
        return (long) ((distance/(float)mSpeed) * 1000f);
    }

    private ObjectAnimator createHorizontalAnimator(float startValue, float endValue) {
        pathDistances.add(Math.abs(startValue-endValue));
        return createObjectAnimation("scrollX", startValue, endValue);
    }

    private ObjectAnimator createVerticalAnimator(float startValue, float endValue) {
        pathDistances.add(Math.abs(startValue-endValue));
        return createObjectAnimation("scrollY", startValue, endValue);
    }

    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));
    }

    /**
     * Class for create custom AUTO travel type.
     */
    public class Builder {

        private ArrayList<Animator> mList;

        Builder() {
            mList = new ArrayList<Animator>();
            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);
            updateListener();
            setUpValues();
            MovingViewAnimator.this.start();
        }

    }

}




Java Source Code List

net.grobas.animation.MovingViewAnimator.java
net.grobas.movingimageview.sample.SampleActivity.java
net.grobas.view.MovingImageView.java