ImageView翻转效果

点击图中的星星开始翻转
ImageView翻转效果
源码:
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.Transformation;
import android.widget.ImageView;

import fr.castorflex.android.flipimageview.R;

/**
 * Created with IntelliJ IDEA. User: castorflex Date: 30/12/12 Time: 16:25
 */
public class FlipImageView extends ImageView implements View.OnClickListener,
        Animation.AnimationListener {

    private static final int FLAG_ROTATION_X = 1 << 0;

    private static final int FLAG_ROTATION_Y = 1 << 1;

    private static final int FLAG_ROTATION_Z = 1 << 2;

    private static final Interpolator fDefaultInterpolator = new DecelerateInterpolator();

    private static int sDefaultDuration;

    private static int sDefaultRotations;

    private static boolean sDefaultAnimated;

    private static boolean sDefaultFlipped;


    public interface OnFlipListener {

        public void onClick(boolean flipped);

        public void onFlipStart();

        public void onFlipEnd();
    }

    private OnFlipListener mListener;

    private boolean mIsFlipped;

    private boolean mIsDefaultAnimated;

    private Drawable mDrawable;

    private Drawable mFlippedDrawable;

    private FlipAnimator mAnimation;

    private boolean mIsRotationXEnabled;

    private boolean mIsRotationYEnabled;

    private boolean mIsRotationZEnabled;

    public FlipImageView(Context context) {
        super(context);
        init(context, null, 0);
    }

    public FlipImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public FlipImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        sDefaultDuration = context.getResources().getInteger(R.integer.default_fiv_duration);
        sDefaultRotations = context.getResources().getInteger(R.integer.default_fiv_rotations);
        sDefaultAnimated = context.getResources().getBoolean(R.bool.default_fiv_isAnimated);
        sDefaultFlipped = context.getResources().getBoolean(R.bool.default_fiv_isFlipped);

        TypedArray a = context
                .obtainStyledAttributes(attrs, R.styleable.FlipImageView, defStyle, 0);
        mIsDefaultAnimated = a.getBoolean(R.styleable.FlipImageView_isAnimated, sDefaultAnimated);
        mIsFlipped = a.getBoolean(R.styleable.FlipImageView_isFlipped, sDefaultFlipped);
        mFlippedDrawable = a.getDrawable(R.styleable.FlipImageView_flipDrawable);
        int duration = a.getInt(R.styleable.FlipImageView_flipDuration, sDefaultDuration);
        int interpolatorResId = a.getResourceId(R.styleable.FlipImageView_flipInterpolator, 0);
        Interpolator interpolator = interpolatorResId > 0 ? AnimationUtils
                .loadInterpolator(context, interpolatorResId) : fDefaultInterpolator;
        int rotations = a.getInteger(R.styleable.FlipImageView_flipRotations, sDefaultRotations);
        mIsRotationXEnabled = (rotations & FLAG_ROTATION_X) != 0;
        mIsRotationYEnabled = (rotations & FLAG_ROTATION_Y) != 0;
        mIsRotationZEnabled = (rotations & FLAG_ROTATION_Z) != 0;

        mDrawable = getDrawable();

        mAnimation = new FlipAnimator();
        mAnimation.setAnimationListener(this);
        mAnimation.setInterpolator(interpolator);
        mAnimation.setDuration(duration);

        setOnClickListener(this);

        setImageDrawable(mIsFlipped ? mFlippedDrawable : mDrawable);

        a.recycle();
    }

    public boolean isRotationXEnabled() {
        return mIsRotationXEnabled;
    }

    public void setRotationXEnabled(boolean enabled) {
        mIsRotationXEnabled = enabled;
    }

    public boolean isRotationYEnabled() {
        return mIsRotationYEnabled;
    }

    public void setRotationYEnabled(boolean enabled) {
        mIsRotationYEnabled = enabled;
    }

    public boolean isRotationZEnabled() {
        return mIsRotationZEnabled;
    }

    public void setRotationZEnabled(boolean enabled) {
        mIsRotationZEnabled = enabled;
    }

    public FlipAnimator getFlipAnimation() {
        return mAnimation;
    }

    public void setInterpolator(Interpolator interpolator) {
        mAnimation.setInterpolator(interpolator);
    }

    public void setDuration(int duration) {
        mAnimation.setDuration(duration);
    }

    public boolean isFlipped() {
        return mIsFlipped;
    }

    public boolean isAnimated() {
        return mIsDefaultAnimated;
    }

    public void setAnimated(boolean animated) {
        mIsDefaultAnimated = animated;
    }

    public void setFlipped(boolean flipped) {
        setFlipped(flipped, mIsDefaultAnimated);
    }

    public void setFlipped(boolean flipped, boolean animated) {
        if (flipped != mIsFlipped) {
            toggleFlip(animated);
        }
    }

    public void toggleFlip() {
        toggleFlip(mIsDefaultAnimated);
    }

    public void toggleFlip(boolean animated) {
        if (animated) {
            mAnimation.setToDrawable(mIsFlipped ? mDrawable : mFlippedDrawable);
            startAnimation(mAnimation);
        } else {
            setImageDrawable(mIsFlipped ? mDrawable : mFlippedDrawable);
        }
        mIsFlipped = !mIsFlipped;
    }


    public void setOnFlipListener(OnFlipListener listener) {
        mListener = listener;
    }


    @Override
    public void onClick(View v) {
        toggleFlip();
        if (mListener != null) {
            mListener.onClick(mIsFlipped);
        }
    }

    @Override
    public void onAnimationStart(Animation animation) {
        if (mListener != null) {
            mListener.onFlipStart();
        }
    }

    @Override
    public void onAnimationEnd(Animation animation) {
        if (mListener != null) {
            mListener.onFlipEnd();
        }
    }

    @Override
    public void onAnimationRepeat(Animation animation) {
    }

    /**
     * Animation part All credits goes to coomar
     */
    public class FlipAnimator extends Animation {

        private Camera camera;

        private Drawable toDrawable;

        private float centerX;

        private float centerY;

        private boolean forward = true;

        private boolean visibilitySwapped;

        public void setToDrawable(Drawable to) {
            toDrawable = to;
            visibilitySwapped = false;
        }

        public FlipAnimator() {
            setFillAfter(true);
        }


        @Override
        public void initialize(int width, int height, int parentWidth, int parentHeight) {
            super.initialize(width, height, parentWidth, parentHeight);
            camera = new Camera();
            this.centerX = width / 2;
            this.centerY = height / 2;
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            // Angle around the y-axis of the rotation at the given time. It is
            // calculated both in radians and in the equivalent degrees.
            final double radians = Math.PI * interpolatedTime;
            float degrees = (float) (180.0 * radians / Math.PI);

            // Once we reach the midpoint in the animation, we need to hide the
            // source view and show the destination view. We also need to change
            // the angle by 180 degrees so that the destination does not come in
            // flipped around. This is the main problem with SDK sample, it does not
            // do this.
            if (interpolatedTime >= 0.5f) {
                degrees -= 180.f;

                if (!visibilitySwapped) {
                    setImageDrawable(toDrawable);
                    visibilitySwapped = true;
                }
            }

            if (forward) {
                degrees = -degrees;
            }

            final Matrix matrix = t.getMatrix();

            camera.save();
            camera.translate(0.0f, 0.0f, (float) (150.0 * Math.sin(radians)));
            camera.rotateX(mIsRotationXEnabled ? degrees : 0);
            camera.rotateY(mIsRotationYEnabled ? degrees : 0);
            camera.rotateZ(mIsRotationZEnabled ? degrees : 0);
            camera.getMatrix(matrix);
            camera.restore();

            matrix.preTranslate(-centerX, -centerY);
            matrix.postTranslate(centerX, centerY);
        }
    }
}


使用方法:
import android.app.Activity;
import android.os.Bundle;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnticipateOvershootInterpolator;
import android.view.animation.BounceInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;

import fr.castorflex.android.flipimageview.R;
import fr.castorflex.android.flipimageview.library.FlipImageView;

public class SampleActivity extends Activity implements FlipImageView.OnFlipListener,
        SeekBar.OnSeekBarChangeListener {

    private static final String[] fData = new String[]{
            "Decelerate",
            "Accelerate",
            "AccelerateDecelerate",
            "Bounce",
            "Overshoot",
            "AnticipateOvershoot"

    };

    private static final Interpolator[] fInterpolators = new Interpolator[]{
            new DecelerateInterpolator(),
            new AccelerateInterpolator(),
            new AccelerateDecelerateInterpolator(),
            new BounceInterpolator(),
            new OvershootInterpolator(),
            new AnticipateOvershootInterpolator()
    };

    private SeekBar mSeekBar;

    private Spinner mSpinner;

    private TextView mTextViewDuration;

    private FlipImageView mFlipImageView;

    private CheckBox mCheckBoxX;

    private CheckBox mCheckBoxY;

    private CheckBox mCheckBoxZ;

    private TextView mTextViewAnimationListener;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mTextViewAnimationListener = (TextView) findViewById(R.id.textview);
        mFlipImageView = (FlipImageView) findViewById(R.id.imageview);
        mSpinner = (Spinner) findViewById(R.id.spinner);
        mTextViewDuration = (TextView) findViewById(R.id.textview_duration);
        mSeekBar = (SeekBar) findViewById(R.id.seekbar);
        mCheckBoxX = (CheckBox) findViewById(R.id.checkedtextview_x);
        mCheckBoxY = (CheckBox) findViewById(R.id.checkedtextview_y);
        mCheckBoxZ = (CheckBox) findViewById(R.id.checkedtextview_z);

        mSpinner.setAdapter(
                new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, fData));

        mSeekBar.setOnSeekBarChangeListener(this);

        mFlipImageView.setOnFlipListener(this);
    }

    /////////////////////FLIP IMAGE VIEW///////////////////

    @Override
    public void onClick(boolean flipped) {
        mFlipImageView.setInterpolator(fInterpolators[mSpinner.getSelectedItemPosition()]);
        mFlipImageView.setDuration(mSeekBar.getProgress());
        mFlipImageView.setRotationXEnabled(mCheckBoxX.isChecked());
        mFlipImageView.setRotationYEnabled(mCheckBoxY.isChecked());
        mFlipImageView.setRotationZEnabled(mCheckBoxZ.isChecked());
    }

    @Override
    public void onFlipStart() {
        mTextViewAnimationListener.setText("OnFlipStart");
    }

    @Override
    public void onFlipEnd() {
        mTextViewAnimationListener.setText("OnFlipEnd");
    }

    ////////////////////////SEEK BAR/////////////////////////

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        mTextViewDuration.setText("" + progress);
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }
}

你可能感兴趣的:(imageview)