自定义view-实现计步器的效果

news/2024/7/5 3:46:55

首先看下效果图

这里写图片描述

在做这个项目之前先了解下文字获取
我之前也写过一篇文章是自定义view——自定义圆环进度条:http://blog.csdn.net/qq_24675479/article/details/78880078

这里写图片描述

今天详细讲解一下baseLine 基线(参考文章:文淑大神的自定义View之绘图篇(四)http://blog.csdn.net/u012551350/article/details/51361778)
FontMetrics

这里写图片描述

top:可绘制的最高高度所在线
bottom:可绘制的最低高度所在线
ascent :系统建议的,绘制单个字符时,字符应当的最高高度所在线
descent:系统建议的,绘制单个字符时,字符应当的最低高度所在线

获取实例

Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
Paint.FontMetricsInt fm=  mPaint.getFontMetricsInt();

成员变量

        float ascent = fontMetrics.ascent;
        float descent = fontMetrics.descent;
        float top = fontMetrics.top;
        float bottom = fontMetrics.bottom;
        float leading = fontMetrics.leading;

这里的ascent,descent,top,bottom,leading指的是到基线baseline的位置

这里写图片描述

文字的高度

         float top = fontMetrics.top + baseLineY;
        float bottom = fontMetrics.bottom + baseLineY;
        //文字高度
        float height= bottom - top; //注意top为负数
        //文字中点y坐标
        float center = (bottom - top) / 2;

即中线是(bottom-top)/2,实际呢是bottom+top只是因为这里的top是负的(图片上的top到baseline的距离)

已知中线求baseline
这里写图片描述
结论
baseline=centerY+A-fm.bottom;

centerY呢实际就是getHeight/2,整体高度的一半,然后求基线的y坐标,实际就是(top-bottom)/2-fontMetrics.bottom;再次强调:这里的ascent,descent,top,bottom,leading指的是到基线baseline的位置。最后相加getHeight+(top-bottom)/2-fontMetrics.bottom**

接下来开始做项目:

  • 第一步自定义属性
    一共需要:内部圆环颜色,外部圆环颜色,圆环宽度,文字颜色,文字大小五种
<declare-styleable name="QQStepView">
        <attr name="outerColor" format="color" />
        <attr name="innerColor" format="color" />
        <attr name="borderWidth" format="dimension" />
        <attr name="stepTextSize" format="dimension" />
        <attr name="stepTextColor" format="color" />
    </declare-styleable>
  • 自定义view获取属性,设置属性等
public class QQStepView extends View {
    private int mOuterColor = Color.RED;
    private int mInnerColor = Color.BLUE;
    private int mBorderWidth = 20;
    private int mStepTextSize;
    private int mStepTextColor;
    private Paint mOuterPaint, mInnerPaint, mTextPaint;
    private int mStepMax;//总的步数
    private int mCurrentStep;//当前步数

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

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

    public QQStepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.QQStepView);
        mOuterColor = ta.getColor(R.styleable.QQStepView_outerColor, mOuterColor);
        mInnerColor = ta.getColor(R.styleable.QQStepView_innerColor, mInnerColor);
        mBorderWidth = (int) ta.getDimension(R.styleable.QQStepView_borderWidth, mBorderWidth);
        mStepTextSize = ta.getDimensionPixelOffset(R.styleable.QQStepView_stepTextSize, mStepTextSize);
        mStepTextColor = ta.getColor(R.styleable.QQStepView_stepTextColor, mStepTextColor);
        ta.recycle();
        //内弧
        mOuterPaint = new Paint();
        mOuterPaint.setAntiAlias(true);
        mOuterPaint.setStrokeWidth(mBorderWidth);
        mOuterPaint.setColor(mOuterColor);
        mOuterPaint.setStrokeCap(Paint.Cap.ROUND);//设置下方为圆形
        mOuterPaint.setStyle(Paint.Style.STROKE);//设置内部为空心
        //外弧
        mInnerPaint = new Paint();
        mInnerPaint.setAntiAlias(true);
        mInnerPaint.setStrokeWidth(mBorderWidth);
        mInnerPaint.setColor(mInnerColor);
        mInnerPaint.setStrokeCap(Paint.Cap.ROUND);//设置下方为圆形
        mInnerPaint.setStyle(Paint.Style.STROKE);//设置内部为空心

        //文字
        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(mStepTextSize);
        mTextPaint.setColor(mStepTextColor);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //调用者在布局文件中可能 wrap_content导致宽高不一致
        //确保是正方形
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(width > height ? height : width, width > height ? height : width);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //1.画外圆弧   边缘没有显示完整
        //RectF recf = new RectF(0, 0, getWidth(), getHeight());

        int center = getWidth() / 2;
        int radius = getWidth() / 2 - mBorderWidth / 2;
        //mBorderWidth/2,mBorderWidth/2,getWidth()-mBorderWidth/2,getWidth()-mBorderWidth/2
        RectF recf = new RectF(center - radius,
                center - radius,
                center + radius,
                center + radius);
        canvas.drawArc(recf, 135, 270, false, mOuterPaint);
        //2.绘制内圆弧
        float sweepAngle = (float) mCurrentStep / mStepMax;
        canvas.drawArc(recf, 135, sweepAngle * 270, false, mInnerPaint);

        //3.绘制文字
        String stepText = mCurrentStep + "";
        Rect rect = new Rect();
        mTextPaint.getTextBounds(stepText,0,stepText.length(),rect);
        int dx = getWidth() / 2 - rect.width() / 2;
        //第一种方式获取高度
        //int dy = getWidth() / 2 + rect.width()/2;
        //第二种表达方式获取高度
        Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
        //获取中心(fontMetrics.bottom - fontMetrics.top) / 2
        int dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
        int baseLine = getHeight() / 2 + dy;
        canvas.drawText(stepText, dx, baseLine, mTextPaint);

    }
    //其他,写几个方法让他动起来

    public void setStepMax(int mStepMax) {
        this.mStepMax = mStepMax;
    }

    public void setCurrentStep(int mCurrentStep) {
        this.mCurrentStep = mCurrentStep;
        //不断绘制 onDraw()
        invalidate();
    }
}

在MainActivity中设置动画

final QQStepView qqStepView = (QQStepView) findViewById(R.id.step_view);
        qqStepView.setStepMax(5000);
        //属性动画
        ValueAnimator animator = ValueAnimator.ofFloat(0, 3000);//0到3000的变化
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float currentStep = (float) animation.getAnimatedValue();//获取当前值
                qqStepView.setCurrentStep((int) currentStep);
            }
        });
        animator.setDuration(2000);
        animator.start();

http://www.niftyadmin.cn/n/3648899.html

相关文章

马克吐温刷墙与碗底的诱惑

马克吐温刷墙马克.吐温小时侯&#xff0c;有一天因为逃学&#xff0c;被妈妈罚着去刷围墙。围墙有30码长&#xff0c;比他的头顶还高出很多。他把刷子蘸上灰浆&#xff0c;刷了几下。看着这么长的围墙&#xff0c;他灰心丧气地坐了下来。伙伴桑迪提着水桶走过来。“桑迪&#x…

Android 解决APN无权限问题

在ICS40以前的版本中&#xff0c;如果程序需要设置APN&#xff0c;只需要在AndroidManifest文件中声明这个权限即可。在40的机器上运行则会抛出以下异常&#xff1a;java.lang.SecurityException: No permission to write APN settings: Neither user *** nor current process …

Android:No permission to write APN settings(沒有写入 APN 设置的权限)

如果你想读Android 4.2以及以上版本的APN&#xff0c;我觉得你改变一下方法即可。我试了&#xff0c;而且可以实现。在Android 4.1 以及以下版本 &#xff1a;Cursor c getContentResolver().query(Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"…

自定义view之实现文字不同颜色

效果图 定义属性 <declare-styleable name"ColorTrackTextView"><attr name"originColor" format"color"/><attr name"changeColor" format"color"/></declare-styleable> 自定义布局&#x…

[Regex]ASP.NET 中的正则表达式-微软速成课程

ASP.NET 中的正则表达式发布日期&#xff1a; 8/17/2004| 更新日期&#xff1a; 8/17/2004速成课程Steven A. Smith适用范围&#xff1a;Microsoft .NET FrameworkMicrosoft ASP.NET正则表达式 API摘要&#xff1a;正则表达式是一种处理文本的有用工具。无论是验证用户输入、搜…

debian交叉编译ide_如何在Debian 10上设置Eclipse Theia Cloud IDE平台

debian交叉编译ide介绍 (Introduction) With developer tools moving to the cloud, adoption of cloud IDE (Integrated Development Environment) platforms is growing. Cloud IDEs are accessible from every type of modern device through web browsers, and they offer …

Android获取手机型号,系统版本,App版本号等信息

MainActivity如下: package cn.testgethandsetinfo; import android.os.Bundle; import android.text.TextUtils; import android.widget.TextView; import android.app.Activity; import android.content.Context; import android.content.pm.PackageInfo; import android.co…

如何在Ubuntu 18.04上使用PHP在MySQL中实现分页

The author selected the the Apache Software Foundation to receive a donation as part of the Write for DOnations program. 作者选择了Apache软件基金会作为Write for DOnations计划的一部分来接受捐赠。 介绍 (Introduction) Pagination is the concept of constrainin…