以编程方式创建时剪裁椭圆形状

时间:2013-09-09 07:52:12

标签: android

我遇到了裁剪问题。

首先,我尝试仅显示带有Xml的椭圆形状。我有以下代码:

RES /抽拉/ circle.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval" >
    <size
        android:width="240dp"
        android:height="240dp" />
    <solid
        android:color="#FFFFFF" />
    <stroke
        android:width="2dp"
        android:color="#EEEEEE" />
</shape>    

* RES /布局/的test.xml

....
<RelativeLayout
    android:id="@+id/circle_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1" >

    <ImageView
        android:src="@drawable/circle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" />

</RelativeLayout>
....

它完美无缺,并且给了我:Screenshot

问题是,出于各种原因,我必须以程序方式进行相同的操作。

我有这段代码:

RelativeLayout layout = (RelativeLayout) findViewById(R.id.circle_layout);

ShapeDrawable drawable = new ShapeDrawable(new OvalShape());
drawable.getPaint().setColor(Color.parseColor("#EEEEEE"));
drawable.getPaint().setStyle(Style.STROKE);
drawable.getPaint().setStrokeWidth(dpToPx(2));
drawable.getPaint().setAntiAlias(true);
drawable.setIntrinsicHeight(dpToPx(240));
drawable.setIntrinsicWidth(dpToPx(240));

ImageView iv = new ImageView(this);
iv.setImageDrawable(drawable);

RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
iv.setLayoutParams(lp);

layout.addView(iv);

dpToPx功能是:

private float scale = 0;

private float getScale() {
    if (scale == 0)
        scale  = this.getResources().getDisplayMetrics().densityDpi / 160f;
    return scale;
}

public float dpToPx(float dp) {
    return dp * getScale();
}

......这应该给我同样的东西吧?好吧,它给了一个略大的圆圈,顶部,右侧,底部和左侧边缘被修剪。这是一个屏幕截图(屏幕的区域与前一个区域相同):Screehshot

有人知道什么和为什么?

谢谢。

修改

如果我将行程宽度设置为更高的值(12dp),我就得到了这个:Screenshot

5 个答案:

答案 0 :(得分:22)

我在此页面上找到了解决方案:http://www.betaful.com/2012/01/programmatic-shapes-in-android/

在Android中,当您使用笔划绘制时,它会在您绘制的形状的边界处绘制笔划的中心。如您所见,笔划会被图像的边界裁剪掉。幸运的是,您可以在画布上执行转换。我们想要做的是将我们的笔触形状转换为略小于边界 - 并且有一个Matrix操作!

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);

修改

...在链接的评论部分找到更好,更简单的解决方案:

正如您在Android文档中看到的那样,资源中的Drawable实际上映射到GradientDrawable,而不是ShapeDrawable:

所以,我已经完成了以下代码:

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));

答案 1 :(得分:0)

您使用setIntrinsicHeight,尝试将其设置为Height / With - strokeWidth,因此在这种情况下将Width和Height设置为238。

答案 2 :(得分:0)

你应该删除它:

 drawable.getPaint().setStrokeWidth(dpToPx(2));

答案 3 :(得分:0)

我遇到了同样的问题。这可能是由于Android中的错误引起的。解决方案是将父View的填充设置为某个值,然后在将来某个时候将其重新设置为所需的值。

// 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 .:我尝试使用View.invalidate()View.requestLayout(),但无法正常工作。

答案 4 :(得分:-1)

我有同样的裁剪问题,这个简单的配置给了我所需的外观,没有任何裁剪:

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>

用法:

<View
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:background="@drawable/redring" />