如何在带有圆angular的android中查看视图

我正在尝试使用圆angular边缘在Android中的视图。 我目前find的解决scheme是定义一个圆angular的形状,并将其用作该视图的背景。

这是我做的,定义一个drawable如下所示

<padding android:top="2dp" android:bottom="2dp"/> <corners android:bottomRightRadius="20dp" android:bottomLeftRadius="20dp" android:topLeftRadius="20dp" android:topRightRadius="20dp"/> 

现在我用这个作为我的布局的背景如下

 <LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginBottom="10dp" android:clipChildren="true" android:background="@drawable/rounded_corner"> 

这工作非常好,我可以看到,视图圆润的边缘。

但是我的布局在其中有很多其他的子视图说一个ImageView或一个MapView。 当我在上面的布局中放置一个ImageView时,图像的angular落不会被剪切/裁剪,而会显得满了。

我已经看到了其他的解决方法,使它像这里解释的工作。

但有没有一种方法来设置一个视图的圆angular,所有的子视图都包含在那个圆angular的主视图中?

谢谢。

另一种方法是制作一个如下所示的自定义布局类。 此布局首先将其内容绘制到离屏位图,用圆angular矩形遮罩离屏位图,然后在实际canvas上绘制离屏位图。

我试了一下,似乎工作(至less对于我简单的testing用例)。 这当然会影响性能比较正常的布局。

 package com.example; import android.content.Context; import android.graphics.*; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; import android.widget.FrameLayout; public class RoundedCornerLayout extends FrameLayout { private final static float CORNER_RADIUS = 40.0f; private Bitmap maskBitmap; private Paint paint, maskPaint; private float cornerRadius; public RoundedCornerLayout(Context context) { super(context); init(context, null, 0); } public RoundedCornerLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } private void init(Context context, AttributeSet attrs, int defStyle) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics); paint = new Paint(Paint.ANTI_ALIAS_FLAG); maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); setWillNotDraw(false); } @Override public void draw(Canvas canvas) { Bitmap offscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888); Canvas offscreenCanvas = new Canvas(offscreenBitmap); super.draw(offscreenCanvas); if (maskBitmap == null) { maskBitmap = createMask(canvas.getWidth(), canvas.getHeight()); } offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint); canvas.drawBitmap(offscreenBitmap, 0f, 0f, paint); } private Bitmap createMask(int width, int height) { Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8); Canvas canvas = new Canvas(mask); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.WHITE); canvas.drawRect(0, 0, width, height, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint); return mask; } } 

使用这个像一个正常的布局:

 <com.example.RoundedCornerLayout android:layout_width="200dp" android:layout_height="200dp"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/test"/> <View android:layout_width="match_parent" android:layout_height="100dp" android:background="#ff0000" /> </com.example.RoundedCornerLayout> 

shape.xml

 <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="#f6eef1" /> <stroke android:width="2dp" android:color="#000000" /> <padding android:bottom="5dp" android:left="5dp" android:right="5dp" android:top="5dp" /> <corners android:radius="5dp" /> </shape> 

并在你的布局

 <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginBottom="10dp" android:clipChildren="true" android:background="@drawable/shape"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/your image" android:background="@drawable/shape"> </LinearLayout> 

或者你可以像这样使用android.support.v7.widget.CardView

 <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" card_view:cardBackgroundColor="@color/white" card_view:cardCornerRadius="4dp"> <!--YOUR CONTENT--> </android.support.v7.widget.CardView> 

如果将触摸侦听器添加到布局时遇到问题。 使用此布局作为父布局。

 import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.graphics.Region; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.View; import android.widget.FrameLayout; public class RoundedCornerLayout extends FrameLayout { private final static float CORNER_RADIUS = 6.0f; private float cornerRadius; public RoundedCornerLayout(Context context) { super(context); init(context, null, 0); } public RoundedCornerLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } private void init(Context context, AttributeSet attrs, int defStyle) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics); setLayerType(View.LAYER_TYPE_SOFTWARE, null); } @Override protected void dispatchDraw(Canvas canvas) { int count = canvas.save(); final Path path = new Path(); path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), cornerRadius, cornerRadius, Path.Direction.CW); canvas.clipPath(path, Region.Op.REPLACE); canvas.clipPath(path); super.dispatchDraw(canvas); canvas.restoreToCount(count); } } 

 <?xml version="1.0" encoding="utf-8"?> <com.example.view.RoundedCornerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:id="@+id/patentItem" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingRight="20dp"> ... your child goes here </RelativeLayout> </com.example.view.RoundedCornerLayout> 

在drawable文件夹中创build一个xml round.xml

 <solid android:color="#FFFFFF" /> <stroke android:width=".05dp" android:color="#d2d2d2" /> <corners android:topLeftRadius="5dp" android:topRightRadius="5dp" android:bottomLeftRadius="5dp" android:bottomRightRadius="5dp" /> 

然后使用round.xml作为项目的背景..然后它会给圆angular

在Android L中,您将只能使用View.setClipToOutline来获得该效果。 在以前的版本中,没有办法只将某个随机ViewGroup的内容剪切成某种形状。

你将不得不想一些会给你类似的效果:

  • 如果您只需要在ImageView中使用圆angular,则可以使用着色器将图像“绘制”为所用形状的背景。 看看这个图书馆的例子。

  • 如果你真的需要每一个孩子被剪裁,也许你可以在你的布局另一个视图? 一个有你使用的任何颜色的背景,还有一个中间的圆形“洞”? 实际上你可以创build一个自定义的ViewGroup,在每个孩子上覆盖onDraw方法来绘制这个形状。

Jaap van Hengstum的回答很好,但是我认为它很昂贵,如果我们在Button上应用这个方法,触摸效果就会丢失,因为视图是以位图的forms呈现的。

对我来说,最好的方法和最简单的方法就是在视图上应用一个遮罩,就像这样:

 @Override protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { super.onSizeChanged(width, height, oldWidth, oldHeight); float cornerRadius = <whatever_you_want>; this.path = new Path(); this.path.addRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, Path.Direction.CW); } @Override protected void dispatchDraw(Canvas canvas) { if (this.path != null) { canvas.clipPath(this.path); } super.dispatchDraw(canvas); } 

您提供的教程链接似乎暗示您需要将您的子元素的layout_width和layout_height属性设置为match_parent。

 <ImageView android:layout_width="match_parent" android:layout_height="match_parent"> 

尝试这个属性与你的线性布局,这将有助于
工具:“youractivity”上下文=

请按照本教程及其下面的所有讨论http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/

根据Guy Romain写的这篇文章,他是整个Android UI工具包的主要开发人员之一,可以制作一个圆angular的容器(以及他的所有子视图),但是他解释说它太昂贵了(从表演渲染问题)。

我会build议你去根据他的职位,如果你想要圆angular,然后根据这个职位实现圆angular的ImageView 。 那么,你可以把它放在一个有任何背景的容器里面,你会得到你想要的效果。

这也是我最终也做的。

与Jaap van Hengstum的回答不同:

  1. 使用BitmapShader而不是掩码位图。
  2. 只创build一次位图。
 public class RoundedFrameLayout extends FrameLayout { private Bitmap mOffscreenBitmap; private Canvas mOffscreenCanvas; private BitmapShader mBitmapShader; private Paint mPaint; private RectF mRectF; public RoundedFrameLayout(Context context) { super(context); init(); } public RoundedFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); init(); } public RoundedFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { setWillNotDraw(false); } @Override public void draw(Canvas canvas) { if (mOffscreenBitmap == null) { mOffscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888); mOffscreenCanvas = new Canvas(mOffscreenBitmap); mBitmapShader = new BitmapShader(mOffscreenBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setShader(mBitmapShader); mRectF = new RectF(0f, 0f, canvas.getWidth(), canvas.getHeight()); } super.draw(mOffscreenCanvas); canvas.drawRoundRect(mRectF, 8, 8, mPaint); } } 
 public class RoundedCornerLayout extends FrameLayout { private double mCornerRadius; public RoundedCornerLayout(Context context) { this(context, null, 0); } public RoundedCornerLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } private void init(Context context, AttributeSet attrs, int defStyle) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); setLayerType(View.LAYER_TYPE_SOFTWARE, null); } public double getCornerRadius() { return mCornerRadius; } public void setCornerRadius(double cornerRadius) { mCornerRadius = cornerRadius; } @Override public void draw(Canvas canvas) { int count = canvas.save(); final Path path = new Path(); path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), (float) mCornerRadius, (float) mCornerRadius, Path.Direction.CW); canvas.clipPath(path, Region.Op.REPLACE); canvas.clipPath(path); super.draw(canvas); canvas.restoreToCount(count); } } 
 public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) { Bitmap roundedBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap .getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(roundedBitmap); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(rect); final float roundPx = pixels; paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return roundedBitmap; } 

使用矩形的xml中的形状。将底部或上半径的属性设置为want.then将该xml作为背景应用于您的视图….或…使用梯度从代码执行。