Android TextView 仿动控件

2021-11-24 14:03:29 浏览数 (1)

看到一些应用中的点赞觉得挺有意思,具体效果大概就是这个样子

50buq-l34h1.gif

然后我仿写了下,效果差不多,代码比较简单就不过多说明了

代码语言:javascript复制
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

public class LikeView extends View {

    private static final String DEFAULT_TEXT_COLOR = "#cccccc";
    private static final int ANIM_TIME = 300;
    private int mCurrValue;
    // true 字符相同,false 不同
    private boolean[] mArrayStatus;
    private Paint mTextPaint;
    private int mTextSize;
    private int mTextOffY;
    private boolean mIsLike;
    private float mCurrOffsetY;
    private int mSingleTextWidth;

    public LikeView(Context context) {
        super(context);
        init(context);
    }

    public LikeView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

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

    private void init(Context context) {
        mTextSize = sp2px(context, 16f);
        mTextOffY = mTextSize / 2;
        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setColor(Color.parseColor(DEFAULT_TEXT_COLOR));
        mSingleTextWidth = measureWidth("9");
    }

    private int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale   0.5f);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = measureWidth(String.valueOf(mCurrValue))   getPaddingLeft()   getPaddingRight();
        int height = mTextSize   getPaddingTop()   getPaddingBottom();
        if (View.MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
            width = Math.max(width, MeasureSpec.getSize(widthMeasureSpec));
        }
        if (View.MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
            height = Math.max(width, MeasureSpec.getSize(heightMeasureSpec));
        }
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        String content = String.valueOf(mCurrValue);
        int offX = getPaddingLeft();
        int offY = getPaddingTop()   mTextSize;
        if (null == mArrayStatus || mArrayStatus.length != content.length()) {
            canvas.drawText(content, offX, offY, mTextPaint);
        } else {
            int currLeft = offX;
            int strLength = content.length() - 1;
            for (int i = 0, y = content.length(); i < y; i  ) {
                if (mArrayStatus[strLength]) {
                    canvas.drawText(String.valueOf(content.charAt(i)), currLeft, offY, mTextPaint);
                } else {
                    canvas.drawText(String.valueOf(content.charAt(i)), currLeft, offY   mCurrOffsetY, mTextPaint);
                }
                currLeft  = mSingleTextWidth;
                strLength--;
            }
        }
    }

    private int measureWidth(String content) {
        return (int) Math.ceil(mTextPaint.measureText(content));
    }

    public void setCurrValue(int currValue) {
        this.mCurrValue = currValue;
        requestLayout();
    }

    public void setLike() {
        setLike(!mIsLike);
    }

    public void setLike(boolean isLike) {
        setLike(isLike, 1);
    }

    public void setLike(boolean isLike, int value) {
        this.mIsLike = isLike;
        int lastValue = mCurrValue;
        if (isLike) {
            lastValue  = value;
        } else {
            lastValue -= value;
        }
        findDiff(String.valueOf(mCurrValue), String.valueOf(lastValue));
        mCurrValue = lastValue;
        startAnim();
    }

    private void findDiff(String currStr, String lastStr) {
        if (null == currStr || null == lastStr || currStr.equals(lastStr)) {
            return;
        }
        int currStrLength = currStr.length() - 1;
        int lastStrLength = lastStr.length() - 1;
        int maxLength = Math.max(currStr.length(), lastStr.length());
        mArrayStatus = new boolean[maxLength];
        for (int i = 0; i < maxLength; i  ) {
            if (currStrLength >= 0 && lastStrLength >= 0) {
                char c1 = currStr.charAt(currStrLength);
                char c2 = lastStr.charAt(lastStrLength);
                mArrayStatus[i] = c1 == c2;
                currStrLength--;
                lastStrLength--;
            } else {
                mArrayStatus[i] = false;
            }
        }
    }

    public void setTextOffY(float offsetY) {
        float value = mTextOffY * offsetY;
        this.mCurrOffsetY = mIsLike ? value : -value;
        invalidate();
    }

    private void startAnim() {
        @SuppressLint("ObjectAnimatorBinding") ObjectAnimator anim = ObjectAnimator.ofFloat(this, "textOffY"
                , 1, 0);
        anim.setDuration(ANIM_TIME);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                mArrayStatus = null;
                mCurrOffsetY = 0;
            }
        });
        anim.start();
    }

}
gif

0 人点赞