Android 中带有水平进度条指示器的图像滑块

问题描述 投票:0回答:1

我想创建一个带有水平进度条的图像滑块。这是我正在查看的最终输出。

我正在使用下面列出的一个示例。我想用水平进度条替换点滑块,并带有当前滑块的屏幕截图

目前,我有一个点指示器

默认指标.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>

选定的.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>

我正在使用视图页面加载此图像滑块

 <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>

在爪哇中

    private ViewPager sliderpager;

private TabLayout indicator;

//

indicator.setupWithViewPager(sliderpager,true);

android-studio android-viewpager slider android-viewpager2 viewpagerindicator
1个回答
0
投票

我有一个简单的方法来实现你想要的,这是我做的愚蠢的方法:

首先像这样更新你的布局:

            <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>

然后应用此代码来实现进度条作为带有加载和移动动画的指示器

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>()

在 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)
    }

并添加新的扩展

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()
}

别忘了这一点

override fun onDestroyView() {
    super.onDestroyView()
    handler.removeCallbacks(slideRunnable)
    progressBarTimer?.cancel()
    _binding = null
}

还有这个 CarouselItems 模型

data class CarouselItem(val imageUrl: String)

它看起来像这样 预览

© www.soinside.com 2019 - 2024. All rights reserved.