我想创建一个自定义的SeekBar,但是在某些地方进度未遵循SeekBar的拇指(在进度值从0-10到90-100之间)时出现了这个问题。我相信这是因为我将thumbOffset
设置为0,以便拇指停留在进度栏中。我想制作一个iPhone风格的SeekBar。
正在进行的SeekBar 0(可以):
正在进行的SeekBar 5(不正常):
正在进行的SeekBar 50(可以):
正在进行的SeekBar 90(不正常):
正在进行的SeekBar 100(可以):
基于拇指位置绘制进度时,似乎未考虑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 thumb 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>
还有其他人遇到这个问题吗?
您的实现依赖于ClipDrawable绘制进度条。进度条跨越进度条的整个长度,但是会被ClipDrawable缩短或剪切。这将圆角留在进度条的左侧,但在右侧为正方形。随着进度条的增长,追上并超越拇指,您会看到方形的一面。
可能有几种方法可以解决此问题,但让我们来研究基于XML的东西。让我们用ScaleDrawable替换ClipDrawable,如下所示:
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
属性告诉我们,当级别最大时,可绘制对象将缩放为100%。顺便说一下,似乎没有记录的useIntrinsicSizeAsMinimum
属性指定可绘制对象的最小大小为其固有宽度,即50dp x 48dp。这不是完全正确,因为在级别为零时drawable的宽度和高度为零,而在级别为1或更大时将弹出到固有尺寸。
这里是完成此更改后进度条的内容。我已经用默认的拇指弄清楚了正在发生什么:
您可以看到,一旦拇指开始移动,进度条就会跳到最小尺寸并从那里开始增长。
所以,让我们重新介绍原始的拇指。此拇指将在开始时覆盖进度条,并将跳转隐藏到最小大小。我们只是想覆盖该区域,因此白色不会显示出来。
我通过这种方式解决了问题:
首先,拇指永远不会消失。当进度为0或100时显示。使用偏移量时,拇指向外弹出。
bg_seekbar_first.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">
<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解决了此问题:
结果:
我希望它对您有用。