Layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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=".view.support.GalleryActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_marginTop="-7dp"
android:layout_marginBottom="-7dp"
android:max="100"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"
android:visibility="gone"
/>
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/main_content" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I am using LiveData
to update ProgressBar
, which support 2 mode
- Busy Mode (horizontal animation)
- Progress Mode (horizontal progress)
class MainActivity : AppCompatActivity() { private val viewModel by viewModels<MainViewModel>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) setSupportActionBar(toolbar) init() } private fun init() { viewModel.busyEvent.observe(this, Observer { event -> event.getIfPending()?.also { show -> if (show) { // prevent restart bug with progress animation progressBar.progress = 0 progressBar.isVisible = true progressBar.isIndeterminate = true } else { progressBar.isGone = true progressBar.isIndeterminate = false // prevent restart bug with progress animation progressBar.progress = 0 } } }) viewModel.progressEvent.observe(this, Observer { event -> event.getIfPending()?.also { value -> progressBar.isVisible = true progressBar.isIndeterminate = false val progress = (value * progressBar.max).toInt() /* if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // progressBar.progress = progress progressBar.setProgress(progress, true) } */ val animation: ObjectAnimator = ObjectAnimator.ofInt(progressBar, "progress", progressBar.progress, progress) animation.duration = 500 animation.interpolator = DecelerateInterpolator() animation.start() } }) } fun testBusy() { viewModel.busyEvent.value = Event(true) lifecycleScope.launch { delay(5000) viewModel.busyEvent.value = Event(false) } } fun testProgress() { viewModel.busyEvent.value = Event(true) lifecycleScope.launch { repeat(10) { delay(1000) viewModel.progressEvent.value = Event((it+1)/10.0) } viewModel.busyEvent.value = Event(false) } }}
NOTE: Get ViewModel via ktx
ViewModel
class MainViewModel(application: Application) : AndroidViewModel(application) { internal val busyEvent = MutableLiveData<Event<Boolean>>() internal val progressEvent = MutableLiveData<Event<Double>>()}