圆角视图不平滑

时间:2013-12-24 09:46:29

标签: android rounded-corners android-shapedrawable

查看下面的代码。

ShapeDrawable shapeDrawable = new ShapeDrawable(new RectShape());
    shapeDrawable.getPaint().setColor(Color.parseColor("#5a2705"));
    shapeDrawable.getPaint().setStyle(Style.STROKE);
    shapeDrawable.getPaint().setAntiAlias(true);
    shapeDrawable.getPaint().setStrokeWidth(2);
    shapeDrawable.getPaint().setPathEffect(new CornerPathEffect(10));

我将此作为背景应用于LinearLayout,但边缘不平滑。我该如何解决这个问题?

以下是它的外观截图。

enter image description here

7 个答案:

答案 0 :(得分:6)

使用以编程方式创建的形状可绘制为视图背景会导致笔画宽度的外半部分被裁剪掉(原因我不知道)。仔细观察你的图像,你会发现你的笔划只有1像素宽,即使你要求2.这就是为什么角落看起来很难看。如果您尝试更大的笔划和半径(例如分别为10和40),则此效果将更加明显。

要么使用XML drawable,这似乎没有这个问题,比如Harshit Jain的答案,或者如果你必须(或者更喜欢)使用程序化解决方案,请执行以下操作。

解决方案:使用图层列表按照要剪裁的数量(笔触宽度的一半)插入矩形,如下所示:

float strokeWidth = 2;

ShapeDrawable shapeDrawable = new ShapeDrawable(new RectShape());
shapeDrawable.getPaint().setColor(Color.parseColor("#5a2705"));
shapeDrawable.getPaint().setStyle(Style.STROKE);
shapeDrawable.getPaint().setAntiAlias(true);
shapeDrawable.getPaint().setStrokeWidth(strokeWidth);
shapeDrawable.getPaint().setPathEffect(new CornerPathEffect(10));

Drawable[] layers = {shapeDrawable};
LayerDrawable layerDrawable = new LayerDrawable(layers);

int halfStrokeWidth = (int)(strokeWidth/2);
layerDrawable.setLayerInset(0, halfStrokeWidth, halfStrokeWidth, halfStrokeWidth, halfStrokeWidth);

然后使用layerDrawable作为背景。以下是上述代码结果的屏幕截图:

enter image description here

答案 1 :(得分:3)

您可以尝试使用圆角矩形的布局创建单独的xml文件。如:

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="color_here"/>
    <stroke android:width="5dp" android:color="color_here"/>
    <corners android:radius="2dp"/>
</shape>

您可以根据自己的喜好对其进行调整,并将此XML文件用作主XML中的背景。

您也可以尝试使用SDK附带的 9Patch

答案 2 :(得分:1)

为了满足这样的背景要求,我更喜欢使用9-patch drawable。 下面是创建和使用9-patch可绘制资源的指针:

  1. 开发人员文档:http://developer.android.com/tools/help/draw9patch.html

  2. 另一种解释:http://radleymarx.com/blog/simple-guide-to-9-patch/

  3. Online tool创建9补丁图片。 (注意:保存图像时将文件扩展名修改为*.9.png

答案 3 :(得分:1)

您可能需要考虑checking this

文斯

Rounded Image Views

答案 4 :(得分:1)

我以一种非常简单的方式解决了这个问题,

我一直在寻找可以通过编程方式完成的代码,而不是通过xml,

以下是代码:

GradientDrawable shape = new GradientDrawable();
    shape.setCornerRadius(10);
    shape.setColor(Color.WHITE);
    shape.setStroke(2, Color.parseColor("#996633"));

您可以这样设置:view.setBackgroundDrawable(shape);

@ Tenfour04 发布的答案也可能解决问题,但我没有尝试过。

希望它有所帮助。

答案 5 :(得分:0)

您可以尝试使用这样的选择器。此解决方案是您只需将此选择器设置为布局背景的最佳解决方案。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/white" />
    <stroke android:width="1dp" android:color="@color/grey" />
    <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" />
    <corners android:radius="15dp" />
         <gradient
          android:angle="90"
          android:startColor="@color/white"
          android:centerColor="@color/grey"
          android:endColor="@color/white"
          android:type="linear" />
</shape>

选择您自己的颜色。 干杯!

答案 6 :(得分:0)

我最近遇到了这个问题,并提出了另一种解决方案。恕我直言,最好的解决方案是创建自己的Shape实现,并使用它来创建ShapeDrawable

下面是一个圆角矩形的简单实现,它将允许您插入其边框。

class InsetRoundRectShape(
    private var radiusArray: FloatArray = floatArrayOf(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f),
    private var inset: RectF = RectF()
): RectShape() {

    private var innerRect: RectF = RectF()
    private var path: Path = Path()

    constructor(radius: Float, inset: RectF): this(floatArrayOf(radius, radius, radius, radius, radius, radius, radius, radius), inset)
    constructor(radius: Float, inset: Float): this(radius, RectF(inset, inset, inset, inset))

    init {
        if (radiusArray.size < 8) {
            throw ArrayIndexOutOfBoundsException("radius array must have >= 8 values")
        }
    }

    override fun draw(canvas: Canvas, paint: Paint) {
        canvas.drawPath(path, paint)
    }

    override fun getOutline(outline: Outline) {
        super.getOutline(outline)

        val radius = radiusArray[0]
        if(radiusArray.any { it != radius }) {
            outline.setConvexPath(path)
            return
        }

        val r = rect()
        outline.setRoundRect(ceil(r.left).toInt(), ceil(r.top).toInt(), floor(r.right).toInt(), floor(r.bottom).toInt(), radius)
    }

    override fun onResize(w: Float, h: Float) {
        super.onResize(w, h)
        val r = rect()
        path.reset()
        innerRect.set(r.left + inset.left, r.top + inset.top, r.right - inset.right, r.bottom - inset.bottom)
        if(innerRect.width() <= w && innerRect.height() <= h) {
            path.addRoundRect(innerRect, radiusArray, Path.Direction.CCW)
        }
    }

    override fun clone(): InsetRoundRectShape {
        val shape = super.clone() as InsetRoundRectShape
        shape.radiusArray = radiusArray.clone()
        shape.inset = RectF(inset)
        shape.path = Path(path)
        return shape
    }
}

像这样创建ShapeDrawable

//Inset has to be half of strokeWidth
ShapeDrawable(InsetRoundRectShape(10f, 4f)).apply {
    this.paint.color = Color.BLUE
    this.paint.style = Paint.Style.STROKE
    this.paint.strokeWidth = 8.dp
    this.invalidateSelf()
}