FruitLoadView 一个自定义view可用来做加载view

闲暇时自己做得一个自定义view,后续如果还有时间的话再去增强功能。

Github地址:https://github.com/X-FAN/FruitLoadView 欢迎star

效果图
博客上的图片文件不能太大,github效果图要清晰些,大家将就下
这里写图片描述

2016.8.5:
新增fruitDrawableArray属性,可以在跳动中变换
这里写图片描述

源码还是比较简单的

public class FruitLoadView extends View {
    private final String TAG = "Fruit";
    private int mWidth;
    private int mHeight;
    private int mOvalW;
    private int mOvalH;
    private int mStartHeight;
    private int mFruitHeight;
    private int mFruitWidth;
    private int mIndex = 1;
    private int mLength;
    private boolean mIsDraw = false;
    private boolean mIsMutliMode = false;
    private boolean mIsHasChanged = false;//是否已经变换过在达到最高前
    private float mMinScale;
    private float mAnimatedValue = 1.0f;
    private List<Drawable> mFruitDrawables;

    private Drawable mFruitDrawable;
    private ValueAnimator mScaleLargerAnimator;
    private Paint mPaint;
    private RectF mOvalRectF;


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


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

    public FruitLoadView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }


    private void init(Context context, AttributeSet attrs) {
        if (attrs == null) {
            return;
        }
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FruitLoadView);
        handleMultiDrawable(a);
        if (!mIsMutliMode) {
            mFruitDrawable = a.getDrawable(R.styleable.FruitLoadView_fruitDrawable);
            if (mFruitDrawable == null) {
                throw new NullPointerException("fruit drawable is null");
            }
        }
        int shadowColor = a.getColor(R.styleable.FruitLoadView_shadowColor, 0xFFE6E6E6);
        int animatorDuration = a.getInt(R.styleable.FruitLoadView_animatorDuration, 1000);
        int maxHeight = a.getDimensionPixelSize(R.styleable.FruitLoadView_maxHeight, 100);
        int fruitHeight = a.getDimensionPixelSize(R.styleable.FruitLoadView_fruitHeight, -1);
        int fruitWidth = a.getDimensionPixelSize(R.styleable.FruitLoadView_fruitWidth, -1);
        if (fruitHeight > 0) {
            mFruitHeight = fruitHeight;
        } else {
            mFruitHeight = mFruitDrawable.getIntrinsicHeight();
        }
        if (fruitWidth > 0) {
            mFruitWidth = fruitWidth;
        } else {
            mFruitWidth = mFruitDrawable.getIntrinsicWidth();
        }
        mOvalW = mFruitWidth / 2;
        mOvalH = (int) (mFruitHeight * 0.5) / 2;
        mStartHeight = mFruitHeight + maxHeight;
        mMinScale = (float) mFruitHeight / (float) mStartHeight;
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(shadowColor);
        mOvalRectF = new RectF();
        initAnimator(animatorDuration);
        a.recycle();
    }

    /**
     * 处理多个drawable的情况
     *
     * @param a
     */
    private void handleMultiDrawable(TypedArray a) {
        int resId = a.getResourceId(R.styleable.FruitLoadView_fruitDrawableArray, -1);
        if (resId != -1) {
            Resources resources = getResources();
            TypedArray typedArray = resources.obtainTypedArray(resId);
            mFruitDrawables = new ArrayList<>();
            for (int i = 0; i < typedArray.length(); i++) {
                Drawable drawable = typedArray.getDrawable(i);
                mFruitDrawables.add(drawable);
            }
            if (!mFruitDrawables.isEmpty()) {
                mIsMutliMode = true;
                mFruitDrawable = mFruitDrawables.get(0);
                mLength = mFruitDrawables.size();
            }
            typedArray.recycle();
        }
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mIsDraw) {
            canvas.translate(mWidth / 2, mHeight / 2);// 将画布坐标原点移动到中心位置
            canvas.save();
            canvas.drawOval(mOvalRectF, mPaint);
            mFruitDrawable.setBounds(-mOvalW, (int) (-mStartHeight * mAnimatedValue), mOvalW, (int) (-(mStartHeight * mAnimatedValue - mFruitHeight)));
            mFruitDrawable.draw(canvas);
            canvas.restore();
        }

    }


    private void initAnimator(long duration) {
        mScaleLargerAnimator = ValueAnimator.ofFloat(1.0f, mMinScale, 1.0f).setDuration(duration);
        mScaleLargerAnimator.setInterpolator(new DecelerateInterpolator());
        mScaleLargerAnimator.setRepeatCount(ValueAnimator.INFINITE);
        mScaleLargerAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mAnimatedValue = (float) animation.getAnimatedValue();
                if (mAnimatedValue > 0.9f) {//认为达到最高点
                    mIsHasChanged = false;
                }
                mOvalRectF.set(-mOvalW * mAnimatedValue, -mOvalH * mAnimatedValue, mOvalW * mAnimatedValue, mOvalH * mAnimatedValue);
                changeDrawable();
                invalidate();
            }
        });
        mScaleLargerAnimator.start();
    }

    /**
     * 变更需要绘制的drawable
     */
    private void changeDrawable() {
        //差值小于0.05f即认为在最低点
        if (mIsMutliMode && !mIsHasChanged && (mAnimatedValue - mMinScale) < 0.05f) {
            mFruitDrawable = mFruitDrawables.get(mIndex);
            if (mIndex < mLength - 1) {
                mIndex++;
            } else {
                mIndex = 0;
            }
            mIsHasChanged = true;
        }
    }


    /**
     * 是否正在展示
     *
     * @return
     */
    public boolean isShowing() {
        return mIsDraw;
    }

    /**
     * 展示
     */
    public void showLoading() {
        mIsDraw = true;
        mScaleLargerAnimator.start();
    }

    /**
     * 消失
     */
    public void hideLoading() {
        mIsDraw = false;
        mScaleLargerAnimator.cancel();
        mScaleLargerAnimator.end();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值