Android自定义进度条的圆角横向进度条实例详解

1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的:

invalidate()方法
RectF方法的应用
onMeasure方法的应用

2.原理

画3层圆角矩形,底层为黑色,第二层为灰色,最上一层为进度条颜色,示例图如下:

3.效果图

 

实现圆角进度条还有很多其他方法,比如在Progress控件里填充圆角图片,通过拉伸图片来达到预想的效果,虽然听起来很简单,但实现起来还是有些麻烦的。

4.解说方法

(1)invalidate()方法

invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时, 调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。一般在自定义控件中会用到这个方法。

(2)RectF方法的应用

RectF是用来绘画矩形的方法。

RectF(left,top,right,bottom),四个参数的含义分别是父控件距离矩形左上右下边距的距离,以下用图来说明:

drawRoundRect方法是用来绘制圆角矩形的,它的参数如下:
参数说明

rect:RectF对象。
rx:x方向上的圆角半径。
ry:y方向上的圆角半径。
paint:绘制时所使用的画笔。

(3)onMeasure方法

指定自定义控件在屏幕上的大小,onMeasure方法的两个参数是由上一层控件 传入的大小,而且是模式和尺寸混合在一起的数值,需要MeasureSpec.getMode(widthMeasureSpec) 得到模式,MeasureSpec.getSize(widthMeasureSpec)得到尺寸。

onMeasure的几种模式分别为EXACTLY,AT_MOST,UNSPECIFIED。

[1]MeasureSpec.EXACTLY

MeasureSpec.EXACTLY是精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width=”50dip”,或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。

[2]MeasureSpec.AT_MOST

MeasureSpec.AT_MOST是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。

[3]MeasureSpec.UNSPECIFIED

MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。

5.activity_main.xml文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.progresstest.MainActivity"
tools:ignore="MergeRootFrame" >
<com.example.progresstest.ProgressViewTest
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

6.ProgressViewTest.java文件

package com.example.progresstest;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
public class ProgressViewTest extends View {
/**进度条最大值*/
private float maxCount;
/**进度条当前值*/
private float currentCount;
/**画笔*/
private Paint mPaint;
private int mWidth,mHeight;
public ProgressViewTest(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public ProgressViewTest(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public ProgressViewTest(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
/***
* 设置最大的进度值
* @param maxCount
*/
public void setMaxCount(float maxCount) {
this.maxCount = maxCount;
}
/**
* 得到最大进度值
*/
public double getMaxCount(){
return maxCount;
}
/***
* 设置当前的进度值
* @param currentCount
*/
public void setCurrentCount(float currentCount) {
this.currentCount = currentCount > maxCount ? maxCount : currentCount;
/**
* invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时,
* 调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI
* 线程队列中pop掉。
*/
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
mPaint = new Paint();
//设置抗锯齿效果
mPaint.setAntiAlias(true);
//设置画笔颜色
mPaint.setColor(Color.BLACK);
int round = mHeight/2;
/**
* RectF:绘制矩形,四个参数分别是left,top,right,bottom
* 类型是单精度浮点数
*/
RectF rf = new RectF(0, 0, mWidth, mHeight);
/*绘制圆角矩形,背景色为画笔颜色*/
canvas.drawRoundRect(rf, round, round, mPaint);
/*设置progress内部是灰色*/
mPaint.setColor(Color.rgb(211, 211, 211));
RectF rectBlackBg = new RectF(2, 2, mWidth-2, mHeight-2);
canvas.drawRoundRect(rectBlackBg, round, round, mPaint);
//设置进度条进度及颜色
float section = currentCount/maxCount;
RectF rectProgressBg = new RectF(3, 3, (mWidth-3)*section, mHeight-3);
if(section!=0.0f){
mPaint.setColor(Color.GREEN);
}else{
mPaint.setColor(Color.TRANSPARENT);
}
canvas.drawRoundRect(rectProgressBg, round, round, mPaint);
}
//dip * scale + 0.5f * (dip >= 0 ? 1 : -1)
private int dipToPx(int dip){
float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (dip * scale + 0.5f * (dip >= 0 ? 1 : -1));//加0.5是为了四舍五入
}
/**指定自定义控件在屏幕上的大小,onMeasure方法的两个参数是由上一层控件
* 传入的大小,而且是模式和尺寸混合在一起的数值,需要MeasureSpec.getMode(widthMeasureSpec)
* 得到模式,MeasureSpec.getSize(widthMeasureSpec)得到尺寸
*
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
//MeasureSpec.EXACTLY,精确尺寸
if (widthSpecMode == MeasureSpec.EXACTLY || widthSpecMode == MeasureSpec.AT_MOST) {
mWidth = widthSpecSize;
} else {
mWidth = 0;
}
//MeasureSpec.AT_MOST,最大尺寸,只要不超过父控件允许的最大尺寸即可,MeasureSpec.UNSPECIFIED未指定尺寸
if (heightSpecMode == MeasureSpec.AT_MOST || heightSpecMode == MeasureSpec.UNSPECIFIED) {
mHeight = dipToPx(20);
} else {
mHeight = heightSpecSize;
}
//设置控件实际大小
setMeasuredDimension(mWidth, mHeight);
}
}

MainActivity.java文件

package com.example.progresstest;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
public class MainActivity extends ActionBarActivity {
private ProgressViewTest progress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progress = (ProgressViewTest) findViewById(R.id.progressbar);
progress.setMaxCount(100);
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i <=progress.getMaxCount(); i++) {
Message msg = new Message();
msg.arg1 = i;
msg.what = 0x01;
handler.sendMessage(msg);
try {
//每隔0.1秒进度前进1
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
Handler handler = new Handler(){
public void handleMessage(Message msg) {
if(msg.what==0x01){
progress.setCurrentCount(msg.arg1);
}
};
};
}

以上所述是小编给大家介绍的Android自定义进度条的圆角横向进度条实例详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Android string-array数据源简单使用

    在Android中,用string-array是一种简单的提取XML资源文件数据的方法. 例子如下: 把相应的数据放到values文件夹的arrays.xml文件里 <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="city"> <item>厦门市</item> <item>福州市&l

  • Android this与Activity.this的区别

    写语句的时候有两种情况: Toast.makeText(AlarmActivity.this,"闹钟取消", Toast.LENGTH_SHORT); <pre name="code" class="java">Toast.makeText(this,"闹钟5秒后启动", Toast.LENGTH_SHORT); 用英文在google搜what's difference between this and Activ

  • Android Studio查看Android 5.x源码的步骤详解

    关于Android Studio的好处我就不用说了,下面两点就足矣让你转投Android Studio了: 1.Android Studio是Google官方指定的,目前官网已经去掉了ADT, 大家可以在Android开发者官网 中进行查看,目前只有Android Studio提供下载了. 2.Google也表示ADT不再进行维护了. 转投Android Studio时大势所趋,网上关于如何使用Android Studio的帖子也是满天飞,所以我就不再啰嗦夸奖Android Studio了. 这

  • 浅谈Android中视图动画的属性与使用

    简介 Android动画主要包括视图动画和属性动画,视图动画包括Tween动画和Frame动画,Tween动画又包括渐变动画.平移动画.缩放动画.旋转动画. Tween动画的基本属性 目标 View: 时常 duration; 开始状态 fromXXX; 结束动画 toXXX; 开始时间 startOffset; 重复次数 repeatCount; 时间轴 interpolator(插值器). 代码示例 xml实现 <?xml version="1.0" encoding=&qu

  • Android ViewPager 的使用总结

    在一个窗口里面添加tab便签,完成便签切换来实现页面的切换,这样的好处是可以在同一个窗口里面有多个页面,这些页面共享同一个窗口的资源,同使用多个窗口来实现这个功能来得更加流畅!! 主要产生的类文件有activity,n个view,adapter,自定义的ViewPager,n+1个布局文件 demo所用到文件 步骤: 创建activity package com.example.myviewpager; import java.util.ArrayList; import java.util.L

  • Android6.0 屏幕固定功能详解

    可能大家看到这个标题不知道是什么东西,我先说明下,android6.0在设置->安全->屏幕固定开启后,然后再长按home键出现最近的几个Activity可以选择一个图钉按钮就开启了屏幕固定功能. 屏幕固定开启后,屏幕只能固定在设定的Task上的Activity切换. 一.设置固定屏幕 我们先来看SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java的代码,这段代码就是长按home键出现几个Activity,然后按

  • Android布局居中的几种做法

    Android的布局文件中,如果想让一个组件(布局或View)居中显示在另一个布局(组件)中,可以由这么几种做法: android:layout_gravity android:gravity android:layout_centerInParent layout_gravity android:layout_gravity ,用来指定当前组件(布局或View)在父组件(布局)中的位置,父布局应该是LinearLayout或者它的后裔. layout_gravity取值可能是: top bot

  • Android实现音频条形图效果(仿音频动画无监听音频输入)

    音频条形图 如下图所示就是这次的音频条形图: 由于只是自定义View的用法,我们就不去真实地监听音频输入了,随机模拟一些数字即可. 如果要实现一个如上图的静态音频条形图,相信大家应该可以很快找到思路,也就是绘制一个个的矩形,每个矩形之间稍微偏移一点距离即可.如下代码就展示了一种计算坐标的方法. for (int i = 0; i < mRectCount; i++) { // 矩形的绘制是从左边开始到上.右.下边(左右边距离左边画布边界的距离,上下边距离上边画布边界的距离) canvas.dra

  • Android自定义进度条的圆角横向进度条实例详解

    1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的: invalidate()方法 RectF方法的应用 onMeasure方法的应用 2.原理 画3层圆角矩形,底层为黑色,第二层为灰色,最上一层为进度条颜色,示例图如下: 3.效果图   实现圆角进度条还有很多其他方法,比如在Progress控件里填充圆角图片,通过拉伸图片来达到预想的效果,虽然听起来很简单,但实现起来还是有些麻烦的. 4.解说方法 (1)invalidate()方法 invalidate()是用来刷新

  • Android 使用PopupWindow实现弹出更多的菜单实例详解

    最近想要做一个弹出更多的菜单,而原生的弹出菜单却不是我们想要的效果,所以必然要自定义菜单咯.本人也是借鉴网上的资料进行封装的,感觉还蛮不错的. 原生的菜单如下图: 自定义之后的效果图: 是不是看到这里之后,对比可知,原生的效果不太理想,所以还是再自己定义吧! 1.PopupWindow可以说是一个浮动在Activity之上的容器,通常用来显示自定义的视图.弹出菜单的封装PopMenuMore /** * 对弹出菜单的封装. * http://blog.csdn.net/maosidiaoxian

  • Android获取arrays.xml里的数组字段值实例详解

    Android获取arrays.xml里的数组字段值实例详解 比如在arrays.xml里: <!--leo added for KYLIN-496--> <string-array name="reboot_item"> <item>Reboot</item> <item>Recovery</item> <item>BootLoader</item> </string-array&g

  • Android 拍照并对照片进行裁剪和压缩实例详解

    Android 拍照并对照片进行裁剪和压缩实例详解 本文主要介绍 Android 调用摄像头拍照并对照片进行裁剪和压缩,文中给出了主要步骤和关键代码. 调用摄像头拍照,对拍摄照片进行裁剪,代码如下. /** * 调用摄像头拍照,对拍摄照片进行裁剪 */ private void showCameraAction() { // 跳转到系统照相机 Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (camera

  • Android源码中常用的接口传参实例详解

    Android源码中常用的接口传参实例详解 把MyCclass中的参数传到MyDclass /*接口传参例子2 * MyCclass.java发送MyDclass.java接收 * 原理和MyAclass.java发送MyDclass.java接收完全一样 * */ public class MyCclass { public void getEditext(GetMyFragmentData myFragmentData){ String edStr="人的生命是有限的,可是为人民服务是无限的

  • Android中webview与JS交互、互调方法实例详解

    Android中webview与JS交互.互调方法实例详解 前言: 对于试水的功能,一般公司都会采用H5的方式来开发,可以用很少的资源与很短的项目工期来完成. 但许多情况下,H5页面会需要一些原生持有的一些如用户信息之类的数据,一些交互也需要调用原生的,如toast之类要保持同一个手机风格一致的交互行为.这个时候就需要能够让JS主动调用原生的方法来进行操作或者获取数据.或者是原生调用JS的方法在H5加载的时候传递一些参数. 对于原生调用JS的方法 我们需要实现一个WebViewClient,在这

  • android studio按钮监听的5种方法实例详解

    1.匿名内部类 public class MainActivity extends AppCompatActivity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn1 = fin

  • Android自定义view之利用drawArc方法实现动态效果(思路详解)

    目录 前言 一.准备 1.测量 2.初始化画笔 3.自定义属性 二.关键方法介绍 drawArc 三.实现 1.思路 2.效果图 前言 前几天看了一位字节Android工程师的一篇博客,他实现的是歌词上下滚动的效果,实现的关键就是定义一个偏移量,然后根据情况去修改这个值,最后触发View的重绘来达到效果.于是今天根据这个思路来写一篇简单的文章.欢迎留言 一.准备 在这之前呢,还是得简单描述一下自定义view中的一些准备工作 1.测量 @Override protected void onSize

  • Android中ViewFlipper的使用及设置动画效果实例详解

    本文实例讲述了Android中ViewFlipper的使用及设置动画效果.分享给大家供大家参考,具体如下: 说到左右滑动,其实实现左右滑动的方式很多,有ViewPaer,自定义实现Viewgroup,gallery等都可以达到这种效果.这里做下ViewFliper实现左右滑动的效果. 会用到以下的技术: 1.ViewFlipper 2.GestureDetector 3.Animation 主要是这三个类在起作用. ViewFlipper,不妨把它看做一个容器吧,你可以把许多的View放在这个容

  • Android OkHttp Post上传文件并且携带参数实例详解

    Android OkHttp Post上传文件并且携带参数 这里整理一下 OkHttp 的 post 在上传文件的同时,也要携带请求参数的方法. 使用 OkHttp 版本如下: compile 'com.squareup.okhttp3:okhttp:3.4.1' 代码如下: protected void post_file(final String url, final Map<String, Object> map, File file) { OkHttpClient client = n

随机推荐