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的值即可。