IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Android 步数表盘自定义view -> 正文阅读

[游戏开发]Android 步数表盘自定义view

package com.walking.strong.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import com.money.common.ComponentContext;
import com.money.common.log.DLog;
import com.money.statistics.StatisticsUtils;
import com.walking.strong.R;
import com.walking.strong.bean.WalkStepTipsBean;
import com.walking.strong.bean.response.ConfigResponse;
import com.walking.strong.constant.StatisticConstants;
import com.walking.strong.mvp.model.IUserInfoModel;
import com.walking.strong.utils.GoldUtils;

import org.jetbrains.annotations.NotNull;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class DashboardPointView extends View {
    private int mRadius; // 扇形半径
    private int mStartAngle = 150; // 起始角度
    private int mSweepAngle = 240; // 绘制角度
    private int mMin = 0; // 最小值
    private int mMax = 6000; // 最大值
    private int mSection = 4; // 值域(mMax-mMin)等分份数
    private double mPortion = 15; // 一个mSection等分份数
    private String mHeaderText = "今日步数"; // 表头
    private String mTips = "";
    private int mStrokeWidth; // 画笔宽度
    private int mLength1; // 长刻度的相对圆弧的长度
    private int mLength2; // 刻度读数顶部的相对圆弧的长度
    private int mStepCount = 1500;  //步数
    private int goldCoin = 0;

    private int mStepRecord;
    private boolean mRefreshText = true;

    private int mPadding;
    private float mCenterX, mCenterY; // 圆心坐标
    private Paint mPaint;   //刻度画笔
    private Paint mTextPaint;  //刻度文字画笔
    private Paint mProgressPaint;  //进度画笔
    private Rect mRectText;
    private String[] mTexts;
    private ValueAnimator mValueAnimator;

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

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

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

    private void init() {
        mStrokeWidth = dp2px(3);
        mLength1 = dp2px(13) + mStrokeWidth;
        mLength2 = mLength1 + dp2px(4);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mStrokeWidth);
        mPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_FFC801));

        mProgressPaint = new Paint();
        mProgressPaint.setAntiAlias(true);
        mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
        mProgressPaint.setStyle(Paint.Style.STROKE);
        mProgressPaint.setStrokeWidth(mStrokeWidth);
        mProgressPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_progress));

        mTextPaint = new Paint();
        mProgressPaint.setAntiAlias(true);
        mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
        mProgressPaint.setStrokeWidth(mStrokeWidth);
        mTextPaint.setTextSize(sp2px(12));
        mTextPaint.setStyle(Paint.Style.FILL);
        mTextPaint.setColor(ContextCompat.getColor(getContext(), R.color.scale_text_color));
        Typeface dincond_bold = Typeface.createFromAsset(ComponentContext.getContext().getAssets(), "fonts/DINCond-Bold.otf");
        mTextPaint.setTypeface(dincond_bold);

        mRectText = new Rect();

        mTexts = new String[mSection + 1]; // 需要显示mSection + 1个刻度读数
        for (int i = 0; i < mTexts.length; i++) {
            if (i == 0) {
                mTexts[i] = "1";
            } else {
                int n = (mMax - mMin) / mSection;
                mTexts[i] = String.valueOf(mMin + i * n);
            }
        }
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mPadding = Math.max(
                Math.max(getPaddingLeft(), getPaddingTop()),
                Math.max(getPaddingRight(), getPaddingBottom())
        );
        setPadding(mPadding, mPadding, mPadding, mPadding);
        int width = resolveSize(dp2px(245), widthMeasureSpec);
        mRadius = (width - mPadding * 2 - mStrokeWidth * 2) / 2;
        setMeasuredDimension(width, width - dp2px(50));
        mCenterX = mCenterY = getMeasuredWidth() / 2f;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //背景设置透明颜色
        canvas.drawColor(ContextCompat.getColor(getContext(), R.color.transparent));
        drawScale(canvas);  //画刻度
        drawScaleProgress(canvas);  //画进度条
        //drawLongScaleText(canvas);  //关键刻度度数
        drawHeadText(canvas);  //我的步数
        drawStepCount(canvas);  //具体步数
    }


    /**
     * 画刻度
     * 同样采用canvas的旋转原理
     */
    private void drawScale(Canvas canvas) {
        canvas.save();
        mPaint.setStrokeWidth(mStrokeWidth);
        mPaint.setColor(ContextCompat.getColor(getContext(), R.color.dashboard_scale_gray));
        double cos = Math.cos(Math.toRadians(mStartAngle - 180));
        double sin = Math.sin(Math.toRadians(mStartAngle - 180));
        float x0 = (float) (mPadding + mStrokeWidth + mLength1 / 3 + (mRadius - mLength1 / 3) * (1 - cos));
        float y0 = (float) (mPadding + mStrokeWidth + mLength1 / 3 + (mRadius - mLength1 / 3) * (1 - sin));
        float x2 = (float) (mPadding + mStrokeWidth + mRadius - (mRadius - mLength1) * cos);
        float y2 = (float) (mPadding + mStrokeWidth + mRadius - (mRadius - mLength1) * sin);

        float lx0 = (float) (mPadding + mStrokeWidth + mRadius * (1 - cos));
        float ly0 = (float) (mPadding + mStrokeWidth + mRadius * (1 - sin));
        float lx1 = (float) (mPadding + mStrokeWidth + mRadius - (mRadius - mLength1) * cos);
        float ly1 = (float) (mPadding + mStrokeWidth + mRadius - (mRadius - mLength1) * sin);

        float angle = (float) (mSweepAngle * 1f / (mSection * mPortion));

        for (int i = 0; i <= mSection * mPortion; i++) {
            if (i % mPortion == 0) { // 避免与长刻度画重合
                mPaint.setStrokeWidth(mStrokeWidth);
                canvas.drawLine(lx0, ly0, lx1, ly1, mPaint);
            } else {
                canvas.drawLine(x0, y0, x2, y2, mPaint);
            }
            canvas.rotate(angle, mCenterX, mCenterY);
        }
        canvas.restore();
    }

    /**
     * 画进度刻度
     *
     * @param canvas
     */
    private void drawScaleProgress(Canvas canvas) {
        canvas.save();
        mProgressPaint.setStrokeWidth(mStrokeWidth);
        double cos = Math.cos(Math.toRadians(mStartAngle - 180));
        double sin = Math.sin(Math.toRadians(mStartAngle - 180));
        float x0 = (float) (mPadding + mStrokeWidth + mLength1 / 3 + (mRadius - mLength1 / 3) * (1 - cos));
        float y0 = (float) (mPadding + mStrokeWidth + mLength1 / 3 + (mRadius - mLength1 / 3) * (1 - sin));
        float x2 = (float) (mPadding + mStrokeWidth + mRadius - (mRadius - mLength1) * cos);
        float y2 = (float) (mPadding + mStrokeWidth + mRadius - (mRadius - mLength1) * sin);

        float lx0 = (float) (mPadding + mStrokeWidth + mRadius * (1 - cos));
        float ly0 = (float) (mPadding + mStrokeWidth + mRadius * (1 - sin));
        float lx1 = (float) (mPadding + mStrokeWidth + mRadius - (mRadius - mLength1) * cos);
        float ly1 = (float) (mPadding + mStrokeWidth + mRadius - (mRadius - mLength1) * sin);

        if (mStepCount > 0) {
            canvas.drawLine(lx0, ly0, lx1, ly1, mProgressPaint);
        }
        float angle = (float) (mSweepAngle * 1f / (mSection * mPortion));
        for (int i = 0; i <= getProgressCell(); i++) {
            if (i % mPortion == 0) { // 避免与长刻度画重合
                mProgressPaint.setStrokeWidth(mStrokeWidth);
                canvas.drawLine(lx0, ly0, lx1, ly1, mProgressPaint);
            } else {
                canvas.drawLine(x0, y0, x2, y2, mProgressPaint);
            }
            canvas.rotate(angle, mCenterX, mCenterY);
        }
        canvas.restore();
    }

    /**
     * 我的步数
     */
    private void drawHeadText(Canvas canvas) {
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setColor(ContextCompat.getColor(getContext(), R.color.dashboard_text_black1));
        mPaint.setTextSize(sp2px(12));
        mPaint.setTypeface(null);
        canvas.drawText(mHeaderText, mCenterX, mCenterY - dp2px(55), mPaint);
    }

    /**
     * 具体步数
     *
     * @param canvas
     */
    private void drawStepCount(Canvas canvas) {
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setTextSize(sp2px(48));
        mPaint.setColor(ContextCompat.getColor(getContext(), R.color.dashboard_text_black2));
        Typeface dincond_black = Typeface.createFromAsset(ComponentContext.getContext().getAssets(), "fonts/DINCond-Black.otf");
        mPaint.setTypeface(dincond_black);
        mPaint.setTextSize(sp2px(48));
        canvas.drawText(String.valueOf(mStepCount), mCenterX, mCenterY - dp2px(7), mPaint);
    }


    /**
     * 画刻度读数
     *
     * @param canvas
     */
    private void drawLongScaleText(Canvas canvas) {
        float α;
        float[] p;
        float angle = mSweepAngle * 1f / mSection;
        for (int i = 0; i <= mSection; i++) {
            α = mStartAngle + angle * i;
            p = getCoordinatePoint(mRadius - mLength2, α);
            if (α % 360 > 135 && α % 360 < 225) {
                mTextPaint.setTextAlign(Paint.Align.LEFT);
            } else if ((α % 360 >= 0 && α % 360 < 45) || (α % 360 > 315 && α % 360 <= 360)) {
                mTextPaint.setTextAlign(Paint.Align.RIGHT);
            } else {
                mTextPaint.setTextAlign(Paint.Align.CENTER);
            }
            mTextPaint.getTextBounds(mHeaderText, 0, mTexts[i].length(), mRectText);
            int txtH = mRectText.height();
            if (i <= 1 || i >= mSection - 1) {
                canvas.drawText(mTexts[i], p[0], p[1] + txtH / 2, mTextPaint);
            } else if (i == 3) {
                canvas.drawText(mTexts[i], p[0] + txtH / 2, p[1] + txtH, mTextPaint);
            } else if (i == mSection - 3) {
                canvas.drawText(mTexts[i], p[0] - txtH / 2, p[1] + txtH, mTextPaint);
            } else {
                canvas.drawText(mTexts[i], p[0], p[1] + txtH + dp2px(3), mTextPaint);
            }
        }
    }


    private int getProgressCell() {
        if (mStepCount <= mMin) {
            return 0;
        } else if (mStepCount > 0 && mStepCount <= mMax) {
            double v = mMax / mSection / mPortion;
            return (int) Math.floor(mStepCount / v);
        } else {
            return (int) (mSection * mPortion);
        }
    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                Resources.getSystem().getDisplayMetrics());
    }

    private int sp2px(int sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, sp,
                Resources.getSystem().getDisplayMetrics());
    }

    public float[] getCoordinatePoint(int radius, float angle) {
        float[] point = new float[2];
        double arcAngle = Math.toRadians(angle); //将角度转换为弧度
        if (angle < 90) {
            point[0] = (float) (mCenterX + Math.cos(arcAngle) * radius);
            point[1] = (float) (mCenterY + Math.sin(arcAngle) * radius);
        } else if (angle == 90) {
            point[0] = mCenterX;
            point[1] = mCenterY + radius;
        } else if (angle > 90 && angle < 180) {
            arcAngle = Math.PI * (180 - angle) / 180.0;
            point[0] = (float) (mCenterX - Math.cos(arcAngle) * radius);
            point[1] = (float) (mCenterY + Math.sin(arcAngle) * radius);
        } else if (angle == 180) {
            point[0] = mCenterX - radius;
            point[1] = mCenterY;
        } else if (angle > 180 && angle < 270) {
            arcAngle = Math.PI * (angle - 180) / 180.0;
            point[0] = (float) (mCenterX - Math.cos(arcAngle) * radius);
            point[1] = (float) (mCenterY - Math.sin(arcAngle) * radius);
        } else if (angle == 270) {
            point[0] = mCenterX;
            point[1] = mCenterY - radius;
        } else {
            arcAngle = Math.PI * (360 - angle) / 180.0;
            point[0] = (float) (mCenterX + Math.cos(arcAngle) * radius);
            point[1] = (float) (mCenterY - Math.sin(arcAngle) * radius);
        }
        return point;
    }

    public int getStepCount() {
        return mStepCount;
    }

    public void setStepCount(int stepCount, boolean b) {
        mStepCount = stepCount;
        if (mStepCount < 0) {
            StatisticsUtils.statisicsGrowing(StatisticConstants.EVENT_STEPCOUNTERROR, StatisticConstants.KEY_STEPCOUNT, String.valueOf(mStepCount));
        }
        mRefreshText = b;
        postInvalidate();
    }

    public int getGoldCoin() {
        return goldCoin;
    }

    /**
     * 刷新展示刻度动画
     */
    public void refreshScale(int currentCount) {
        mStepRecord = currentCount;
        ValueAnimator valueAnimator = this.mValueAnimator;
        if (valueAnimator == null) {
            mValueAnimator = new ValueAnimator();
            mValueAnimator.setDuration(2000);
            mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    int intValue = ((Integer) animation.getAnimatedValue()).intValue();
                    setStepCount(intValue, false);
                }
            });

        } else {
            mValueAnimator.cancel();
        }
        mValueAnimator.setIntValues(new int[]{0, mMax, currentCount});
        mValueAnimator.start();
    }

}

<color name="dashboard_scale_gray">#6A6868</color>
    <color name="dashboard_text_black1">#333333</color>
    <color name="dashboard_text_black2">#000000</color>
  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:59:49  更:2022-03-30 19:00:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:40:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码