Android基础--自定义ProgressBar

ProgressBar概念

ProgressBar为进度条控件,有Indeterminate不确定模式和Determinate确定模式两种:①不确定模式通常使用圆形循环动画来表示类似“正在加载”的过程,进度无法确定,具有不确定性;②确定模式是通过将已发生的进度与总量的百分比显示在进度条上,比如下载或上传文件的数量等。

  • ProgressBar属性
属性含义
style修改ProgressBar样式
animationResolution动画帧之间的超时(以毫秒为单位)
indeterminate允许启用不确定模式
indeterminateTint修改进度条颜色
indeterminateBehavior定义进度达到最大值时不确定模式应如何表现
indeterminateDrawable用于不确定模式的Drawable
indeterminateDuration不确定动画的持续时间
indeterminateOnly仅限于不确定模式(状态保持进度模式将不起作用)
interpolator设置不确定动画的加速度曲线
max定义最大值
min定义最小值
mirrorForRtl定义在RTL模式下是否需要镜像关联的可绘制对象
progress定义默认进度值,介于0到最大值之间
progressDrawable可绘制用于进度模式
secondaryProgress定义二级进度值,介于0和最大值之间

ProgressBar自定义样式

1. Indeterminate不确定模式

Indeterminate不确定模式默认样式是一个有缺口的圆环循环转动,如下图左侧所示,只能通过indeterminateTint修改下进度条颜色,下面将自定义写一个类似太阳花的不确定模式ProgressBar。

  • 简单drawable一下

(1) 首先找一张加载图片;

在这里插入图片描述

(2) drawable中设置图片的旋转动画**<drawable/indeterminate_style.xml>**;

<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/loading"
    android:fromDegrees="0.0"
    android:pivotX="50.0%"
    android:pivotY="50.0%"
    android:toDegrees="360.0" />

(3) 修改ProgressBar的样式;

    <ProgressBar
        android:id="@+id/bar2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminateTint="#3d3d3d"
        android:indeterminateDrawable="@drawable/indeterminate_style" />

需要注意的是,这种效果图片是会旋转起来的,太阳花上进度格的位置不是固定的。

  • 自定义 “正在加载” 弹窗

自定义ProgressBar弹窗的效果图如下:

  • 首先做好准备工作;

Indeterminate模式 “正在加载” 的动画 <drawable/loading_style.xml>

自定义加载的圆形图片有10个进度条,这里将动画定为10个动画帧,这样看起来比较连贯;

<?xml version="1.0" encoding="utf-8"?>
<animation-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <!-- 定义动画帧 -->
    <item
        android:drawable="@drawable/loading1"
        <!-- 该动画帧的持续时间 -->
        android:duration="100" />
    <item
        android:drawable="@drawable/loading2"
        android:duration="100" />
    <item
        android:drawable="@drawable/loading3"
        android:duration="100" />
    <item
        android:drawable="@drawable/loading4"
        android:duration="100" />
    <item
        android:drawable="@drawable/loading5"
        android:duration="100" />
    <item
        android:drawable="@drawable/loading6"
        android:duration="100" />
    <item
        android:drawable="@drawable/loading7"
        android:duration="100" />
    <item
        android:drawable="@drawable/loading8"
        android:duration="100" />
    <item
        android:drawable="@drawable/loading9"
        android:duration="100" />
    <item
        android:drawable="@drawable/loading10"
        android:duration="100" />
</animation-list>


“正在加载” 的背景 <progress_bg.xml>

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- 背景颜色 -->
    <solid android:color="#ff404040" />
    <!-- 背景圆角 -->
    <corners
        android:bottomLeftRadius="8dp"
        android:bottomRightRadius="8dp"
        android:topLeftRadius="8dp"
        android:topRightRadius="8dp" />
</shape>

  • 自定义 “正在加载” 弹窗

弹窗中显示的自定义item <custom_progress_bar.xml>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="@drawable/progress_bg"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:padding="30dp">

    <View
        android:id="@+id/loading_image"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@drawable/loading_style" />

    <TextView
        android:id="@+id/loading_tips"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:text="正在加载"
        android:textColor="#FFFFFF" />

</LinearLayout>

弹窗的样式 <values/styles.xml>

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

    <!-- 定义ProgressDialog样式 -->
    <style parent="@android:style/Theme.Dialog" name="ProgressDialog">
        <!-- 窗口的边框样式 -->
        <item name="android:windowFrame">@null</item>
        <!-- 是否为浮动窗口 -->
        <item name="android:windowIsFloating">true</item>
        <!-- 窗口内容覆盖的样式 -->
        <item name="android:windowContentOverlay">@null</item>
        <!-- 窗口动画样式,这里使用对话框的默认动画样式 -->
        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
        <!-- 窗口与软键盘的交互模式,这里设置在软键盘弹出时调整窗口位置 -->
        <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
        <!-- 窗口的背景颜色 -->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!-- 窗口是否显示标题栏,这里不显示标题栏 -->
        <item name="android:windowNoTitle">true</item>
    </style>

</resources>

  • 自定义 “正在加载” 弹窗 <LoadingDialog.kt>
class LoadingDialog(context : Context, themeResId : Int) : Dialog(context , themeResId) {

    override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)

        // 当弹窗获得焦点时,开始 ”正在加载“ 动画
        if( loading_image != null ){
            val spinner = loading_image.background as AnimationDrawable
            spinner.start()
        }
    }

}

  • “正在加载” 弹窗的使用 <MainActivity.kt>

在MainActivity的布局中添加一个按钮,id为load_btn,然后在初始化View中给load_btn按钮添加点击事件,点击按钮触发 “正在加载” 弹窗;

class MainActivity : AppCompatActivity() {

    private lateinit var loadingDialog : LoadingDialog

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initView()
    }

    private fun initView(){

        load_btn.setOnClickListener {

            // 创建对话框
            loadingDialog = LoadingDialog(this, R.style.ProgressDialog)
            loadingDialog.setContentView(R.layout.custom_progress_bar)
            loadingDialog.loading_tips.text = "加载中..."

            // 设置对话框属性
            // 将对话框设置为不可撤销,用户无法通过点击对话框外部或按返回键来取消对话框
            loadingDialog.setCancelable(false)
            loadingDialog.setOnCancelListener(null)
            // 将对话框的位置设置为屏幕中心
            loadingDialog.window!!.attributes.gravity = Gravity.CENTER
            // 获取对话框窗口的属性对象
            val lp = loadingDialog.window!!.attributes
            // 设置对话框背景的透明度为0.2,即20%不透明
            lp.dimAmount = 0.2f
            // 将修改后的属性对象应用到对话框窗口上
            loadingDialog.window!!.attributes = lp
            loadingDialog.show()
            
        }

    }
}

2. Determinate确定模式

Determinate确定模式可以用横向的进度条来显示进度,进度条的进度需要通过设置来实现,使用时需要将ProgressBar的style属性修改为水平进度条;

  style="?android:attr/progressBarStyleHorizontal" 
  or
  style="@android:style/Widget.Material.ProgressBar.Horizontal"

使用第2种方法的话,在style上按滚轮键可以跳转到Widget.Material.ProgressBar.Horizontal的样式设置代码部分:

    <style name="Widget.Material.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal">
        <item name="progressDrawable">@drawable/progress_horizontal_material</item>
        <item name="indeterminateDrawable">@drawable/progress_indeterminate_horizontal_material</item>
        <item name="minHeight">16dip</item>
        <item name="maxHeight">16dip</item>
    </style>

水平进度条的样式在progressDrawable中进行自定义绘制,可以把系统中progress_horizontal_material.xml内容复制出来进行修改;

  • 自定义绘制水平进度条ProgressBar <horizontal_style.xml>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 进度条的背景色 -->
    <item android:id="@android:id/background"
        android:gravity="center_vertical|fill_horizontal">
        <shape android:shape="rectangle">
            <!-- 设置水平进度条的高度、圆角、颜色 -->
            <size android:height="10dp" />
            <corners android:radius="5dp" />
            <solid android:color="#AAA" />
        </shape>
    </item>
    <!-- 缓冲进度条的背景色 -->
    <item android:id="@android:id/secondaryProgress"
        android:gravity="center_vertical|fill_horizontal">
        <!-- 属性android:scaleWidth="100%"一定要加上,否则设置进度无效 -->
        <scale android:scaleWidth="100%">
            <shape android:shape="rectangle">
                <size android:height="10dp" />
                <corners android:radius="5dp" />
                <solid android:color="@color/purple_200" />
            </shape>
        </scale>
    </item>
    <!-- 进度条的背景色 -->
    <item android:id="@android:id/progress"
        android:gravity="center_vertical|fill_horizontal">
        <scale android:scaleWidth="100%">
            <shape android:shape="rectangle">
                <size android:height="10dp" />
                <corners android:radius="5dp" />
                <solid android:color="@color/purple_500"/>
            </shape>
        </scale>
    </item>
</layer-list>

  • 添加ProgressBar控件 <activity_main.xml>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/minus_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="minus"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <Button
        android:id="@+id/add_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="add"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <ProgressBar
        android:id="@+id/progress_bar"
        style="@android:style/Widget.Material.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:min="0"
        android:progress="28"
        android:secondaryProgress="60"
        android:progressDrawable="@drawable/horizontal_style"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="50dp"/>


</androidx.constraintlayout.widget.ConstraintLayout>

  • ProgressBar的使用 <MainActivity.kt>
class MainActivity : AppCompatActivity() {

    private var progressNum : Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initView()
    }

    private fun initView(){
        progressNum = progress_bar.progress

        minus_btn.setOnClickListener {
            if (progressNum >= 10){
                progressNum -= 10
                progress_bar.progress = progressNum
            }else{
                progress_bar.progress = 0
            }
        }

        add_btn.setOnClickListener {
            if (progressNum <= 90){
                progressNum += 10
                progress_bar.progress = progressNum
            }else{
                progress_bar.progress = 100
            }
        }
    }
}

效果图如下,可以通过点击按钮来设置水平进度条的进度;实际应用过程中根据进度的百分比来设置ProgressBar的progress的值即可。

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
img
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓(文末还有ChatGPT机器人小福利哦,大家千万不要错过)

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题
图片

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现圆弧进度条的自定义ProgressBar,可以使用Canvas和Paint来绘制。 首先,创建一个自定义ProgressBar类,继承自ProgressBar类,并实现构造方法和onDraw方法: ``` public class CircleProgressBar extends ProgressBar { private Paint paint; // 画笔 private int roundColor; // 圆环颜色 private int progressColor; // 进度条颜色 private int textColor; // 文字颜色 private float textSize; // 文字大小 private float roundWidth; // 圆环宽度 private int max; // 最大进度 private boolean textIsDisplayable; // 是否显示进度文字 private int style; // 进度条样式 public static final int STROKE = 0; public static final int FILL = 1; public CircleProgressBar(Context context) { this(context, null); } public CircleProgressBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleProgressBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // 获取自定义属性的值 TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar); roundColor = mTypedArray.getColor(R.styleable.CircleProgressBar_roundColor, Color.RED); progressColor = mTypedArray.getColor(R.styleable.CircleProgressBar_progressColor, Color.GREEN); textColor = mTypedArray.getColor(R.styleable.CircleProgressBar_textColor, Color.GREEN); textSize = mTypedArray.getDimension(R.styleable.CircleProgressBar_textSize, 15); roundWidth = mTypedArray.getDimension(R.styleable.CircleProgressBar_roundWidth, 5); max = mTypedArray.getInteger(R.styleable.CircleProgressBar_max, 100); textIsDisplayable = mTypedArray.getBoolean(R.styleable.CircleProgressBar_textIsDisplayable, true); style = mTypedArray.getInt(R.styleable.CircleProgressBar_style, 0); mTypedArray.recycle(); // 初始化画笔 paint = new Paint(); } @Override protected synchronized void onDraw(Canvas canvas) { super.onDraw(canvas); // 获取圆心坐标和半径 int centerX = getWidth() / 2; int centerY = getHeight() / 2; int radius = (int) (centerX - roundWidth / 2); // 绘制圆环 paint.setColor(roundColor); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(roundWidth); paint.setAntiAlias(true); canvas.drawCircle(centerX, centerY, radius, paint); // 绘制进度条 paint.setStrokeWidth(roundWidth); paint.setColor(progressColor); RectF oval = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius); switch (style) { case STROKE: paint.setStyle(Paint.Style.STROKE); canvas.drawArc(oval, 0, 360 * getProgress() / getMax(), false, paint); break; case FILL: paint.setStyle(Paint.Style.FILL_AND_STROKE); if (getProgress() != 0) canvas.drawArc(oval, 0, 360 * getProgress() / getMax(), true, paint); break; } // 绘制文字 paint.setStrokeWidth(0); paint.setColor(textColor); paint.setTextSize(textSize); paint.setTypeface(Typeface.DEFAULT_BOLD); int percent = (int) (((float) getProgress() / (float) getMax()) * 100); if (textIsDisplayable && percent >= 0) { String text = percent + "%"; float textWidth = paint.measureText(text); canvas.drawText(text, centerX - textWidth / 2, centerY + textSize / 2, paint); } } } ``` 在这个类中,我们定义了几个自定义属性,包括圆环颜色、进度条颜色、文字颜色、文字大小、圆环宽度、最大进度、是否显示进度文字、进度条样式等。在构造方法中,我们获取了这些属性的值,并初始化了画笔。在onDraw方法中,我们首先获取了圆心坐标和半径,然后使用画笔绘制了圆环和进度条,最后绘制了进度文字。 接下来,在布局文件中使用这个自定义ProgressBar: ``` <com.example.circleprogressbar.CircleProgressBar android:id="@+id/circle_progressbar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" app:roundColor="#cccccc" app:roundWidth="5dp" app:progressColor="#FF4081" app:textColor="#FF4081" app:textSize="20sp" app:textIsDisplayable="true" app:style="STROKE" /> ``` 最后,在Java代码中设置进度值即可: ``` CircleProgressBar circleProgressBar = findViewById(R.id.circle_progressbar); circleProgressBar.setProgress(50); // 设置进度为50% ``` 这样就完成了自定义的圆弧进度条的实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值