评分条星星之间的空格

43
我需要在我的评分条星号之间插入一个空格,例如评分条如下:

enter image description here

但我需要它这样:

enter image description here

我该如何做到这一点?


请参考这个Stack Overflow回答 - Cat
1
我已经添加了一个功能请求,请为其投票:https://code.google.com/p/android/issues/detail?id=230511 - Leos Literak
6个回答

5
我不知道它是否还有用,但我做了一个自定义库,可以在程序中和XML中编程更改星号之间的空格(以及其他一些内容):SimpleRatingBar
它具有以下特点:
  • android:layout_width完全工作:可以将其设置为wrap_contentmatch_parent或任意dp。
  • 任意数量的星星。
  • 任意步长。
  • 可以通过精确设置或设置最大大小来精确控制星星的大小。
  • 正常状态下的颜色可自定义(星星和评分栏的边框、填充和背景)。
  • 按下状态下的颜色可自定义(星星和评分栏的边框、填充和背景)。
  • 可以自定义星星之间的大小分离。
  • 可以自定义星星的边框宽度。
  • 可以自定义星星的圆角半径。
  • 允许设置OnRatingBarChangeListener。
  • 星星的填充可以从左到右或从右到左设置(支持RTL语言)。
  • AnimationBuilder集成在视图中,可以使用动画编程设置评分。
这是它的预览
在您的情况下,您只需要执行以下操作:
ratingbar.setStarsSeparation(20, Dimension.DP);

或者,例如以像素为单位:
ratingbar.setStarsSeparation(100, Dimension.PX);

您可以在jcenter或者Maven Central中找到它。因此,在您的build.gradle文件中,只需将以下内容添加到依赖项中:

compile 'com.iarcuschin:simpleratingbar:0.1.+'


它不支持自定义星形图案。或者它支持吗? - FoY
嗨 @FoY,它不会。 - FlyingPumba

4
您有一个next属性。
android:progressDrawable = "@drawable/rating_stars"
android:indeterminateDrawable = "@drawable/rating_stars"

@drawable/rating_stars :

<?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:drawable="@drawable/star_empty" />
    <item android:id="@+android:id/secondaryProgress"
          android:drawable="@drawable/star_empty" />
    <item android:id="@+android:id/progress"
          android:drawable="@drawable/star" />
</layer-list>

star_empty和star是存储在drawable目录中的图像。因此,您可以在图形编辑器中更改star和star_empty,如果需要,还可以添加spassing。


4
我同意,但是请考虑下面的情况:在一个大项目中,您需要创建4种不同类型的评分条,每个评分条包含3种不同类型的可绘制图像,大约有12张图片,并且它们之间有2像素的间距。现在如果需要增加1像素的间距,我更倾向于将setPadding(2)更改为setPadding(3),而不是重新发行10张图片。 - ademar111190
1
通过在可绘制对象的左侧和/或右侧添加插图,会在视图的左侧和/或右侧边框上获得不必要的填充。 - hqzxzwb

1

只需使用自定义图标并使用样式,我是说将其视为Photoshop并根据您想要的外观进行替换,以取代系统评级样式图标。


0

我认为你需要获取系统星形PNG文件的副本,并使用Photoshop / GIMP /其他编辑器手动添加所需的填充。


根据我上面发布的链接,我相信您可以使用大小属性自定义用于星星的Drawable,通过为RatingBar设置style标签来伪造填充。 - Cat
这种方式很丑,评分条类的配置中没有方法。 - ademar111190
@Soxxeh 嗯,我在你发布的链接中都没有找到这方面的例子。第一个链接看起来更有希望,但第一句话说:“你必须将填充添加到png本身”,然后展示了ProgressBar类的一个方法。我没有看到任何影响填充的样式。你能详细说明一下吗? - FoamyGuy
@Tim 抱歉,我看错了我发的第二个链接。(它是改变实际图像大小,而不是大小+填充...)我会在上面做出评论。 - Cat

0

我同意Tim的观点,我也采用了相同的逻辑并且成功了。 在我的项目中,我使用自己的星形图像来进行星级评分。 我制作了带有额外空间(填充)的星形图像,这导致星星之间有空隙。


1
是的,我同意。但是现在考虑以下情况:您将在一个大项目中创建4种类型的评分条,每个评分条都有2或3种不同类型的可绘制对象,大约有10张图片,它们之间有2像素的间距。现在如果需要增加1像素的间距,我更喜欢将setPadding(2)更改为setPadding(3),而不是重新发行这10张图片。 - ademar111190
你有解决方案吗?请分享一下你尝试过的最好的方法。 - Meher
不幸的是,我找不到优雅的解决方法,所以我在自己的图像中加入了间距 :( ,我不喜欢这个问题被解决,希望有一天能找到一个合适的方法来解决它。 - ademar111190

0

您可以使用自定义SVG并设置分离值

通过使用这个类,您可以修复Android自定义SVG评分栏,并通过替换类内的值(我将此值标记为There_You_Can_Set_Your_Value)来设置Drawable End。

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapShader
import android.graphics.Canvas
import android.graphics.Shader
import android.graphics.drawable.*
import android.graphics.drawable.shapes.RoundRectShape
import android.graphics.drawable.shapes.Shape
import android.util.AttributeSet
import android.view.Gravity
import androidx.appcompat.graphics.drawable.DrawableWrapper
import androidx.appcompat.widget.AppCompatRatingBar

class RatingBarSvg @JvmOverloads
constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = R.attr.ratingBarStyle,
) : AppCompatRatingBar(context, attrs, defStyleAttr) {

    private var mSampleTile: Bitmap? = null

    private val drawableShape: Shape
        get() {
            val roundedCorners = floatArrayOf(5f, 5f, 5f, 5f, 5f, 5f, 5f, 5f)
            return RoundRectShape(roundedCorners, null, null)
        }

    init {
        val drawable = tileify(progressDrawable, false) as LayerDrawable
        //drawable.findDrawableByLayerId(android.R.id.background).setColorFilter(backgroundTintColor, PorterDuff.Mode.SRC_ATOP);
        //drawable.findDrawableByLayerId(android.R.id.progress).setColorFilter(progressTintColor, PorterDuff.Mode.SRC_ATOP);
        progressDrawable = drawable
    }

    /**
     * Converts a drawable to a tiled version of itself. It will recursively
     * traverse layer and state list drawables.
     */
    @SuppressLint("RestrictedApi")
    private fun tileify(drawable: Drawable, clip: Boolean): Drawable {
        if (drawable is DrawableWrapper) {
            var inner: Drawable? = drawable.wrappedDrawable
            if (inner != null) {
                inner = tileify(inner, clip)
                drawable.wrappedDrawable = inner
            }
        } else if (drawable is LayerDrawable) {
            val numberOfLayers = drawable.numberOfLayers
            val outDrawables = arrayOfNulls<Drawable>(numberOfLayers)

            for (i in 0 until numberOfLayers) {
                val id = drawable.getId(i)
                outDrawables[i] = tileify(
                    drawable.getDrawable(i),
                    id == android.R.id.progress || id == android.R.id.secondaryProgress
                )
            }

            val newBg = LayerDrawable(outDrawables)

            for (i in 0 until numberOfLayers) {
                newBg.setId(i, drawable.getId(i))
            }

            return newBg

        } else if (drawable is BitmapDrawable) {
            val tileBitmap = drawable.bitmap
            if (mSampleTile == null) {
                mSampleTile = tileBitmap
            }

            val shapeDrawable = ShapeDrawable(drawableShape)
            val bitmapShader = BitmapShader(
                tileBitmap,
                Shader.TileMode.REPEAT, Shader.TileMode.CLAMP
            )
            shapeDrawable.paint.shader = bitmapShader
            shapeDrawable.paint.colorFilter = drawable.paint.colorFilter
            return if (clip)
                ClipDrawable(
                    shapeDrawable, Gravity.START,
                    ClipDrawable.HORIZONTAL
                )
            else
                shapeDrawable
        } else {
            return tileify(getBitmapDrawableFromVectorDrawable(drawable), clip)
        }

        return drawable
    }

    private fun getBitmapDrawableFromVectorDrawable(drawable: Drawable): BitmapDrawable {
        val bitmap = Bitmap.createBitmap(
            drawable.intrinsicWidth + (**There_You_Can_Set_Your_Value**).toInt(), //dp between svg images  //* resources.displayMetrics.density
            drawable.intrinsicHeight,
            Bitmap.Config.ARGB_8888
        )
        val canvas = Canvas(bitmap)
        drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
        drawable.draw(canvas)
        return BitmapDrawable(resources, bitmap)
    }

    @Synchronized
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        if (mSampleTile != null) {
            val width = mSampleTile!!.width * numStars
            setMeasuredDimension(
                resolveSizeAndState(width, widthMeasureSpec, 0),
                measuredHeight
            )
        }
    }
}

你所添加的值将会被加到可绘制对象的宽度上,而不是内边距上。 - Rubyna Thapa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接