Android 自定义图片进度条

news2025/6/10 18:11:42

用系统的Progressbar,设置图片drawable作为进度条会出现图片长度不好控制,容易被截断,或者变形的问题。而我有个需求,使用图片背景,和图片进度,而且在进度条头部有个闪光点效果。

如下图:

1605e545fb19408284eb6b6bda03fd28.jpeg

找了两个小时,国内外,百度,github搜遍了,全网都没有找到一个现成的。

最后只好自己写一个。本来我用自己代码写的用颜色值的进度条,很容易就实现了。

产品要用设计师的图片。谁知道啊,这么个小功能却这么麻烦,为这么个进度条的功能加班到晚上11点。

package com.alisajidapps.watermarkpdfss.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;

import com.alisajidapps.watermarkpdfss.R;

public class CustomProgressBar extends View {
 
    private Paint paint;
    private Bitmap progressBarImage;

    private Bitmap backgroundImage;

    private Bitmap progressPointerBitmap;

    private Rect srcRect;
    private Rect dstRect;
    private int progress;

    //手机宽度
    private int screenWidth;

    private int progressWidth;

    private int progressHeight;

    //缩放后的进度条宽度
    private int progressBarWidthNew;

    private Rect pointerRect;

    private Rect pointerDstRect;



 
    public CustomProgressBar(Context context) {
        super(context);
        init();
    }
 
    public CustomProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
 
    public CustomProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
 
    private void init() {
        paint = new Paint();
        progressBarImage = BitmapFactory.decodeResource(getResources(), R.drawable.update_progress); // 你的进度条图片资源
        backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.update_progress_bg); // 你的进度条图片资源
        progressPointerBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.update_progress_seek); // 你的进度条图片资源

        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        screenWidth = displayMetrics.widthPixels;

        scale = (float) (screenWidth*0.7/backgroundImage.getWidth());

        progressWidth =  progressBarImage.getWidth();

        progressHeight = progressBarImage.getHeight();

        progressBarWidthNew = (int) (progressBarImage.getWidth()*scale);

        srcRect = new Rect();
        dstRect = new Rect();

        backRect=new Rect();
        backDstRect=new Rect();

        pointerRect = new Rect();
        pointerDstRect = new Rect();

        progress =10;
    }
 
    public void setProgress(int progress) {
        this.progress = progress;
        invalidate(); // 重绘视图
    }

    Rect backRect;
    Rect backDstRect;

    float scale;


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

        Log.e("xxx","scrrenWidth:"+screenWidth);

        //第一步,画背景

        backRect.left =0;
        backRect.top = 0;
        backRect.right = backgroundImage.getWidth();
        backRect.bottom = backgroundImage.getHeight();

        Log.e("xxx",scale+"");

        Log.e("xxx","backgroundImageWidth:"+backgroundImage.getWidth()+"");

        backDstRect.top =20;
        backDstRect.left = (int) (screenWidth/2 - (backgroundImage.getWidth() * scale/2));
        backDstRect.right = (int) (screenWidth/2 + (backgroundImage.getWidth() * scale/2));
        backDstRect.bottom = (int) (backgroundImage.getHeight() * scale)+20;

        // 绘制缩放后的位图,dstRect缩放后,画进去的图片就是缩放的。
        canvas.drawBitmap(backgroundImage, backRect, backDstRect, paint);


        //第二步,画进度条
        srcRect.left = 0;
        srcRect.top = 0;
        srcRect.right = progressWidth;
        srcRect.bottom = progressHeight;

        Log.e("xxx","progressWidth:"+progressWidth);
        Log.e("xxx","progressHeight:"+progressHeight);

        Log.e("xxx","progressbarWidth:"+progressBarImage.getWidth());
        progressWidth = (int) (progressBarWidthNew *progress / 100 ); // 假设进度是0到100

        //dstRect  等比例缩放了,画进去的图片就会等比例缩放
        dstRect.top =30;
        dstRect.left = (int) (screenWidth/2 -  progressBarWidthNew/2);
        dstRect.right = dstRect.left+ progressWidth;
        dstRect.bottom = (int) (progressBarImage.getHeight() * scale+30);

        canvas.drawBitmap(progressBarImage, srcRect, dstRect, paint);

        Log.e("xxx","怎么没有绘制:"+progressWidth);


        //第三步,画进度条前面的指针效果

        pointerRect.left = 0;
        pointerRect.top = 0;
        pointerRect.right = progressPointerBitmap.getWidth();
        pointerRect.bottom = progressPointerBitmap.getHeight();

        pointerDstRect.left = dstRect.right-15;
        pointerDstRect.top = 0;
        pointerDstRect.right = (int) (dstRect.right+ progressPointerBitmap.getWidth()*scale-15);
        pointerDstRect.bottom = (int) (progressPointerBitmap.getHeight()*scale);

        canvas.drawBitmap(progressPointerBitmap,pointerRect,pointerDstRect,paint);

    }
}

使用时只需要调用setProgressBar就行。

上图就是代码实现的效果。

 

知识总结:

1,基本的绘制图片方法

drawBitmap(Bitmap bitmap, float left, float top, Paint paint)

参数://Bitmap:图片对象,left:偏移左边的位置,top: 偏移顶部的位置

 

2, drawBitmap( Bitmap bitmap, Rect src, Rect dst, Paint paint);

 

这里由2个Rect,第一个Rect --src 代表要裁剪的bitmap的区域,如传null,表示需要绘制整个图片,

 

第二个Rect ---det表示需要将bitmap,绘制在屏幕上的位置,不可为空,并且大于src则把src的裁截区放大,小于src则把src的裁截区缩小。

 

 Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(),R.drawable.ic_logo);

        //绘制方法1:---原图,制作偏移

        canvas.drawBitmap(bitmap,100,100,mPaint);//将图片从(0,0)位置向左偏移100,向右偏移100

 

        Rect srcRect = new Rect(0,0,bitmap.getWidth()/2,bitmap.getHeight()/2);//截取图片左上1/4的区域

 

        Rect dstRect = new Rect(500,500,800,800);//图片需要绘制的矩形区域

        //绘制方法2:--先裁剪再展示

        canvas.drawBitmap(bitmap,srcRect,dstRect, mPaint);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1694372.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用于时间序列概率预测的蒙特卡洛模拟

大家好,蒙特卡洛模拟是一种广泛应用于各个领域的计算技术,它通过从概率分布中随机抽取大量样本,并对结果进行统计分析,从而模拟复杂系统的行为。这种技术具有很强的适用性,在金融建模、工程设计、物理模拟、运筹优化以…

基于springboot+vue的招聘信息管理系统

开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…

大模型的灵魂解读:Anthropic AI的Claude3 Sonnet可解释性研究

大模型技术论文不断,每个月总会新增上千篇。本专栏精选论文重点解读,主题还是围绕着行业实践和工程量产。若在某个环节出现卡点,可以回到大模型必备腔调重新阅读。而最新科技(Mamba,xLSTM,KAN)则提供了大模型领域最新技…

【C语言】C语言-设备管理系统(源码+数据文件)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…

HarmonyOS开发之DevEco Studio安装

HUAWEI DevEco Studio是基于IntelliJ IDEA Community开源版本打造,为运行在HarmonyOS和OpenHarmony系统上的应用和服务(以下简称应用/服务)提供一站式的开发平台。 作为一款开发工具,除了具有基本的代码开发、编译构建及调测等功能…

Python高级进阶--slice切片

slice切片⭐⭐ 在 Python 中,切片操作是一种常见且方便的方式,用于从字符串、列表或元组中获取部分元素。这种操作通过指定起始索引、结束索引和步长来实现。下面我们来看一些关于切片的简单介绍以及一些常见用法。 1. 切片简介 取一个str、list、tup…

一文搞懂 Transformer(总体架构 三种注意力层)

本文将从Transformer的本质、Transformer_的原理_、_Transformer的应用__三个方面,带您一文搞懂Transformer(总体架构 & 三种注意力层)。 节前,我们组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友…

出题123

题目时限空间说明 无特殊均默认 1 s , 256 M B 1s,256MB 1s,256MB Problem a 最大化 在最大化目标值的基础上选择的操作越多越好,且输出操作应当按照顺序执行,即你的输出顺序就是你的执行顺序,当有多个执行顺序可以最大化目标值时&#xff0…

GEE批量导出逐日、逐月、逐季节和逐年的遥感影像(以NDVI为例)

影像导出 1.逐日数据导出2.逐月数据导出3.季节数据导出4.逐年数据导出 最近很多小伙伴们私信我,问我如何高效导出遥感数据,从逐日到逐季度,我都有一套自己的方法,今天就来和大家分享一下!   🔍【逐日导出…

详解最新版RabbitMQ 基于RPM 方式的安装

如何选择安装版本 已经不支持的发布系列 版本最后补丁版本首次发布时间停止更新时间3.73.7.282017年11月28日2020年09月30日3.63.6.162015年12月22日2018年05月31日3.53.5.82015年03月11日2016年10月31日3.43.4.42014年10月21日2015年10月31日3.33.3.52014年04月02日2015年03…

Vivado报错集合

Synth 8-5535 报错代码 [Synth 8-5535] port <clk_0> has illegal connections. It is illegal to have a port connected to an input buffer and other components. The following are the port connections : Input Buffer:Port I of instance clkin1_ibufg(IBUF) i…

张大哥笔记:穷人都在拼命挣钱,而富人都在努力让自己更值钱

最近行业大佬&#xff0c;纷纷网红化&#xff0c;比如周鸿祎&#xff0c;雷军&#xff0c;刘强东纷纷下场&#xff01; 大佬当网红&#xff0c;图啥&#xff1f;当然是图钱了。 大佬都很精的&#xff0c;他们老早就运用媒体的传播杠杆&#xff0c;把自己热度炒起来。 在不断…

类和对象(下篇)(未完结)!

文章目录 在谈构造函数1.构造函数体赋值2.初始化列表尽量使用初始化列表&#xff1f;初始化列表的初始化顺序&#xff1f;成员变量声明处的缺省值构造函数支持类型转换3.explicit关键字 static成员 在谈构造函数 1.构造函数体赋值 class Date{public:Date(int year, int mont…

MATLAB:插值函数之interp与griddata

MATLAB 提供了多种插值函数来处理不同维度的数据。其中&#xff0c;interp1、interp2 和 griddata 是常用的插值函数&#xff0c;分别用于一维、二维和多维&#xff08;不规则&#xff09;数据的插值。 之前有对interp1进行过详细介绍&#xff0c;如需详细了解&#xff0c;请查…

【算法】决策单调性优化DP

文章目录 决策单调性四边形不等式决策单调性 形式1法1 分治法2 二分队列例题 P3515Solution 形式2例题 P3195Solution 形式3例题 CF833BSolution 形式4例题Solution 后话 决策单调性 四边形不等式 定义: 对于二元函数 w ( x , y ) w(x,y) w(x,y)&#xff0c;若 ∀ a , b , …

【Linux取经路】线程同步——条件变量

文章目录 前言一、条件变量1.1 pthread_cond_init——初始化一个条件变量1.2 pthread_cond_destroy——销毁一个条件变量1.3 定义一个全局的条件变量1.4 pthread_cond_wait——等待条件满足1.5 pthread_cond_signal——唤醒一个等待线程1.6 pthread_cond_broadcast——唤醒所有…

云界洞见:移动云服务开启技术创新与问题解决的新篇章

一、什么是移动云 移动云以“央企保障、安全智慧、算网一体、属地服务”为品牌支撑&#xff0c;聚焦智能算力建设&#xff0c;打造一朵智能、智慧、安全可信可控的云&#xff0c;提供更优质的算力服务&#xff0c;引领云计算产业发展。 那么下面博主带领大家了解移动云的优势所…

为什么建立数据库连接耗时?究竟耗时多久?

数据库连接从连接池中取这已经是大家的共识了&#xff0c;因为频繁的建立或者关闭连接代价太大&#xff0c;那么代价究竟有多大&#xff1f; 我们先准备一个简单的数据库连接代码段 public static void main(String[] args) throws ClassNotFoundException, SQLException, Int…

Aligned Layer:trustless应用的通用验证层

1. 引言 Aligned Layer近期获得了2000万美金的A轮融资&#xff0c;Aligned Layer&#xff1a; 致力于成为 去中心化 zero-knowledge (ZK) proof 验证层。旨在为不同证明系统&#xff0c;提供快速、经济且可扩展的零知识证明验证。作为以太坊生态系统及其他生态系统的通用sour…

都2024年了!是谁还不会优化 Hive 的小文件啊!!!速看!

文章目录 小文件产生的原因1.查询建表或者插入2.装载数据3.动态分区小文件影响解决方法针对已经存在的小文件进行优化1.小文件归档2.getmerge3.concatenate4.重写针对写入数据时的优化1.调参优化2.动态分区优化3.使用 Spark 算子控制小文件数量查看 HDFS 上的文件时,无意间点进…