背景

当我们看到UI给我们设计的效果的时候,我们习惯性的思路就是看看google有没有为我们提供相应的控件或者是能否在网上找到一些合适的轮子拿过来直接用。但是,有时候很不巧的是没有这样的轮子供我们直接使用,而且,UI以及产品就需要这样的效果的时候,我们就只能自己进行实现绘制。今天呢,我就带大家从简单的实现一个带有指示器的进度条,帮大家理解一下之定义View的绘制流程。

效果实现图

俗话说,没有效果图,就等于是耍那个啥,所以按照惯例,贴图:

开干

当我们决定要自己进行绘制的时候,我们首先需要对需求,效果进行观察、分析、拆解。就是所谓的大事化小,小事化无。

观察:效果图中包含 进度条、带三角箭头的圆角指示器、进度值以及进度动画

分析:通过观察我们可以将整个进度条分为 指示器,进度条、进度值、动画4部分

拆解:因此我们可以依次对上述部分的组成部分进行单独的绘制最后整体关联是实现上图的效果

自定义View的流程(按照上述部分进行)

大家应该都知道绘制流程包含三部分,自定义属性、测量 measure、draw、layout。但是,我们今天所讲的是进度条View,而不是ViewLayout,所以layout的部分今天暂且不讲。

自定义属性以及代码中获取

属性

说明

app:hpb_centerPadding="5dp"

指示器与进度条的间距

app:hpb_progressBarBackgroundColor="@color/colorPrimary"

进度条背景色

app:hpb_progressBarForegroundColor="@color/colorAccent"

进度条前景色

app:hpb_progressBarHeight="2dp"

指示器bottomPadding

app:hpb_textBottomPadding="5dp"

指示器与进度条的间距

app:hpb_textLeftPadding="5dp"

指示器leftPadding

app:hpb_textRightPadding="5dp"

指示器rightPadding

app:hpb_textTopPadding="5dp"

指示器topPadding

app:hpb_textSize="12sp"

指示器文字大小

app:hpb_textColor="#FFFFFF"

指示器文字颜色

app:hpb_progress="20"

进度值

//获取自定义属性

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.HorizontalProgressBar);

mTextSize = ta.getDimension(R.styleable.HorizontalProgressBar_hpb_textSize, Utils.sp2px(context, 12));

mTextColor = ta.getColor(R.styleable.HorizontalProgressBar_hpb_textColor, Color.parseColor("#FFFFFF"));

currentProgress = ta.getFloat(R.styleable.HorizontalProgressBar_hpb_progress, 0);

mTextLeftPadding = (int) ta.getDimension(R.styleable.HorizontalProgressBar_hpb_textLeftPadding, Utils.sp2px(context, 5));

mTextRightPadding = (int) ta.getDimension(R.styleable.HorizontalProgressBar_hpb_textRightPadding, Utils.sp2px(context, 5));

mTextTopPadding = (int) ta.getDimension(R.styleable.HorizontalProgressBar_hpb_textTopPadding, Utils.sp2px(context, 5));

mTextBottomPadding = (int) ta.getDimension(R.styleable.HorizontalProgressBar_hpb_textBottomPadding, Utils.sp2px(context, 5));

mCenterPadding = (int) ta.getDimension(R.styleable.HorizontalProgressBar_hpb_centerPadding, Utils.sp2px(context, 5));

mProgressHeight = (int) ta.getDimension(R.styleable.HorizontalProgressBar_hpb_progressBarHeight, Utils.sp2px(context, 2));

mBackgroundColor = ta.getColor(R.styleable.HorizontalProgressBar_hpb_progressBarBackgroundColor, Color.parseColor("#E8E8E8"));

mForegroundColor = ta.getColor(R.styleable.HorizontalProgressBar_hpb_progressBarForegroundColor, Color.parseColor("#912CEE"));

ta.recycle();

//进度条条背景色画笔初始化

mBackgroundPaint = new Paint();

mBackgroundPaint.setColor(mBackgroundColor);

mBackgroundPaint.setStrokeCap(Paint.Cap.ROUND);

mBackgroundPaint.setStrokeWidth(mProgressHeight);

mBackgroundPaint.setAntiAlias(true);

//指示器Path画笔初始化

mPathPaint = new Paint();

mPathPaint.setColor(mForegroundColor);

mPathPaint.setStrokeCap(Paint.Cap.ROUND);

mPathPaint.setPathEffect(new CornerPathEffect(Utils.dp2px(getContext(), 2)));

mPathPaint.setAntiAlias(true);

//进度条前景色画笔初始化

mProgressPaint = new Paint();

mProgressPaint.setColor(mForegroundColor);

mProgressPaint.setStrokeWidth(mProgressHeight);

mProgressPaint.setStrokeCap(Paint.Cap.ROUND);

mProgressPaint.setAntiAlias(true);

//进度值文案画笔初始化

mTextPaint = new Paint();

mTextPaint.setColor(mTextColor);

mTextPaint.setTextSize(mTextSize);

mTextPaint.setStyle(Paint.Style.FILL);

//指示器Path初始化

mPath = new Path();

测量

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int width = MeasureSpec.getSize(widthMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

int height = MeasureSpec.getSize(heightMeasureSpec);

setMeasuredDimension(measureWidth(widthMode, width), measureHeight(heightMode, height));

}

/**

* 测量宽度

*

* @param mode

* @param width

* @return

*/

private int measureWidth(int mode, int width) {

switch (mode) {

case MeasureSpec.UNSPECIFIED:

case MeasureSpec.AT_MOST:

case MeasureSpec.EXACTLY:

mWidth = width;

break;

}

return mWidth;

}

/**

* 测量高度

*

* @param mode

* @param height

* @return

*/

private int measureHeight(int mode, int height) {

switch (mode) {

case MeasureSpec.UNSPECIFIED:

case MeasureSpec.AT_MOST:

case MeasureSpec.EXACTLY:

mHeight = height;

break;

}

return mHeight;

}

//文字测量

private void measureText(String text) {

Rect rect = new Rect();

mTextPaint.getTextBounds(text, 0, text.length(), rect);

mTextWidth = rect.width();

mTextHeight = rect.height();

}

绘制

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

mIndicatorWidth = mTextLeftPadding + mTextWidth + mTextRightPadding;

mIndicatorHeight = mTextTopPadding + mTextHeight + mTextBottomPadding;

float backgroundProgressBarStartX = (float) (1.0 * mIndicatorWidth / 2);

float backgroundProgressBarEndX = mWidth - mIndicatorWidth / 2;

float foregroundProgress = (float) (1.0 * (mWidth - mIndicatorWidth) * currentProgress / 100);

float foregroundProgressBarStartX = (float) (1.0 * mIndicatorWidth / 2);

float foregroundProgressBarEndX = foregroundProgressBarStartX + foregroundProgress;

Log.e(TAG, "backgroundProgressBarStartX----" + backgroundProgressBarStartX

+ "----backgroundProgressBarEndX----" + backgroundProgressBarEndX

+ "----foregroundProgress----" + foregroundProgress

+ "----foregroundProgressBarStartX----" + foregroundProgressBarStartX

+ "----foregroundProgressBarEndX----" + foregroundProgressBarEndX

);

float progressX = foregroundProgress;

float progressY = (float) (mCenterPadding + mIndicatorHeight * 1.5);

//进度背景

canvas.drawLine(backgroundProgressBarStartX, progressY, backgroundProgressBarEndX, progressY, mBackgroundPaint);

//进度前景色

canvas.drawLine(foregroundProgressBarStartX, progressY, foregroundProgressBarEndX, progressY, mProgressPaint);

//指示器

drawPath(canvas, progressX, 45);

//文字

drawText(canvas, mTextProgress, progressX);

}

1. 指示器绘制

通过Path进行绘制,描绘出矩形以及下三角

/**

* 绘制指示器

*

* @param canvas

* @param progressX

*/

private void drawPath(Canvas canvas, float progressX, float rotateAngle) {

mPath.reset();

mPath.moveTo(progressX, 0); //1

mPath.lineTo(progressX + mIndicatorWidth, 0); //2

mPath.lineTo(progressX + mIndicatorWidth, mIndicatorHeight); //3

mPath.lineTo((float) (progressX + mIndicatorWidth * 0.75), mIndicatorHeight); //4

mPath.lineTo((float) (progressX + mIndicatorWidth * 0.5), (float) (mIndicatorHeight * 1.5)); //5

mPath.lineTo((float) (progressX + mIndicatorWidth * 0.25), mIndicatorHeight); //6

mPath.lineTo(progressX, mIndicatorHeight);//7

mPath.close();

canvas.drawPath(mPath, mPathPaint);

}

2. 文字的绘制

文字的绘制涉及到测量上边测量中已经提及,但是在绘制中有涉及到基线获取如下所示

/**

* 计算绘制文字时的基线到中轴线的距离

*

* @param p

* @return 基线和centerY的距离

*/

public float getBaseline(Paint p) {

Paint.FontMetrics fontMetrics = p.getFontMetrics();

return (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent;

}

/**

* 绘制文字

*

* @param canvas

* @param text

* @param progressX

*/

private void drawText(Canvas canvas, String text, float progressX) {

float baseline = getBaseline(mTextPaint);

float textY = mTextTopPadding + mTextHeight / 2 + baseline;

canvas.drawText(text, progressX + mTextTopPadding, textY, mTextPaint);

}

总结

以上的完整代码已经上传至github,github地址,如有需要可以上去看看,也可以下载直接使用或者是通过jcenter引入,由于jcenter现状已经停止维护,所以后续会迁入maven

以上就是Android实现带有指示器的进度条的详细内容,更多关于Android 指示器进度条的资料请关注脚本之家其它相关文章!

android 流程指示,Android实现带有指示器的进度条相关推荐

  1. android下载通知栏,Android开发中实现下载文件通知栏显示进度条

    android开发中实现下载文件通知栏显示进度条. 1.使用asynctask异步任务实现,调用publishprogress()方法刷新进度来实现(已优化) public class myasync ...

  2. android仿微信图片上传进度,Android开发之模仿微信打开网页的进度条效果(高仿)...

    一,为什么说是真正的高仿? 阐述这个问题前,先说下之前网上的,各位可以复制这段字,去百度一下  "仿微信打开网页的进度条效果",你会看到有很多类似的文章,不过他们有个共同点,就是实 ...

  3. android仿微信 进度条,Android开发之模仿微信打开网页的进度条效果(高仿)

    一,为什么说是真正的高仿? 阐述这个问题前,先说下之前网上的,各位可以复制这段字,去百度一下  "仿微信打开网页的进度条效果" ,你会看到有很多类似的文章,不过他们有个共同点,就是 ...

  4. android 全局进度条,Android:如何在中心显示全屏进度条

    我正在尝试显示带有自定义主题的进度栏.但是它在左上角而不是中心.如果我不使用自定义主题,它将以中心显示,但不是全屏显示,这会在背景中显示文本视图和其他元素,看起来很糟糕.以下是代码和屏幕截图 自定义主 ...

  5. android 曲线进度条,Android自定义View——使用贝塞尔曲线实现流量进度条

    第一次写带图片的博客,多少还是有点紧张,效果不好,请将就着看,前面的图是今天要写的控件的效果图,元素不多,分别是一个按钮和一个自定义的控件. 在此以前,我看过许多的书,比如<Android群英传 ...

  6. Android魔术——手把手教你实现水晶球波浪进度条

    目录 1.效果展示 2.波浪函数 3.波浪填充 1)原理分析 2)代码实现 4.实现波浪运动效果 1)实现横向运动 2)实现波浪消退效果 5.总结 源码: 1.效果展示 本篇文章讲解如何实现一个水晶球 ...

  7. android自定义进度条百分比跟着走,Android自定义View实现水平带数字百分比进度条...

    这个进度条可以反映真实进度,并且完成百分比的文字时随着进度增加而移动的,所在位置也恰好是真实完成的百分比位置,效果如下: 思路如下:第一部分是左侧的蓝色直线,代表已经完成的进度:第二部分是右侧灰色的直 ...

  8. Android自定义成长值、等级、积分进度条(带属性动画)

    现在很多APP的会员进度条.等级.积分进度条都是按分段显示的,由于最近自己的项目也用到类似的控件,如下图所示,于是就自己撸了一个! package progressandanimation.wtt.c ...

  9. Android移动应用开发之使用异步调用进度条及实现幻灯片切换效果

    文章目录 异步调用进度条 实现幻灯片切换效果 异步调用进度条 核心代码如下: package scq.scq.asyntaskdemo;import androidx.appcompat.app.Ap ...

最新文章

  1. 如何在10亿个整数中找出前1000个最大的数?
  2. 《Thinking in UML》读书笔记之一
  3. Python高级编程:类和实例属性的查找顺序—mro查找
  4. rss聚合模式案例_RSS的完整形式是什么?
  5. H5播放Rtmp之Flowplayer播放
  6. linux vi恢复文件怎么打开文件,Linux上vi编辑文件非正常退出后文件恢复
  7. 英文连写字体怎么练_“衡中体”英语书写视频受到英国媒体关注,现在开始练还不晚!...
  8. 第一个用python实现的数据化运营分析实例——销售预测
  9. 焦作java培训_周口市转行做it
  10. win10下卜卦占星工具
  11. 2020中国自主研发游戏海外市场销售收入保持稳定增加:今年收入同增33%
  12. 计算圆周率可以根据公式如下:请利用Python提供的itertools模块,我们来计算这个序列的前N项和——python
  13. 蓝绿发布、灰度发布(金丝雀发布) 和滚动发布
  14. 搭建Openstack环境以及Openstack认证服务
  15. 在计算机软件中怎么拍照,计算机相机相机软件,这三个软件不仅用于拍照
  16. QTP - 29 What’s New in QTP QTP的一些功能介绍
  17. 什么是稀疏向量(向量的稀疏表示)
  18. uboot调试总结(freescale平台为例)
  19. 2048小游戏 java版(代码+注释)
  20. 大学物理——电磁学的一些知识整理

热门文章

  1. PEiD--查看导出函数
  2. 2019湖湘杯 misc3 之miscmisc
  3. 15 OpenCV4图像处理与视频分析实战(49.基于颜色的对象跟踪-.)
  4. PPTP和L2TP有哪些区别?
  5. 计算机辅助设计与制造实训,最新计算机辅助设计与制造上机实验报告.doc
  6. python学习之下载数据可视化(一)
  7. Web登录其实没那么简单
  8. 剪映使用教程,剪映如何剪视频
  9. ModuleNotFoundError: No module named ‘suit.apps‘
  10. 这个编辑器即将开源!