Oval shape clipped when created programmatically

后端 未结 5 1945
逝去的感伤
逝去的感伤 2020-12-31 21:16

I\'ve got a clipping problem.

First, I tried to display an oval shape with Xml only. I had the following code:

res/drawable/circle.xml



        
相关标签:
5条回答
  • 2020-12-31 21:52

    you should remove this:

     drawable.getPaint().setStrokeWidth(dpToPx(2));
    
    0 讨论(0)
  • 2020-12-31 21:58

    I found the solution on this page: http://www.betaful.com/2012/01/programmatic-shapes-in-android/

    In Android, when you draw with a stroke, it draws the center of the stroke at the boundaries of the shape you are drawing. As you can see, the stroke is getting cropped by the boundaries of the image. Luckily, you can perform transformations on a canvas. What we want to do is transform our stroke shape to be slightly smaller than the boundary – and there’s a Matrix operation for that!

    matrix.setRectToRect(new RectF(0, 0, canvas.getClipBounds().right, canvas.getClipBounds().bottom),
    new RectF(strokeWidth/2, strokeWidth/2, canvas.getClipBounds().right - strokeWidth/2,
        canvas.getClipBounds().bottom - strokeWidth/2),
    Matrix.ScaleToFit.FILL);
    

    Edit

    ... Better and easier solution find in the comment section of the link:

    As you can see in the Android docs, a shape Drawable in resources is actually mapped to a GradientDrawable, not a ShapeDrawable:

    And so, I've got the following code working perfectly:

    GradientDrawable drawable = new GradientDrawable();
    drawable.setColor(Color.TRANSPARENT);
    drawable.setShape(GradientDrawable.OVAL);
    drawable.setStroke((int)dpToPx(2), Color.parseColor("#EEEEEE"));
    drawable.setSize((int)dpToPx(240), (int)dpToPx(240));
    
    0 讨论(0)
  • 2020-12-31 22:02

    You use setIntrinsicHeight, try to set it to your Height/With - strokeWidth, so in this case set Width and Height to 238.

    0 讨论(0)
  • 2020-12-31 22:09

    I experienced the same exact issue. This probably happens because of a bug in Android. The solution is to set the parent View's padding to some value, then set it back to the desired value at some point in the future.

    // set stroke properties programmatically
    viewWithStroke.background
            .let {it as GradientDrawable}
            .setStroke(newBorderThickness,newBorderColor)
    
    // set padding to some value now, then to the desired value later as a
    // work-around for the weird android bug where strokes get clipped because
    // android is not refreshing the view layouts properly
    val parentOfViewWithStroke = viewWithStroke.parent.let {it as ViewGroup}
    parentOfViewWithStroke.setPadding(
            newBorderPadding+1,newBorderPadding+1,
            newBorderPadding+1,newBorderPadding+1)
    viewWithStroke.post()
    {
        parentOfViewWithStroke.setPadding(
                newBorderPadding,newBorderPadding,
                newBorderPadding,newBorderPadding)
    }
    

    P.S.: I tried using View.invalidate() and View.requestLayout() but could not get it to work.

    0 讨论(0)
  • 2020-12-31 22:12

    I had the same clipping issue and this simple configuration gave me the appearance I needed without any clipping:

    redring.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="oval" >
        <solid android:color="@android:color/transparent" />
        <stroke
            android:width="2dp"
            android:color="#ff00" />
    </shape>
    

    usage:

    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@drawable/redring" />
    
    0 讨论(0)
提交回复
热议问题