package com.dh.foundation.widget.afkimageview; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.ViewGroup; import android.widget.ImageView; /** * Created by Lee on 2015/9/21. */ public class AfkImageView extends ImageView { public enum AnimType { ALPHA_ANIM, CENTER_EXPAND, } /** * 记录切换动画类型 */ private AnimType mAnimType; /** * FPS */ private final int FPS = 50; /** * 每帧刷新间隔 */ private final int REFRESH_INTERVAL = 1000 / FPS; /** * 当 mBitmap 被赋值时,记录该时间, 暂时作为动画启动时间 * 由于当前没有设置延迟等功能,所以mBitmap被赋值时,将直接有过度动画效果 */ private long mAnimationStartTime; private long mAnimationNowTime; private long mAnimationRemainingTime; private Paint mPaint; private TransitionAnimation mTransitionAnimation; private Drawable mDrawable; /** * 用来记录动画是否结束 */ private boolean mAnimationFinish; /** * 存放图片 最原始的 宽高 */ private int mOldWidth, mOldHeight; /** * 初始图片 宽高 */ private int mFirstImageWidth, mFirstImageHeight; /** * 图片的 最终实际显示的宽高 */ private int mImageWidth, mImageHeight; /** * 控件的 最终宽高 */ private int mWidth, mHeight; /** * 是否播放动画的开关 */ private boolean mTransitionAnimatorEnable; /** * 动画时间、效果渐变时间 */ private int mDuration; public AfkImageView(Context context) { this(context, null); } public AfkImageView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { if (msg.what == 0) { invalidate(); } return false; } }); //===================================================================== //----------------------- override ---------------------------- //_____________________________________________________________________ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mDrawable == null) return; if (mImageWidth == 0 || mImageHeight == 0) { return; } if (mTransitionAnimation == null || mTransitionAnimatorEnable == false) { drawWithOutTransitionAnimation(canvas); } else { drawWithAnimation(canvas); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int width = 0; int height = 0; int ewidth = MeasureSpec.getSize(widthMeasureSpec); int eheight = MeasureSpec.getSize(heightMeasureSpec); width = resolveAdjustedSize(mFirstImageWidth,ewidth,widthMeasureSpec); height = resolveAdjustedSize(mFirstImageHeight,eheight,heightMeasureSpec); mWidth = width; mHeight = height; // mImageWidth = mFirstImageWidth; // mImageHeight = mFirstImageHeight; mImageWidth = setDrawableSize(mFirstImageWidth,mWidth,widthMeasureSpec); mImageHeight = setDrawableSize(mFirstImageHeight,mHeight,heightMeasureSpec); setDrawableSize(mDrawable); setMeasuredDimension(width, height); } //===================================================================== //----------------------- private ----------------------------- //_____________________________________________________________________ private void init() { mPaint = new Paint(); mAnimType = AnimType.ALPHA_ANIM; mFirstImageHeight = -1; mFirstImageWidth = -1; mDuration = 500; setTransitionAnimation(mAnimType); setTransitionAnimationEnable(true); } private void drawWithOutTransitionAnimation(Canvas canvas) { mDrawable.draw(canvas); } private void setDrawable(Drawable drawable) { if (drawable == null) return; mDrawable = drawable; mOldWidth = mDrawable.getIntrinsicWidth(); mOldHeight = mDrawable.getIntrinsicHeight(); if (mFirstImageWidth == -1 || mFirstImageWidth == -1) { if (mOldWidth != 0 && mOldHeight != 0) { mFirstImageWidth = mOldWidth; mFirstImageHeight = mOldHeight; } } setDrawableSize(mDrawable); mAnimationStartTime = System.currentTimeMillis(); if(mTransitionAnimation != null) { mTransitionAnimation.setImage(mDrawable); } invalidate(); } private void setTransitionAnimation(AnimType type) { switch (type) { case ALPHA_ANIM: setTransitionAnimation(new AlphaAnimation()); setDuration(500); break; case CENTER_EXPAND: setTransitionAnimation(new CenterExpandAnimation()); setDuration(500); break; } } private void setDrawableSize(Drawable drawable) { if (drawable == null) return; drawable.setBounds(0, 0, mImageWidth, mImageHeight); } private int setDrawableSize(int imageSize, int layoutSize,int measureSpec){ int specMode = MeasureSpec.getMode(measureSpec); int result = layoutSize; switch (specMode) { case MeasureSpec.AT_MOST: result = imageSize; break; case MeasureSpec.EXACTLY: result = layoutSize; break; } return result; } private int resolveAdjustedSize(int imageSize, int layoutSize, int measureSpec) { int result = layoutSize; int specMode = MeasureSpec.getMode(measureSpec); switch (specMode) { case MeasureSpec.UNSPECIFIED: if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT) result = imageSize; else if (getLayoutParams().height == ViewGroup.LayoutParams.MATCH_PARENT) result = layoutSize; break; case MeasureSpec.AT_MOST: result = imageSize; break; case MeasureSpec.EXACTLY: result = layoutSize; break; } return result; } private void drawWithAnimation(Canvas canvas) { countRemainingTime(); float progress; // if(mAnimationRemainingTime <= 0) // progress = 1; // else{ // double duration = mTransitionAnimation.duration(); // double retime = mAnimationRemainingTime; // progress = 1- retime / duration; // } // if(progress < 0) // progress = 0; float duration = mTransitionAnimation.duration(); float retime = mAnimationRemainingTime; progress = retime / duration; if (progress > 1) progress = 1; else if (progress < 0) progress = 0; mTransitionAnimation.changeProgress(progress); mAnimationFinish = mTransitionAnimation.draw(canvas); if (mAnimationFinish) { //animation is finish } else { delayedRefresh(REFRESH_INTERVAL); } } /** * 计算下一帧延迟刷新时间 */ private void countRemainingTime() { mAnimationNowTime = System.currentTimeMillis(); mAnimationRemainingTime = mTransitionAnimation.duration() - (mAnimationNowTime - mAnimationStartTime); } /** * 间隔一段时间,去执行刷新下一帧 * * @param delayedTime */ private void delayedRefresh(int delayedTime) { mHandler.sendEmptyMessageDelayed(0, delayedTime); } //===================================================================== //----------------------- public ----------------------------- //_____________________________________________________________________ /** * 与ImageView的功能一样 */ // public void setScaleType() { // // } @Override public void setImageBitmap(Bitmap bm) { // super.setImageBitmap(bm); setImage(bm); } @Override public void setImageResource(int resId) { // super.setImageResource(resId); setImage(resId); } @Override public void setImageDrawable(Drawable drawable) { // super.setImageDrawable(drawable); setImage(drawable); } public void setImage(int res) { Drawable drawable = getResources().getDrawable(res); setDrawable(drawable); } public void setImage(Bitmap bitmap) { Drawable drawable = new BitmapDrawable(getResources(), bitmap); setDrawable(drawable); } public void setImage(Drawable drawable) { setDrawable(drawable); } public void setTransitionAnimation(TransitionAnimation animation) { this.mTransitionAnimation = animation; } /** * 设置是否播放动画切换效果 * @param enable */ public void setTransitionAnimationEnable(boolean enable){ this.mTransitionAnimatorEnable = enable; setDuration(mDuration); } /** * 设置动画类型(使用foundation提供的切换效果) * 注:现在只提供了一种效果 * @param type */ public void setAnimType(AnimType type) { this.mAnimType = type; setTransitionAnimation(mAnimType); } /** * 设置渐变动画时间 * @param duration */ public void setDuration(int duration){ this.mDuration = duration; if(mTransitionAnimation != null) mTransitionAnimation.setDuration(duration); } }