10

我想创建一个自定义的 SeekBar,但是我遇到了这个问题,即在某些地方进度没有跟随 SeekBar 的拇指(进度值从 0-10 到 90-100)。我相信它会发生,因为我将 设置thumbOffset为 0,以便拇指留在进度条内。我想做一个 iPhone 风格的 SeekBar。

进度0处的 SeekBar (正常):

在此处输入图像描述

进度5的SeekBar (不正常):

在此处输入图像描述

进度50处的 SeekBar (正常):

在此处输入图像描述

进度90处的 SeekBar (不正常):

在此处输入图像描述

进度100处的 SeekBar (正常):

在此处输入图像描述

根据拇指位置绘制进度时,似乎thumbOffset没有考虑 。我尝试将其更改thumbOffset为拇指宽度的一半,并使用不同的填充进行各种组合,但没有解决问题。我还尝试了在 SO 上找到的所有其他解决方案。

这是我正在使用的 XML:

SeekBar 定义:

<SeekBar
    android:id="@+id/scan_seekbar"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="0.5"
    android:max="100"
    android:progress="5"
    android:progressDrawable="@drawable/bg_seekbar"
    android:splitTrack="false"
    android:thumbOffset="0dp"
    android:thumb="@drawable/seekbar_thumb" />

可绘制bg_seekbar.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">
        <shape android:shape="rectangle">
            <size android:height="48dp"/>
            <corners android:radius="25dp"/>
            <stroke android:color="@color/semiLightBlue" android:width="1dp"/>
        </shape>
    </item>

    <item android:id="@android:id/progress">
        <clip>
            <shape android:shape="rectangle">
                <corners android:radius="25dp"/>
                <size android:height="48dp"/>
                <stroke android:color="@color/colorAccent" android:width="1dp"/>
                <solid android:color="@color/colorAccent"/>
            </shape>
        </clip>
    </item>
</layer-list>

SeekBar 拇指seekbar_thumb.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/colorAccent"/>
            <corners android:radius="25dp"/>

            <padding android:bottom="8dp" android:top="8dp" android:left="16dp" android:right="16dp" />
        </shape>
    </item>


    <item android:drawable="@drawable/ic_swipe_white" android:gravity="center" android:height="32dp" android:width="44dp"/>
</layer-list>

有没有其他人遇到过这个问题?

4

2 回答 2

6

您的实现依赖于ClipDrawable来绘制进度条。进度可绘制跨越进度条的整个长度,但被ClipDrawable缩短或剪裁。这会在进度条的左侧留下圆角,但在右侧形成正方形。随着进度条的增长、赶上并超过拇指,您会看到方形的一面。

可能有几种方法可以解决这个问题,但让我们选择基于 XML 的方法。让我们将ClipDrawable替换为ScaleDrawable,如下所示:

bg_seekbar.xml

<layer-list>
    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <size android:height="48dp" />
            <corners android:radius="25dp" />
            <stroke
                android:width="1dp"
                android:color="@color/semiLightBlue" />
        </shape>
    </item>
    <item android:id="@android:id/progress">
        <scale
            android:scaleWidth="100%"
            android:useIntrinsicSizeAsMinimum="true">
            <shape android:shape="rectangle">
                <corners android:radius="25dp" />
                <size
                    android:width="50dp"
                    android:height="48dp" />
                <stroke
                    android:width="1dp"
                    android:color="@color/colorAccent" />
                <solid android:color="@color/colorAccent" />
            </shape>
        </scale>
    </item>
</layer-list>

scaleWidth属性告诉我们,当级别达到最大值时,drawable 将被缩放到 100%。useIntrinsicSizeAsMinimum顺便说一下,似乎没有记录的属性指定可绘制对象的最小尺寸将是其固有宽度,即 50dp x 48dp。这并不完全正确,因为当级别为零时可绘制对象的宽度和高度将为零,但当级别为 1 或更高时会弹出到固有大小。

这是进行此更改后进度条发生的情况。我已经使用默认拇指来明确发生了什么:

在此处输入图像描述

如您所见,一旦拇指开始移动,进度条就会跳到最小尺寸并从那里开始增长。

所以,让我们重新引入原来的拇指。这个拇指将在开始时覆盖进度条并将跳转隐藏到最小尺寸。我们只是想覆盖那个区域,这样白色就不会透出来。

在此处输入图像描述

于 2020-05-22T13:51:51.830 回答
1

我这样解决了这个问题:

首先,拇指永远不会消失。当进度为0或100时出现。当我们使用偏移量时,拇指会弹出。

bg_seekbar_first.xml

我们将在进度 < max / 2 时使用它

<?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">
            <corners android:radius="24dp"/>
            <size android:height="48dp" />
            <stroke android:width="1dp" android:color="@color/colorAccent"/>
        </shape>
    </item>
    <item android:id="@android:id/progress"
        android:gravity="center_vertical|fill_horizontal">
        <scale android:scaleWidth="100%">
            <shape android:shape="rectangle"
                android:tint="@color/colorAccent">
                <corners android:radius="0dp"/>
                <size android:height="48dp" />
                <solid android:color="@color/colorAccent" />
            </shape>
        </scale>
    </item>
</layer-list>

bg_seekbar_second.xml

我们将在进度 > max / 2 时使用它

<?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">
            <corners android:radius="24dp"/>
            <size android:height="48dp" />
            <stroke android:width="1dp" android:color="@color/colorAccent"/>
        </shape>
    </item>
    <item android:id="@android:id/progress"
        android:gravity="center_vertical|fill_horizontal">
        <scale android:scaleWidth="100%">
            <shape android:shape="rectangle"
                android:tint="@color/colorAccent">
                <corners android:radius="24dp"/>
                <size android:height="48dp" />
                <solid android:color="@color/colorAccent" />
            </shape>
        </scale>
    </item>
</layer-list>

seekbar_thumb.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/colorAccent"/>
            <corners android:topRightRadius="24dp"
                 android:bottomRightRadius="24dp"/>

            <padding android:bottom="8dp" android:top="8dp" android:left="16dp" android:right="16dp" />
        </shape>
    </item>


    <item android:drawable="@android:drawable/ic_menu_close_clear_cancel" android:gravity="center" android:height="32dp" android:width="44dp"/>
</layer-list>

我改变了拇指半径

在此处输入图像描述

<com.google.android.material.card.MaterialCardView
        android:layout_width="match_parent"
        android:layout_height="48dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        app:cardCornerRadius="24dp"
        android:layout_marginTop="64dp"
        >
        <SeekBar
            android:id="@+id/scan_seekbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0.5"
            android:max="100"
            android:paddingStart="0dp"
            android:paddingEnd="0dp"
            android:progress="1"
            android:progressDrawable="@drawable/bg_seekbar_first"
            android:splitTrack="false"
            android:thumb="@drawable/seekbar_thumb"
            android:thumbOffset="0dp"
            />
    </com.google.android.material.card.MaterialCardView>

我添加了一个 cardView 来解决这个问题:

在此处输入图像描述

scan_seekbar.setOnSeekBarChangeListener(object  : SeekBar.OnSeekBarChangeListener{
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                if(progress < seekBar?.max!! / 2){
                    seekBar.progressDrawable = ContextCompat.getDrawable(context!!,R.drawable.bg_seekbar_first)
                }else{
                    seekBar.progressDrawable = ContextCompat.getDrawable(context!!,R.drawable.bg_seekbar_second)
                }
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {
            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {
            }

        })

然后我用这个代码(Kotlin)onProgressChanged 来解决这个问题:

在此处输入图像描述

结果:

在此处输入图像描述

我希望这个对你有用。

于 2020-05-21T14:08:40.163 回答