Reputation: 243
I want to create an image slider with a horizontal progress bar. Here is the final output I am looking at.
I am using an example that is currently listed below. I want to replace the dot slider with a horizontal progress bar with a screenshot of the current slider
At the moment, I have a dot indicator
Default indicatior.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:innerRadius="0dp"
android:shape="ring"
android:thickness="3dp"
android:useLevel="false">
<solid android:color="@android:color/darker_gray" />
</shape>
</item>
selected.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:innerRadius="0dp"
android:shape="ring"
android:thickness="3dp"
android:useLevel="false">
<solid android:color="@color/teal_200" />
</shape>
</item>
I am using view page to load this image slider
<androidx.viewpager.widget.ViewPager
android:id="@+id/slider_pager"
android:layout_width="0dp"
android:layout_height="220dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" >
</androidx.viewpager.widget.ViewPager>
<com.google.android.material.tabs.TabLayout
android:id="@+id/indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="180dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/slider_pager"
app:tabBackground="@drawable/indicator_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
android:background="@android:color/transparent">
</com.google.android.material.tabs.TabLayout>
In Java
private ViewPager sliderpager;
private TabLayout indicator;
//
indicator.setupWithViewPager(sliderpager,true);
Upvotes: 0
Views: 883
Reputation: 1
I have an easy way to achieve what do you want, here is dumb way i do:
First update your layout like this:
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/rvPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="@id/account_balance"
app:layout_constraintBottom_toTopOf="@+id/rv_videos">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="150dp"
tools:listitem="@layout/carousel_item_layout"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="@+id/indicatorLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center"
android:orientation="horizontal"
android:paddingBottom="5dp"
app:layout_constraintBottom_toBottomOf="parent">
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Then apply this code to implements progressbar as indicator with loading and movement animations
private lateinit var viewPager: ViewPager2
private lateinit var carouselAdapter: CarouselAdapter
private val handler = Handler(Looper.getMainLooper())
private val slideRunnable = Runnable { viewPager.currentItem = (viewPager.currentItem + 1) % carouselAdapter.itemCount }
private var progressBarTimer: CountDownTimer? = null
private val progressBars = mutableListOf<ProgressBar>()
Added this code in OnViewCreated
viewPager = binding.viewPager
val carouselItems = listOf(
CarouselItem("https://picsum.photos/id/237/200/300"),
CarouselItem("https://picsum.photos/id/238/200/300"),
CarouselItem("https://picsum.photos/id/239/200/300")
)
carouselAdapter = CarouselAdapter(
carouselItems,
viewPager,
onPageChangeListener = { _, _, _ ->
// Handle page change
}
)
viewPager.adapter = carouselAdapter
val indicatorLayout = view?.findViewById<LinearLayout>(R.id.indicatorLayout)
indicatorLayout?.removeAllViews()
for (i in carouselItems.indices) {
val progressBar = ProgressBar(context, null, android.R.attr.progressBarStyleHorizontal).apply {
layoutParams = LinearLayout.LayoutParams(6.dpToPx(), 6.dpToPx()).apply {
if (i > 0) {
marginStart = 5.dpToPx()
}
}
progressDrawable = ContextCompat.getDrawable(context, R.drawable.bar_carousel_round)
}
indicatorLayout?.addView(progressBar)
progressBars.add(progressBar)
}
val params = progressBars[0].layoutParams
params.width = 30.dpToPx()
params.height = 6.dpToPx()
progressBars[0].layoutParams = params
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
progressBars.forEach { it.progress = 0 }
for (i in progressBars.indices) {
progressBars[i].animateSize(6.dpToPx(), 6.dpToPx())
}
progressBars[position].animateSize(30.dpToPx(), 6.dpToPx())
progressBarTimer?.cancel()
progressBarTimer = object : CountDownTimer(5000, 50) {
override fun onTick(millisUntilFinished: Long) {
val progress = ((5000 - millisUntilFinished) / 50).toInt()
progressBars[position].progress = progress
}
override fun onFinish() {
viewPager.currentItem = (viewPager.currentItem + 1) % carouselAdapter.itemCount
}
}.start()
}
})
handler.postDelayed(slideRunnable, 5000)
}
and add new Extension
fun Int.dpToPx(): Int {
val metrics = Resources.getSystem().displayMetrics
return (this * (metrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)).roundToInt()
}
fun ProgressBar.animateSize(targetWidth: Int, targetHeight: Int) {
val initialWidth = this.width
val initialHeight = this.height
val widthAnimator = ValueAnimator.ofInt(initialWidth, targetWidth)
val heightAnimator = ValueAnimator.ofInt(initialHeight, targetHeight)
widthAnimator.addUpdateListener { animation ->
val params = this.layoutParams
params.width = animation.animatedValue as Int
this.layoutParams = params
}
heightAnimator.addUpdateListener { animation ->
val params = this.layoutParams
params.height = animation.animatedValue as Int
this.layoutParams = params
}
widthAnimator.start()
heightAnimator.start()
}
Don't Forget This
override fun onDestroyView() {
super.onDestroyView()
handler.removeCallbacks(slideRunnable)
progressBarTimer?.cancel()
}
And this CarouselItems Model
data class CarouselItem(val imageUrl: String)
It's will look like this Preview
I Consider make this as library may someone can help?
Upvotes: 0