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
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值