自定义view——水平进度条

news/2024/7/5 1:06:13

这里写图片描述
做之前需要了解一些知识

  • 文字宽高获取:一般有以下几种方式
    ①:设置文字矩形,Paint.getTextBounds方法得到宽高
String test = "Android世界";
Rect rect = new Rect();
mPaint.getTextBounds(text, 0, test.length(), rect);
int width = rect.width();//文字宽
int height = rect.height();//文字高

②获取文字的宽高
首先宽:

        String text = getProgress() + "%";
        int textWidth = (int) mPaint.measureText(text);

然后高

结论:

           //文字的高:
            int textHeight = (int) (mPaint.descent() - mPaint.ascent());

分析(参考文章:http://blog.csdn.net/u012551350/article/details/51361778):
这里写图片描述

ascent = ascent线的y坐标 - baseline线的y坐标;//负数

descent = descent线的y坐标 - baseline线的y坐标;//正数

top = top线的y坐标 - baseline线的y坐标;//负数

bottom = bottom线的y坐标 - baseline线的y坐标;//正数

leading = top线的y坐标 - ascent线的y坐标;//负数

文字的高应该等于asecnt+descent,但是ascent是负的所以mPaint.descent() - mPaint.ascent()

自定义view

package com.yijia.myapplication;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ProgressBar;

/**
 * 项目名:AndFix
 * 包名:com.yijia.myapplication
 * 文件名:HorizontalProgrssBarWithProgess
 * 创建者:周成东
 * 创建时间:2018/1/29 19:44
 * 描述:ToDo
 */

public class HorizontalProgrssBarWithProgess extends ProgressBar {
    private static final int DEFAULT_TEXT_SIZE = 10;//sp
    private static final int DEFAULT_TEXT_COLOR = 0XFFC00D1;
    private static final int DEFAULT_COLOR_UNREACH = 0XFFD3D6DA;
    private static final int DEFAULT_HEIGHT_UNREACH = 2;//dp
    private static final int DEFAULT_COLOR_REACH = DEFAULT_TEXT_COLOR;
    private static final int DEFAULT_HEIGHT_REACH = 2;//dp
    private static final int DEFAULT_TEXT_OFFSET = 10;//dp

    private int mTextSize = s2px(DEFAULT_TEXT_SIZE);
    private int mTextColor = DEFAULT_TEXT_COLOR;
    private int mUnReachColor = DEFAULT_COLOR_UNREACH;
    private int mUnReachHeight = d2px(DEFAULT_HEIGHT_UNREACH);
    private int mReachColor = DEFAULT_COLOR_REACH;
    private int mReachHeight = d2px(DEFAULT_HEIGHT_REACH);
    private int mTextOffset = d2px(DEFAULT_TEXT_OFFSET);

    private Paint mPaint;

    private int mRealWidth;

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

    public HorizontalProgrssBarWithProgess(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HorizontalProgrssBarWithProgess(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        obtainStyledAttrs(attrs);
        mPaint = new Paint();
        mPaint.setTextSize(mTextSize);
    }

    private void obtainStyledAttrs(AttributeSet attrs) {
        TypedArray ta = getContext().obtainStyledAttributes(attrs,
                R.styleable.HorizontalProgrssBarWithProgess);
        mTextSize = (int) ta.getDimension(R.styleable.HorizontalProgrssBarWithProgess_progress_text_size,
                mTextSize);
        mTextColor = ta.getColor(R.styleable.HorizontalProgrssBarWithProgess_progress_text_color,
                mTextColor);
        mUnReachColor = ta.getColor(R.styleable.HorizontalProgrssBarWithProgess_progress_unreach_color
                , mUnReachColor);
        mUnReachHeight = (int) ta.getDimension(R.styleable.HorizontalProgrssBarWithProgess_progress_unreach_height
                , mUnReachHeight);
        mReachColor = ta.getColor(R.styleable.HorizontalProgrssBarWithProgess_progress_reach_color
                , mReachColor);
        mReachHeight = (int) ta.getDimension(R.styleable.HorizontalProgrssBarWithProgess_progress_reach_height
                , mReachHeight);
        mTextOffset = (int) ta.getDimension(R.styleable.HorizontalProgrssBarWithProgess_progress_text_offset,
                mTextOffset);
        //一定不要忘了回收
        ta.recycle();


    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //int widhtMode = MeasureSpec.getMode(widthMeasureSpec);
        int widhtSize = MeasureSpec.getSize(widthMeasureSpec);

        int height = measureHeight(heightMeasureSpec);
        setMeasuredDimension(widhtSize, height);
        mRealWidth = widhtSize - getPaddingRight() - getPaddingLeft();
    }

    private int measureHeight(int heightMeasureSpec) {
        int result;
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else {
            //文字的高
            int textHeight = (int) (mPaint.descent() - mPaint.ascent());
            result = getBottom() + getTop() + Math.max(Math.max(mUnReachHeight, mReachHeight),
                    Math.abs(textHeight));
            if (mode == MeasureSpec.AT_MOST) {
                result = Math.min(result, size);
            }

        }
        return result;
    }

    @Override
    protected synchronized void onDraw(Canvas canvas) {
        canvas.save();
        canvas.translate(getLeft(), getHeight() / 2);

        boolean noNeedUnRech = false;
        float radio = getProgress() * 1.0f / getMax();
        float progressX = radio * getWidth();


        String text = getProgress() + "%";
        int textWidth = (int) mPaint.measureText(text);
        if (textWidth + progressX > mRealWidth) {
            progressX = mRealWidth - textWidth;
            noNeedUnRech = true;
        }
        float endX = progressX - mTextOffset / 2;
        if (endX > 0) {
            mPaint.setColor(mReachColor);
            mPaint.setStrokeWidth(mReachHeight);
            canvas.drawLine(0, 0, endX, 0, mPaint);
        }

        //drawText
        mPaint.setColor(mTextColor);
        int y = (int) (-(mPaint.ascent() + mPaint.descent()) / 2);
        canvas.drawText(text, progressX, y, mPaint);

        //mUnReach bar
        if (!noNeedUnRech) {
            float startX = progressX + mTextOffset / 2 + textWidth;
            mPaint.setColor(mUnReachColor);
            mPaint.setStrokeWidth(mUnReachHeight);
            canvas.drawLine(startX,0,mRealWidth,0,mPaint);
        }
        canvas.restore();
    }

    private int d2px(int dpValue) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue
                , getResources().getDisplayMetrics());
    }

    private int s2px(int spValue) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue
                , getResources().getDisplayMetrics());
    }
}

自定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="progress_unreach_color" format="color"/>
    <attr name="progress_unreach_height" format="dimension"/>
    <attr name="progress_reach_color" format="color"/>
    <attr name="progress_reach_height" format="dimension"/>
    <attr name="progress_text_color" format="color"/>
    <attr name="progress_text_size" format="dimension"/>
    <attr name="progress_text_offset" format="dimension"/>
    <declare-styleable name="HorizontalProgrssBarWithProgess">
        <attr name="progress_unreach_color"/>
        <attr name="progress_unreach_height" />
        <attr name="progress_reach_color" />
        <attr name="progress_reach_height" />
        <attr name="progress_text_color"/>
        <attr name="progress_text_size" />
        <attr name="progress_text_offset" />
    </declare-styleable>
</resources>

MainActivity

public class MainActivity extends Activity {
    private static final int MSG = 0;
    HorizontalProgrssBarWithProgess mProgess;
    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int progress = mProgess.getProgress();
            mProgess.setProgress(++progress);
            if (progress >= 100) {
                handler.removeMessages(MSG);
            }
            handler.sendEmptyMessage(MSG);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mProgess = (HorizontalProgrssBarWithProgess) findViewById(R.id.progress);
        handler.sendEmptyMessage(MSG);

    }


}

布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:yj="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
>

    <com.yijia.myapplication.HorizontalProgrssBarWithProgess
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:progress="50"
         android:padding="5dp"
        android:layout_marginTop="30dp"
        />

    <com.yijia.myapplication.HorizontalProgrssBarWithProgess
        android:id="@+id/progress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:progress="50"
         android:padding="5dp"
        android:layout_marginTop="30dp"
        yj:progress_text_color="#44ff0000"
        yj:progress_unreach_color="#f000"
        yj:progress_reach_color="@color/colorAccent"
        />

</LinearLayout>

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

相关文章

Android属性allowBackup安全风险浅析

1.allowBackup安全风险描述 Android API Level 8及其以上Android系统提供了为应用程序数据的备份和恢复功能&#xff0c;此功能的开关决定于该应用程序中AndroidManifest.xml文件中的allowBackup属性值[1] &#xff0c;其属性值默认是True。当allowBackup标志为true时&#xff…

软件测试管理--目录

前 言第一部分 基础篇第1章 测试管理概论1.1 三个基础测试概念1.2 软件测试基本流程1.3 软件测试管理攻略1.3.1测试管理主要内容1.3.2本书测试管理攻略第2章 软件测试背景2.1 测试案例2.2 软件测试发展历史2.3 国内IT企业测试行业分析第二部分 管理篇第3 章管理团队第4 章测试…

如何在Ubuntu 18.04上使用Docker Compose打包Laravel应用程序进行开发

介绍 (Introduction) To containerize an application refers to the process of adapting an application and its components in order to be able to run it in lightweight environments known as containers. Such environments are isolated and disposable, and can be …

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

首先看下效果图 在做这个项目之前先了解下文字获取 我之前也写过一篇文章是自定义view——自定义圆环进度条:http://blog.csdn.net/qq_24675479/article/details/78880078 今天详细讲解一下baseLine 基线&#xff08;参考文章&#xff1a;文淑大神的自定义View之绘图篇&#x…

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

马克吐温刷墙马克.吐温小时侯&#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…