kka

package com.example.myapplication;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import androidx.annotation.Nullable;

public class ModeSwitcher extends View {
private int mSelectedItemWidth;
private int mSelectedItemHeight;
private int mSelectedToNormalMargin;

private int mNormalItemRadius;
private int mNormalToNormalMargin;

private int mItemBgColor;
private Paint mPaint;

private Bitmap[] mItemIcons;
private int mTargetSelPosition;
private int mLastSelPosition;

private OnItemChangeListener mItemChangeListener;

private ValueAnimator mSwitchAnim;
private final AnimatorListenerAdapter mAnimatorListenerAdapter = new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        mLastSelPosition = mTargetSelPosition;
        invalidate();
        if (mItemChangeListener != null) {
            mItemChangeListener.afterItemChange(mLastSelPosition, mTargetSelPosition);
        }
    }

    @Override
    public void onAnimationStart(Animator animation) {
        if (mItemChangeListener != null) {
            mItemChangeListener.beforeItemChange(mLastSelPosition, mTargetSelPosition);
        }
    }
};

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

public ModeSwitcher(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
}

public ModeSwitcher(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
}

private void init() {
    Resources resources = getResources();
    mSelectedItemWidth = resources.getDimensionPixelSize(R.dimen.mode_switch_sel_item_w);
    mSelectedItemHeight = resources.getDimensionPixelSize(R.dimen.mode_switch_sel_item_h);
    mSelectedToNormalMargin = resources.getDimensionPixelSize(R.dimen.mode_switch_sel_to_normal_margin);

    mNormalItemRadius = resources.getDimensionPixelSize(R.dimen.mode_switch_normal_item_r);
    mNormalToNormalMargin = resources.getDimensionPixelSize(R.dimen.mode_switch_normal_to_normal_margin);

    mItemBgColor = resources.getColor(R.color.mode_switcher_item_bg);

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);

    mSwitchAnim = ValueAnimator.ofFloat(0, 1);
    mSwitchAnim.setInterpolator(new LinearInterpolator());
    mSwitchAnim.setDuration(200);
    mSwitchAnim.addUpdateListener(animation -> invalidate());
    mSwitchAnim.addListener(mAnimatorListenerAdapter);
    mTargetSelPosition = 0;
    mLastSelPosition = mTargetSelPosition;
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (checkItemsIfEmpty()) {
        return;
    }
    final int count = mItemIcons.length;
    for (int i = 0; i < count; i++) {
        drawItems(canvas, i);
    }
}


private void drawItems(Canvas canvas, int position) {
    final float halfW = getWidth() / 2f;
    final float halfH = getHeight() / 2f;
    final float cx = getPaddingLeft() + (getWidth() - getPaddingLeft() - getPaddingRight()) / 2f;
    final float cy = getPaddingTop() + (getHeight() - getPaddingTop() - getPaddingBottom()) / 2f;
    final Bitmap itemIcon = mItemIcons[position];

    float itemCx;
    int alpha;
    boolean isNextMode = mTargetSelPosition > mLastSelPosition;
    int positionOffset = position - mTargetSelPosition;
    float fraction = mSwitchAnim.isStarted() ? mSwitchAnim.getAnimatedFraction() : 1;
    float halfBgWidth;
    float halfBgHeight;
    if (positionOffset < 0) {
        if (!isNextMode) {
            itemCx = cx - mSelectedItemWidth / 2f - mSelectedToNormalMargin - mNormalItemRadius
                    - ((Math.abs(positionOffset) - 1) * (mNormalItemRadius * 2 + mNormalToNormalMargin))
                    - (mNormalItemRadius * 2 + mNormalToNormalMargin) * (1 - fraction);
            halfBgWidth = mNormalItemRadius;
            halfBgHeight = mNormalItemRadius;
            alpha = 0;
        } else {
            if (position == mLastSelPosition) {
                itemCx = cx - (mSelectedItemWidth / 2f + mSelectedToNormalMargin + mNormalItemRadius) * fraction;
                halfBgWidth = mNormalItemRadius + (mSelectedItemWidth / 2f - mNormalItemRadius) * (1 - fraction);
                halfBgHeight = mNormalItemRadius + (mSelectedItemHeight / 2f - mNormalItemRadius) * (1 - fraction);
                alpha = (int) (255 * (1 - fraction));
            } else {
                itemCx = cx - mSelectedItemWidth / 2f - mSelectedToNormalMargin - mNormalItemRadius
                        - ((Math.abs(positionOffset) - 1) * (mNormalItemRadius * 2 + mNormalToNormalMargin))
                        + (mNormalItemRadius * 2 + mNormalToNormalMargin) * (1 - fraction);
                halfBgWidth = mNormalItemRadius;
                halfBgHeight = mNormalItemRadius;
                alpha = 0;
            }
        }

    } else if (positionOffset > 0) {
        if (isNextMode) {
            itemCx = cx + mSelectedItemWidth / 2f + mSelectedToNormalMargin + mNormalItemRadius
                    + ((Math.abs(positionOffset) - 1) * (mNormalItemRadius * 2 + mNormalToNormalMargin))
                    + (mNormalItemRadius * 2 + mNormalToNormalMargin) * (1 - fraction);
            halfBgWidth = mNormalItemRadius;
            halfBgHeight = mNormalItemRadius;
            alpha = 0;
        } else {
            if (position == mLastSelPosition) {
                itemCx = cx + (mSelectedItemWidth / 2f + mSelectedToNormalMargin + mNormalItemRadius) * fraction;
                halfBgWidth = mNormalItemRadius + (mSelectedItemWidth / 2f - mNormalItemRadius) * (1 - fraction);
                halfBgHeight = mNormalItemRadius + (mSelectedItemHeight / 2f - mNormalItemRadius) * (1 - fraction);
                alpha = (int) (255 * (1 - fraction));
            } else {
                itemCx = cx + mSelectedItemWidth / 2f + mSelectedToNormalMargin + mNormalItemRadius
                        + ((Math.abs(positionOffset) - 1) * (mNormalItemRadius * 2 + mNormalToNormalMargin))
                        - (mNormalItemRadius * 2 + mNormalToNormalMargin) * (1 - fraction);
                halfBgWidth = mNormalItemRadius;
                halfBgHeight = mNormalItemRadius;
                alpha = 0;
            }
        }
    } else {
        float cxOffset = (mSelectedItemWidth / 2f + mSelectedToNormalMargin + mNormalItemRadius) * (1 - fraction);
        if (isNextMode) {
            itemCx = cx + cxOffset;
        } else {
            itemCx = cx - cxOffset;
        }
        halfBgWidth = mNormalItemRadius + (mSelectedItemWidth / 2f - mNormalItemRadius) * fraction;
        halfBgHeight = mNormalItemRadius + (mSelectedItemHeight / 2f - mNormalItemRadius) * fraction;
        alpha = (int) (255 * fraction);
    }
    canvas.save();
    canvas.translate(itemCx, cy);

    // 1.draw item background
    mPaint.setColor(mItemBgColor);
    canvas.drawRoundRect(-halfBgWidth, -halfBgHeight, halfBgWidth, halfBgHeight, halfBgHeight, halfBgHeight, mPaint);

    // 2.draw item icon
    int layerId = canvas.saveLayerAlpha(-halfW, -halfH, halfW, halfH, alpha);
    float scale = Math.min(halfBgWidth * 2f / mSelectedItemWidth, halfBgHeight * 2f / mSelectedItemHeight);
    canvas.scale(scale, scale);
    mPaint.setColor(Color.WHITE);
    canvas.drawBitmap(itemIcon, -itemIcon.getWidth() / 2f, -itemIcon.getHeight() / 2f, mPaint);
    canvas.restoreToCount(layerId);

    canvas.restore();
}

private boolean checkItemsIfEmpty() {
    return mItemIcons == null || mItemIcons.length == 0;
}

private Bitmap drawableToBitmap(Drawable drawable) {
    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable) drawable).getBitmap();
    }
    Bitmap bm = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bm);
    drawable.setBounds(0, 0, bm.getWidth(), bm.getHeight());
    drawable.draw(canvas);
    return bm;
}

public void setSelectedPosition(int selPosition, boolean isAnimate) {
    if (checkItemsIfEmpty()) {
        return;
    }
    if (mTargetSelPosition != selPosition && selPosition >= 0 && selPosition < mItemIcons.length) {
        if (mSwitchAnim.isStarted()) {
            mSwitchAnim.removeAllListeners();
            mSwitchAnim.cancel();
            mSwitchAnim.addListener(mAnimatorListenerAdapter);
        }
        mTargetSelPosition = selPosition;
        if (isAnimate) {
            mSwitchAnim.start();
        } else {
            mLastSelPosition = mTargetSelPosition;
            if (mItemChangeListener != null) {
                mItemChangeListener.beforeItemChange(mLastSelPosition, mTargetSelPosition);
                mItemChangeListener.afterItemChange(mLastSelPosition, mTargetSelPosition);
            }
        }
        invalidate();
    }
}

public void setItemIcons(int... itemIconIds) {
    if (mSwitchAnim.isStarted()) {
        mSwitchAnim.removeAllListeners();
        mSwitchAnim.cancel();
        mSwitchAnim.addListener(mAnimatorListenerAdapter);
    }
    mTargetSelPosition = 0;
    mLastSelPosition = mTargetSelPosition;
    if (itemIconIds == null) {
        mItemIcons = null;
        invalidate();
        return;
    }
    mItemIcons = new Bitmap[itemIconIds.length];
    int count = mItemIcons.length;
    for (int i = 0; i < count; i++) {
        mItemIcons[i] = drawableToBitmap(getResources().getDrawable(itemIconIds[i]));
    }
    invalidate();
    if (mItemChangeListener != null) {
        mItemChangeListener.beforeItemChange(mLastSelPosition, mTargetSelPosition);
        mItemChangeListener.afterItemChange(mLastSelPosition, mTargetSelPosition);
    }
}

public boolean isModeSwitching() {
    return mSwitchAnim.isStarted();
}

public int getSelectedPosition() {
    return mTargetSelPosition;
}

public void setOnItemChangeListener(OnItemChangeListener listener) {
    mItemChangeListener = listener;
}

public interface OnItemChangeListener {
    void beforeItemChange(int lastSelPosition, int currentSelPosition);

    void afterItemChange(int lastSelPosition, int currentSelPosition);
}

}
/* 计算得到图片的高度 /
/
这里需要主意,如果你需要更高的精度来保证图片不变形的话,需要自己进行一下数学运算 /
int height = options.outHeight * 200 / options.outWidth;
options.outWidth = 200;
options.outHeight = height;
/
这样才能真正的返回一个Bitmap给你 */
options.inJustDecodeBounds = false;
Bitmap bmp = BitmapFactory.decodeFile(path, options);
image.setImageBitmap(bmp);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值