打赏

跳动的数字和金额、滑动的数字

复制代码
 
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
 
import com.shoneworn.supermvp.uitls.NumberUtils;
 
/**
 * Created by chenxiangxiang on 2019/5/16.
 *
 * @author shoneworn
 * @只支持单个文字的跳动,只想支持数字。
 */
 
public class SingleScrollNumberView extends View {
 
    private String mText = "";
    private int mTextColor = Color.BLACK;
    private int mTextSize = 48;
    private int textPadding = 6;
 
    private Paint mPaint;
    private Context mContext;
    private static String BASE_NUMBER = "0123456789";
 
    /**
     * 由于只想用一个view完事,但是文字绘制的时候,不带边距,只好在measure的时候,用大字体占个大位置。在onDraw的时候,用小字体。这样文字就自带了边距
     */
    private int textOutHeight;
    private int textOutWidth;
    private int textInnerWidth;
    private int scrollY = 0;
    private int scale = 2;
 
    public SingleScrollNumberView(Context context) {
        this(context, null);
    }
 
    public SingleScrollNumberView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }
 
    public SingleScrollNumberView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        initPaint();
    }
 
    private void initPaint() {
        mPaint = new Paint();
        //设置抗锯齿
        mPaint.setAntiAlias(true);
        //设置字体和颜色
        mPaint.setTextSize(mTextSize * scale);
        mPaint.setColor(mTextColor);
        setPadding(textPadding, textPadding, textPadding, textPadding);
    }
 
    public SingleScrollNumberView setText(String text) {
        this.mText = text;
        return this;
    }
 
    public SingleScrollNumberView setTextColor(int textColor) {
        this.mTextColor = textColor;
        mPaint.setColor(mTextColor);
        return this;
    }
 
    public SingleScrollNumberView setTextSize(int textSize) {
        this.mTextSize = textSize;
        mPaint.setTextSize(mTextSize * scale);
        return this;
    }
 
    public SingleScrollNumberView setTextPadding(int padding) {
        this.textPadding = padding;
        setPadding(textPadding, textPadding, textPadding, textPadding);
        return this;
    }
 
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
 
        if (widthMode == MeasureSpec.AT_MOST) {
            Rect bounds = new Rect();
            mPaint.getTextBounds(mText, 0, mText.length(), bounds);
            textOutWidth = bounds.width();
            width = bounds.width() + getPaddingLeft() + getPaddingRight();
 
        }
        if (heightMode == MeasureSpec.AT_MOST) {
            Rect bounds = new Rect();
            mPaint.getTextBounds(mText, 0, mText.length(), bounds);
            textOutHeight = bounds.height();
            height = textOutHeight + getPaddingTop() + getPaddingBottom();
        }
        //设置宽高
        setMeasuredDimension(width, height);
    }
 
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (TextUtils.isEmpty(mText)) return;
        if (mText.length() > 1) return;
        if (!BASE_NUMBER.contains(mText)) return;
 
        //保持垂直方向居中
        //getPaddingLeft() + (textOutWidth - textInnerWidth) / 2 保持水平方向居中
        mPaint.setTextSize(mTextSize);
        Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
        int dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
        int baseLine = getHeight() / 2 + dy;
 
        for (int i = 0; i <= NumberUtils.toInt(mText); i++) {
            mPaint.setTextSize(mTextSize);
            Rect innerBounds = new Rect();
            mPaint.getTextBounds(mText, 0, mText.length(), innerBounds);
            textInnerWidth = innerBounds.width();
            canvas.drawText(String.valueOf(i), getPaddingLeft() + (textOutWidth - textInnerWidth) / 2, baseLine + i * textOutHeight - scrollY, mPaint);
        }
    }
 
 
    private void animateView() {
        this.postDelayed(new Runnable() {
            @Override
            public void run() {
                //最大数字出现后,就要停下来。还要停稳,不然多几个数字,就会出现高低不平了。
                if (scrollY >= textOutHeight * NumberUtils.toInt(mText)) {
                    scrollY = textOutHeight * NumberUtils.toInt(mText);
                    SingleScrollNumberView.this.postInvalidate();
                    return;
                }
                scrollY += textOutHeight / 4;
                SingleScrollNumberView.this.postInvalidate();
                animateView();
 
            }
        }, 8);
    }
 
    public void start() {
        scrollY = 0;
        animateView();
    }
 
 
}
复制代码
复制代码
public class DanceNumberView extends LinearLayout {
 
    private String text;
    private int textColor;
    private int textSize;
    private float textPadding;  //文字间距
 
    private List<SingleScrollNumberView> list = new ArrayList<>();
 
 
    public DanceNumberView(Context context) {
        this(context, null);
    }
 
    public DanceNumberView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }
 
    public DanceNumberView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.scrollNumber);
        initAttributesData(typedArray);
        this.setOrientation(HORIZONTAL);
        this.setGravity(Gravity.CENTER);
    }
 
    public void createView() {
        if (TextUtils.isEmpty(text)) return;
        char[] chars = String.valueOf(NumberUtils.toInt(text)).toCharArray();
        for (int i = 0; i < chars.length; i++) {
            SingleScrollNumberView scrollNumber = new SingleScrollNumberView(getContext());
            scrollNumber.setTextColor(textColor);
            scrollNumber.setTextSize(textSize);
            scrollNumber.setText(String.valueOf(chars[i]));
            addView(scrollNumber);
            list.add(scrollNumber);
        }
    }
 
    public void start() {
        if (Utils.isEmpty(list)) return;
        for (SingleScrollNumberView view : list) {
            view.start();
        }
    }
 
    private void initAttributesData(TypedArray typedArray) {
        textColor = typedArray.getColor(R.styleable.scrollNumber_textColor, Color.BLACK);
        textSize = (int) typedArray.getDimension(R.styleable.scrollNumber_textSize, 16);
        text = typedArray.getString(R.styleable.scrollNumber_text);
        textPadding = typedArray.getDimension(R.styleable.scrollNumber_textPadding, 5);
 
    }
 
 
}
复制代码

新建资源scroll_number_attrs.xml

复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="scrollNumber">
        <attr name="text" format="string" />
        <attr name="textSize" format="dimension" />
        <attr name="textColor" format="color" />
        <attr name="textPadding" format="dimension" />
    </declare-styleable>
</resources>
复制代码

使用

复制代码
<com.shoneworn.supermvp.common.widget.DanceNumberView
        android:id="@+id/dnView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#666666"
        app:text="33891856"
        app:textColor="#ffffff"
        app:textPadding="2dp"
        app:textSize="16sp" />
复制代码

  dnView.createView();
  dnView.start();

posted @   YY2000  阅读(260)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示