自定义View之渐变色圆形进度条

2023-05-16

先展示下效果图:

这里写图片描述

然后按照自定义view的步骤来实现。

我们需要将目标定义清楚:
目标是渐变色圆形进度条,那么,使用canvas画弧形是基础了,另外是渐变色的效果,这里使用LinearGradient来实现。
既然是提供一个进度条,那么,是需要自定义View的用户来进行设置进度值的。
另外,将渐变色的接口也提供出来了,这样,用户就可以根据需要自己定义喜欢的渐变色效果。
还有view的大小,使用直径来表示。
最后,要展示进度条如何使用,用了一个定时器,每秒推进一次进度。

下面来具体实现:

1、自定义View的属性

在values下面新建一个attr.xml,现在里面定义我们的属性,

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <attr name="diameter" format="dimension" />

    <declare-styleable name="CircleProgressView">
        <attr name="diameter" />
    </declare-styleable>

</resources>

2、在View的构造方法中获得我们自定义的属性

    public CircleProgressView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        /**
         * 获得我们所定义的自定义样式属性
         */
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CircleProgressView, defStyle, 0);
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++)
        {
            int attr = a.getIndex(i);
            switch (attr)
            {
            case R.styleable.CircleProgressView_diameter:
                // 默认设置为40dp
                mDiameter = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                        TypedValue.COMPLEX_UNIT_SP, 40, getResources().getDisplayMetrics()));
                break;          
            }
        }
        a.recycle();

        mPaint = new Paint();
        rect = new RectF();
        progressValue=0;
    }

3、重写onMeasure

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        int width = 0;
        int height = 0;

        //设置直径的最小值
        if(mDiameter<=40){
            mDiameter=40;
        }
        height=mDiameter;
        width=mDiameter;

        Log.i("customView","log: w="+width+" h="+height);
        setMeasuredDimension(width, height);
    }

4、重写onDraw

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int mWidth = getMeasuredWidth();
        int mHeight = getMeasuredHeight();

        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth((float) mWidth/10 );
        mPaint.setStyle(Style.STROKE);
        mPaint.setStrokeCap(Cap.ROUND);
        mPaint.setColor(Color.TRANSPARENT);

        rect.set(20, 20, mWidth - 20, mHeight - 20);
        canvas.drawArc(rect, 0, 360, false, mPaint);
        mPaint.setColor(Color.BLACK);   

        float section = ((float)progressValue) / 100;
        int count = mColors.length;
        int[] colors = new int[count];
        System.arraycopy(mColors, 0, colors, 0, count);         

        LinearGradient shader = new LinearGradient(3, 3, mWidth - 3 , mHeight - 3, colors, null,
                Shader.TileMode.CLAMP);
        mPaint.setShader(shader);

        canvas.drawArc(rect, 0, section * 360, false, mPaint);
    }

5、提供对外接口

这里有两个对外接口,一个是用于获取新的进度值的:

    public void setProgressValue(int progressValue){

        this.progressValue = progressValue;
        Log.i("customView","log: progressValue="+progressValue);            

    }

另外一个是用于设置渐变色的,这里我是定义了4种颜色,经过测试效果比较好:

    public void setColors(int[] colors){

        mColors = colors;
        Log.i("customView","log: progressValue="+progressValue);            

    }

6、中布局文件中使用

在布局文件中我定义了5个view,中间一个大的,四角四个小的,这样效果比较炫:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:custom="http://schemas.android.com/apk/res/com.customview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.customview.view.CircleProgressView
        android:id="@+id/circle_progress_view1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"            
        android:layout_centerInParent="true" 
        android:padding="10dp"
        custom:diameter="200dp"              
        /> 

    <com.customview.view.CircleProgressView
        android:id="@+id/circle_progress_view2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"            
        android:layout_toLeftOf="@id/circle_progress_view1"               
        android:layout_below="@id/circle_progress_view1"    
        android:padding="10dp"
        custom:diameter="80dp"  
        /> 

     <com.customview.view.CircleProgressView
        android:id="@+id/circle_progress_view3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/circle_progress_view1"
        android:layout_below="@id/circle_progress_view1"                   
        android:layout_centerHorizontal="true"
        android:padding="10dp"  
        custom:diameter="80dp"      
        /> 

     <com.customview.view.CircleProgressView
        android:id="@+id/circle_progress_view4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/circle_progress_view1"
        android:layout_above="@id/circle_progress_view1"                   
        android:layout_centerHorizontal="true"
        android:padding="10dp"
        custom:diameter="80dp"      
        /> 

     <com.customview.view.CircleProgressView
        android:id="@+id/circle_progress_view5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/circle_progress_view1"
        android:layout_above="@id/circle_progress_view1"                   
        android:layout_centerHorizontal="true"
        android:padding="10dp"  
        custom:diameter="80dp"      
        /> 

</RelativeLayout>

7、在activity中使用

主要是一个定时器的使用,来推进进度条,另外,是渐变色的颜色初值设置:

package com.customview;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.WindowManager;

import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import com.customview.view.CircleProgressView;

import android.app.Activity;
import android.graphics.Color;

public class MainActivity extends Activity
{
    CircleProgressView circle_progress_view1;
    CircleProgressView circle_progress_view2;
    CircleProgressView circle_progress_view3;
    CircleProgressView circle_progress_view4;
    CircleProgressView circle_progress_view5;

    int progressValue=0;    

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
            this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);//去掉信息栏

        setContentView(R.layout.activity_main);

        circle_progress_view1 = (CircleProgressView)findViewById(R.id.circle_progress_view1);
        circle_progress_view2 = (CircleProgressView)findViewById(R.id.circle_progress_view2);
        circle_progress_view3 = (CircleProgressView)findViewById(R.id.circle_progress_view3);
        circle_progress_view4 = (CircleProgressView)findViewById(R.id.circle_progress_view4);
        circle_progress_view5 = (CircleProgressView)findViewById(R.id.circle_progress_view5);

        //第一个使用默认颜色,第二三个使用指定颜色,另外2个使用随机颜色
        int[] colors;
        colors=new int[]{ 0xffc42c1b, 0xfffeea08, 0xff04aafc, 0xff15e078};
        circle_progress_view2.setColors( colors);
        colors=new int[]{ 0xffffffff, 0xffaaaaaa, 0xff555555, 0xff000000};      
        circle_progress_view3.setColors( colors);       
        circle_progress_view4.setColors( randomColors());
        circle_progress_view5.setColors( randomColors());

        timer.schedule(task, 1000, 1000); // 1s后执行task,经过1s再次执行          
    }

    Handler handler = new Handler() {  
        public void handleMessage(Message msg) {  
            if (msg.what == 1) {  
                Log.i("log","handler : progressValue="+progressValue);

                //通知view,进度值有变化
                circle_progress_view1.setProgressValue(progressValue*3);
                circle_progress_view1.postInvalidate();
                circle_progress_view2.setProgressValue(progressValue*5/2);
                circle_progress_view2.postInvalidate();
                circle_progress_view3.setProgressValue(progressValue*2);                
                circle_progress_view3.postInvalidate();
                circle_progress_view4.setProgressValue(progressValue*3/2);              
                circle_progress_view4.postInvalidate();
                circle_progress_view5.setProgressValue(progressValue*1);                
                circle_progress_view5.postInvalidate();

                progressValue+=1;
                if(progressValue>100){
                    timer.cancel();
                }
            }  
            super.handleMessage(msg);              
        };  
    };  

    private int[] randomColors() {
        int[] colors=new int[4];

        Random random = new Random();
        int r,g,b;
        for(int i=0;i<4;i++){
            r=random.nextInt(256);
            g=random.nextInt(256);
            b=random.nextInt(256);
            colors[i]=Color.argb(255, r, g, b);
            Log.i("customView","log: colors["+i+"]="+Integer.toHexString(colors[i]));
        }

        return colors;
    }

    Timer timer = new Timer();  
    TimerTask task = new TimerTask() {  

        @Override  
        public void run() {  
            // 需要做的事:发送消息  
            Message message = new Message();  
            message.what = 1;  
            handler.sendMessage(message);  
        }  
    };  

}

至此,完美收工。
我是实现了一个渐变色圆形进度条,渐变色的颜色初值可以指定,进度条的值也是由用户来指定,本例中是使用定时器来推进的,每个进度条的进度控制不一致,颜色不一样,位置不一样,组合起来,效果很炫哦!

完整代码见如下地址:

http://download.csdn.net/detail/lintax/9623574

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义View之渐变色圆形进度条 的相关文章

  • Ember 不更新模型更改的视图

    该小提琴重新创建了入门套件 并带有可更改模型的额外按钮 http jsfiddle net UjacC 1 http jsfiddle net UjacC 1 但是 当单击 更改 时 数组会更改 但视图不会更新 为什么
  • Android 自定义视图忽略 XML 中的“android:enabled”?

    我正在设置android enabled false 在自定义视图上 但它似乎对isEnabled 财产 这是一个简单的测试用例 public class TestView extends View public TestView Cont
  • Rails:从视图内渲染视图(不是部分视图)

    我有一个对两者都有响应的控制器html and js The htmlview 渲染整个页面 包括页眉和页脚 而js仅替换 main 除了页眉和页脚之外 两种格式呈现相同的内容 我可以用三个文件获得这种效果 show html erb di
  • 如何在视图中调用 Grails 服务?

    简单的问题 我有一个服务类 比方说helpersService 和一个方法def constructURI params 如何从模板视图调用此方法 我尝试了以下代码但没有成功 img src 但我得到以下结果 No signature of
  • “引起:java.lang.RuntimeException:视图必须有标签”的实际含义是什么?

    如果知道想要什么标签 请告诉我 Caused by java lang RuntimeException view must have a tag BaseActivity java Override public void setCont
  • 使用什么来移动 UIView self.frame 或 self.transform 属性?

    这个问题我有点困惑 我知道我可以改变观点self frame origin 但我发现有一个名为 变换 的属性 我认为这是用于在屏幕上移动我的视图等 也许我有点不明白 所以我想知道 我必须使用哪个房产来搬家UIView 或者它的子类 另一个类
  • 在android中,将相机预览流到视图上

    我想将 Android 相机的相机预览流式传输到视图上 目的是随后使用 onDraw 将各种内容添加到视图中 我不需要随时实际捕捉图像 它不必是最高质量或每秒最大数量的帧 有谁知道如何做到这一点 将其添加到您的 xml 中
  • “android.view.View 已弃用” - 还有什么可以使用或如何修复?

    我刚刚开始尝试 Android Studio 按照视频教程上的说明进行操作 这是我对这个人告诉我的看法 但我不断收到错误消息 View is deprecated 我该如何解决 或者我该用什么来代替 这是我的代码 public class
  • Rails:使最终用户可以编辑视图?

    无论如何 我可以使最终用户可以编辑 Rails 视图中的内容吗 这样他们就可以在我允许的页面上进行简单的文本更改 而无需我自己编辑 HAML 文件 想法 澄清 我了解 CMS 系统 但我认为这并不完全是我想要的 我想保持对视图的编程控制 但
  • 如何将一个 SwiftUI View 作为变量传递给另一个 View 结构

    我正在实施一个very自定义 NavigationLink 称为MenuItem并希望在整个项目中重用它 它是一个符合以下条件的结构体View并实施var body some View其中包含一个NavigationLink 我需要以某种方
  • VIEW for 表结合 UNION ALL 的 MySQL 性能

    假设我有 2 张桌子MySQL create table persons id bigint unsigned not null auto increment first name varchar 64 surname varchar 64
  • ASP.NET 视图中的区域?

    我正在使用 razor 引擎制作 ASP NET MVC 应用程序 我想知道是否可以使用Regions http msdn microsoft com en us library 9a1ybwek aspx在一个视图中 就像是 region
  • 推送/呈现模态视图控制器

    我的视图控制器中有一个表 我们称之为 TVC1 我使用了 TVC1 中的行 以便用户除了 TVC1 上的数据之外还可以输入更多数据 因此 当有人点击 TVC1 中的特定行时 它将显示另一个视图控制器 我们称之为 TVC2 然而 当显示TVC
  • Codeigniter查看和回显

    我有一个在 codeigniter 中处理网页侧栏的函数 如下 function process sidebar this gt load gt view first access 1 this gt load gt view second
  • Ruby on Rails(三)隐藏部分视图

    我正在开发 Ruby on Rails 3 Web 应用程序 我有一个名为User有一列名为role 我正在寻找对视图的这些部分具有 错误 角色的用户隐藏视图部分的最佳方法 例如我希望所有用户都能够看到用户index页面 但我只想要具有角色
  • 在视图中获取路线名称

    我尝试设计导航菜单 我有 3 个这样的项目 仪表板 Pages List Add Articles List Add 现在我想大胆Pages当用户处于此部分时 如果在Add页面我都想要粗体Pages and Add my routes ph
  • android 选项卡小部件内列表视图中的滑动事件

    我创建了一个显示列表视图的活动 并且在滑动操作时使用 ViewFlipper 显示另一个列表 代码附在下面 import android app Activity import android os Bundle import androi
  • 具有自定义标题颜色和图像的 UITabBarItem

    我正在尝试在 xcode ios 中自定义我的 TabBar 但是我刚刚发现 ppl 说这是不可自定义的 另外 我确实找到了某种解决方案 但它们都不适合我 我几乎想更改 UITabBarItem 标题 文本 颜色 并更改其中的 2 张图像
  • 如何从沙发底座获取所有钥匙?

    我使用python语言从couchbase获取所有密钥 以下是我的代码 function doc meta emit null meta id 这是 namedb 存储桶中的视图 from couchbase import Couchbas
  • Android 自定义布局 - onDraw() 永远不会被调用

    public class MainActivity extends Activity Override public void onCreate Bundle savedInstanceState super onCreate savedI

随机推荐

  • mongo-db相关方法

    一 参数 名称 描述 db adminCommand 针对 admin数据库运行命令 db aggregate 运行不需要基础集合的管理 诊断管道 db cloneDatabase hostname 不推荐使用 当针对MongoDB 4 0
  • Django-django.core.exceptions.ImproperlyConfigured: SQLite 3.9.0 or later is required (found 3.7.17)

    运行Django报错 xff0c 原因是因为SQLite版本过低 xff0c 需要升级 下载源码包 xff1a wget https www sqlite org 2021 sqlite autoconf 3350500 tar gz xf
  • TIDB-Error 1105: Out Of Memory Quota问题解决

    一 背景 复杂sql查询报错 二 原因 单条s q l使用内存默认为1G 三 解决 tiup cluster edit config tidb test server configs tidb mem quota query 4294967
  • Kafka-offset链接kafka链接不上

    是在kafka的broker配置server properties的listeners改为listeners 61 PLAINTEXT kafka ip 9092 kafka ip要写具体IP xff0c 不要写localhost
  • python-加密解密

    一 安装对应的库 pip span class token function install span pycryptodome 二 加密和解密的步骤 span class token comment 加密 span def cry pas
  • Js闭包理解、运用

    br onClick function br var pageNum 61 sourcePageNum br return function node br getChildSources node pageNum br pageNum 6
  • 关于C++ 的无名对象

    include lt iostream gt using namespace std class A public explicit A int val m val val cout lt lt 34 call 1 34 lt lt end
  • pt工具的使用(7) pt-archiver的使用

    一 描述 pt archiver 是归档表的工具 xff0c 在 sql 中写入高效归档和清除作业 目标是在不对 OLTP 查询产生太大影响的情况下 xff0c 将旧数据从表中蚕食掉 xff0c 从而实现低影响 仅向前的作业 您可以将数据插
  • linux-node_exporter突然挂掉(couldn‘t get dbus connection)

    一 背景 突然收到一台机器挂掉的告警 xff0c 去上面查看发现机器正常 xff0c uptime正常 xff0c 没有重启情况 xff0c UID 20029的用户是tidb su tidb的时间较长 xff0c node exporte
  • pt工具的使用(1) pt工具的安装

    PT工具是使用Perl语言编写和执行的 xff0c 所以需要系统中有Perl环境 rpm qa perl DBI perl DBD MySQL perl Time HiRes perl IO Socket SSL 检查是否已经安装pt工具所
  • 使用move_base进行路径规划

    本文所实现的效果来自 ROS入门实例 xff0c 对初学者会有一定帮助 move base是ROS环境下一个重要的功能包 xff0c 可以使机器人在指定框架内移动到目标位置 xff0c 是实现后续导航功能的基础 xff0c 很多人想学习gm
  • iperf3-带宽测试工具的详细使用说明

    软件简介 xff1a iperf3 是一个 TCP UDP 和 SCTP 网络带宽测量工具 是用于主动测量 IP 网络上可达到的最大带宽的工具 它支持调整与时序 xff0c 协议和缓冲区有关的各种参数 对于每个测试 xff0c 它都会报告测
  • 用示波器 查看波特率是多少?

    在做涉及串口操作的应用时 xff0c 要看看串口数据是否正常 xff0c 如果串口通信有问题 xff0c 也可以用示波器来诊断 示波器可以通过高低电平来检测哪里有数据 xff0c 哪里没数据 xff0c 判断哪个模块出问题了 示波器具体用法
  • VS C++ 实现发布订阅模式(Publish/Subscribe)——基于旧版PX4 uORB模式

    源码已经上传至我的 span class token punctuation span Gitee span class token punctuation span span class token punctuation span ht
  • 【TCP专题】TCP连接建立

    今天开始 xff0c 我们整理一些关于TCP协议的知识 这块的内容写起来是非常费劲的 xff0c 因为本身TCP协议就不是一个简单的协议 xff0c 它能获得如今的地位 xff0c 和其复杂且出色的表现是分不开的 什么是面向连接 众所周知
  • cmake中添加引用动态链接和静态链接库

    动态库的添加 xff1a span class hljs keyword link directories span span class hljs envvar PROJECT SOURCE DIR span lib span class
  • ESP32的SDK开发之blufi一键配网

    ESP32 是集成 2 4 GHz Wi Fi 和蓝牙双模的单芯片方案 xff0c 采用台积电 TSMC 超低功耗的 40 纳米工艺 xff0c 拥有最 佳的功耗性能 射频性能 稳定性 通用性和可靠性 xff0c 适用于各种应用和不同功耗需
  • javascript作用域链的灵活运用1

    size 61 large javascript比较出彩的运用之一 xff1a 作用域链 1 对于有洁癖的前台人员来说 xff0c 全局变量就像长在美女脸上的黑斑 xff0c 真的无法容忍 2 javascript权威指南 说的那样 xff
  • ESP32的SDK开发之blufi一键配网微信小程序端开发

    上一篇文章简单介绍了blufi配网协议 xff0c 现在来讲讲再微信小程序端实现配网的控制 xff0c 小程序开发是基于官方原生API开发 本人的微信小程序开发也是初学的 xff0c 由于之前没接触过前端开发 xff0c 软件写的很渣渣 蓝
  • 自定义View之渐变色圆形进度条

    先展示下效果图 xff1a 然后按照自定义view的步骤来实现 我们需要将目标定义清楚 xff1a 目标是渐变色圆形进度条 xff0c 那么 xff0c 使用canvas画弧形是基础了 xff0c 另外是渐变色的效果 xff0c 这里使用L