Android 绘制带圆角的线性布局

Android 绘制带圆角的线性布局,android,android-canvas,Android,Android Canvas,我试图实现一个LinearLayout子类,它用圆角绘制自己。根据我的研究,我设置了setWillNotDraw(false)并覆盖了onDraw()在画布中绘制一个圆角矩形: @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int sc = canvas.saveLayer(0, 0, getWidth(), getHeight(), drawPaint, Canvas.MATRIX

我试图实现一个LinearLayout子类,它用圆角绘制自己。根据我的研究,我设置了
setWillNotDraw(false)
并覆盖了
onDraw()
在画布中绘制一个圆角矩形:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    int sc = canvas.saveLayer(0, 0, getWidth(), getHeight(), drawPaint, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
            | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
    canvas.drawRoundRect(bounds, mCornerRadius, mCornerRadius, roundPaint);
    canvas.restoreToCount(sc);
}
其中:

drawPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
drawPaint.setColor(0xffffffff);
drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));

roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
roundPaint.setColor(0xffffffff);
DST_IN
在这里似乎是正确的选择(根据APIDemos示例),但是应该是透明的区域(圆形区域)有黑色背景,并且子对象的角仍然可见。这是使用Android 4.2.2的Galaxy Nexus的结果:

有什么提示吗

编辑:以下是我想要实现的目标,对不起,这是一个粗糙的photoshopping:)

编辑2:我向GitHub添加了一个示例runnable项目:

谢谢;)

那么

myLayout.setBackgroundResource(R.drawable.my_rounded_drawable);
然后

my_rounded_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <solid android:color="#FFFFFFFF" />
            <stroke android:width="1dip" android:color="#FF000000" />
            <corners android:radius="10dp" />
        </shape>
    </item>
</selector>

不太一样: Romain Guy写了一篇关于使用位图着色器在图像上裁剪角点的博客文章。。不确定是否要扩展相同的内容


与其尝试从布局中切掉角落,为什么不在其顶部放置一个可绘制的框架,作为与背景颜色匹配的框架?

我可以实现这样的圆角线性布局

步骤:

1.创建自定义布局

public class RoundedLayout extends LinearLayout {
    private RectF rect;
    private Paint paint;

    public RoundedLayout(Context context) {
        super(context);
        init();
    }
    public RoundedLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        rect = new RectF(0.0f, 0.0f, getWidth(), getHeight());
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.parseColor("#7EB5D6"));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);           
        canvas.drawRoundRect(rect, 20, 20, paint);
    }
}
2.像这样在主布局中使用它

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="#336699" >

    <com.example.rounded.RoundedLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:padding="30dp"
        android:background="@android:color/transparent" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="foo" />

    </com.example.rounded.RoundedLayout>    

</LinearLayout>

试试这个

布局:-

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout 
        android:id="@+id/linearLayout"
        android:layout_width="300dp"
        android:gravity="center"
        android:layout_height="300dp"
        android:layout_centerInParent="true"
        android:background="@drawable/rounded_edge">
        <TextView
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="foo" />
    </LinearLayout>
</RelativeLayout>

形状(可绘制):-rounded_edge.xml

<shape 
        xmlns:android="http://schemas.android.com/apk/res/android">
            <solid 
                android:color="@android:color/darker_gray">
            </solid>
            <stroke 
                 android:width="0dp" 
                 android:color="#424242">
            </stroke>
            <corners 
                 android:topLeftRadius="100dip"
                 android:topRightRadius="100dip"
                 android:bottomLeftRadius="100dip"
                 android:bottomRightRadius="100dip">
            </corners>
        </shape>

试试这个!! 摘自

将以下内容添加到文件(比如customshape.xml)中,然后将其放入(res/drawable/customshape.xml)

或者通过XML,只需将以下属性添加到容器(例如:LinearLayout或任何字段):


[编辑:看起来这将添加到L:,它允许您将视图剪裁为矩形、圆形或圆形矩形可绘制视图的形状。]

我自己尝试了很长一段时间,结果发现这是不可能的,因为View类是基于Rect类的。我刚刚检查了消息来源,从评论来看,情况仍然如此



摩托罗拉将于今年夏天晚些时候发布Moto 360(Android Wear watch with round face),因此可能会对框架进行更新,以允许使用矩形以外的形状进行查看。

已经尝试过,但不起作用,因为我使用的不是ImageView,而是布局。我甚至不确定onDraw()而不是dispatchDraw(),或者两者都是正确的重写方法。该算法将起作用。您只需获取返回的位图并使用它创建一个BitmapDrawable。然后将其设置为视图的背景。您可以发布或链接到更多代码。如果您已经准备好调试代码,这会容易得多。问题中添加了示例runnable项目。谢谢我用我想要实现的一个模型更新了这个问题:把孩子们裁剪成一个圆角矩形,所以你的答案不适用。@ventor85你需要的是Shapes@logray这就是为什么你的答案中有我的投票和一条评论,以及这个问题作者的链接,这不是一个一般的解决方案,也不适用于我的情况:舍入布局是在一个非均匀背景上的滚动视图中。你试过android:clipChildren=“true”吗据我所知,在自定义布局上,clipChildren=“false”允许子视图在容器布局的边界之外绘制自己。我想做的正好相反,就是根据给定的形状(本例中为圆角矩形)剪裁布局中的部分子对象。部分问题是由于Android绘制视图的方式。由于子项(例如按钮)是在父项(例如LinearLayout)之后绘制的,并且您无法访问子项用于绘制自身的画笔,因此我猜Xfermode帮不了什么忙。@VentalOr85,作为一种解决方法,您可以使用RelativeLayout来包裹LinearLayout并定位形状(圆弧)可在相册的四个角上画。圆角在哪里?我试过了,但是没有。我试过了,没有成功。另外,第一条注释显示了一个基于clipPath的解决方案,该解决方案要求在布局上禁用硬件加速,我希望避免这种情况。您希望避免禁用硬件加速的具体原因是什么?我认为如果没有clipPath,剪切子视图几乎是不可能的。在线性布局中添加
padding
,它与
topLeftRadius
topRightRadius
…线性布局的padding与shape corners radius完全不同。这是一个非常棒的解决方案,分享它1+。必须做出改变以反映我的需求,比如半径有点不重要
<?xml version="1.0" encoding="UTF-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
 android:shape="rectangle"> 
 <gradient 
     android:startColor="#SomeGradientBeginColor"
     android:endColor="#SomeGradientEndColor" 
     android:angle="270"/> 

<corners 
     android:bottomRightRadius="7dp" 
     android:bottomLeftRadius="7dp" 
     android:topLeftRadius="7dp" 
     android:topRightRadius="7dp"/> 
</shape> 
yourObject.setBackgroundResource(R.drawable.customshape);
android:background="@drawable/customshape"