Android 如何创建圆角视图?
我试图在android中创建一个具有圆形边缘的视图。到目前为止,我找到的解决方案是定义一个具有圆角的形状,并将其用作该视图的背景 下面是我所做的,定义一个可绘制的,如下所示:Android 如何创建圆角视图?,android,android-layout,view,android-view,android-shape,Android,Android Layout,View,Android View,Android Shape,我试图在android中创建一个具有圆形边缘的视图。到目前为止,我找到的解决方案是定义一个具有圆角的形状,并将其用作该视图的背景 下面是我所做的,定义一个可绘制的,如下所示: 现在我用它作为我的布局背景,如下所示: <LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_c
现在我用它作为我的布局背景,如下所示:
<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
放在上面的布局中时,图像的角没有被剪裁/裁剪,而是看起来满了
我已经看到了其他的解决办法,使它像一个解释
但是,有没有一种方法可以为视图及其所有视图设置圆角
子视图包含在已舍入的主视图中
角落
您提供的教程链接似乎建议您需要设置子元素的布局宽度和布局高度属性以匹配父元素
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent">
在线性布局中尝试此属性,它会有所帮助
工具:context=“.youractivity”将xml中的形状与矩形一起使用。根据需要设置底部或上部半径的属性。然后将该xml作为背景应用于您的视图…或…使用渐变从代码中执行此操作。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>
<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>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape">
...
</LinearLayout>
在Android L中,您只需使用即可获得该效果。在以前的版本中,无法仅以特定形状剪裁随机视图组的内容 你必须想出一些能给你带来类似效果的方法:
- 如果在ImageView中只需要圆角,则可以使用着色器在用作背景的形状上“绘制”图像。请看一个例子
- 如果你真的需要剪辑每个孩子,也许你可以在你的布局上再看一眼?一个背景颜色是什么你正在使用,和一个圆形'洞'在中间?实际上,您可以创建一个自定义视图组,在覆盖onDraw方法的每个子对象上绘制该形状
ImageView
。然后,你可以把它放在任何背景的容器中,你会得到你想要的效果
这也是我最终所做的。在
drawable
文件夹中创建一个名为round.xml
的xml文件,并粘贴以下内容:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#FFFFFF" />
<stroke android:width=".05dp" android:color="#d2d2d2" />
<corners android:topLeftRadius="5dp" android:topRightRadius="5dp" android:bottomRightRadius="5dp" android:bottomLeftRadius="5dp"/>
</shape>
然后将
round.xml
作为background
用于任何项目。然后,它将为您提供圆角。另一种方法是创建如下所示的自定义布局类。此布局首先将其内容绘制到屏幕外位图,用圆角矩形遮罩屏幕外位图,然后在实际画布上绘制屏幕外位图
我试过了,它似乎奏效了(至少对于我的简单测试用例是如此)。与常规布局相比,它当然会影响性能
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>
与Jaap van Hengstum的答案不同:
公共类RoundedFrameLayout扩展了FrameLayout{
私有位图mOffscreenBitmap;
克里恩卡纳斯私人帆布;
专用位图着色器mBitmapShader;
私人油漆;
私有RectF mRectF;
公共圆形框架布局(上下文){
超级(上下文);
init();
}
公共RoundedFrameLayout(上下文、属性集属性){
超级(上下文,attrs);
init();
}
公共RoundedFrameLayout(上下文上下文、属性集属性、int-defStyleAttr){
super(上下文、attrs、defStyleAttr);
init();
}
私有void init(){
setWillNotDraw(假);
}
@凌驾
公共空白绘制(画布){
if(mOffscreenBitmap==null){
mOffscreenBitmap=Bitmap.createBitmap(canvas.getWidth()、canvas.getHeight()、Bitmap.Config.ARGB_8888);
mOffscreenCanvas=新画布(mOffscreenBitmap);
mBitmapShader=新位图着色器(mOffscreenBitmap,Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
mPaint=新油漆(油漆.防油漆别名标志);
mPaint.setShader(mBitmapShader);
mRectF=newrectf(0f,0f,canvas.getWidth(),canvas.getHeight());
}
超级绘图(mOffscreenCanvas);
canvas.drawRoundRect(mRectF,8,8,mPaint);
}
}
如果在布局中添加触控监听器时出现问题。将此布局用作父布局
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);
}
}
作为
... 你的孩子到这里来了
或者您可以使用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>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="@dimen/dimen_4"
app:cardElevation="@dimen/dimen_4"
app:contentPadding="@dimen/dimen_10">
...
</androidx.cardview.widget.CardView>
效果很好,但我认为这很昂贵,例如,如果我们在按钮上应用此方法,由于视图呈现为位图,因此触摸效果将丢失
对我来说,最好也是最简单的方法是在视图上应用遮罩,如下所示:
@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);
}
@覆盖
已更改尺寸的受保护空心(int-width、int-height、int-oldWidth、int-oldHeight){
super.onSizeChanged(宽度、高度、旧宽度、旧高度);
浮动半径=;
this.path=新路径();
this.path.addRoundRect(新的RectF(0,0,宽度,高度),cornerRadius,cornerRadius,path.Direction.CW);
}
@超越
@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);
}
<android.support.v7.widget.CardView
android:id="@+id/cardView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
app:cardBackgroundColor="@color/colorPrimary">
<!-- put your content here -->
</android.support.v7.widget.CardView>
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- view background color -->
<solid
android:color="#a9c5ac" >
</solid>
<!-- view border color and width -->
<stroke
android:width="3dp"
android:color="#1c1b20" >
</stroke>
<!-- If you want to add some padding -->
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" >
</padding>
<!-- Here is the corner radius -->
<corners
android:radius="10dp" >
</corners>
</shape>
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/rounded_corner"
android:layout_centerInParent="true">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hi, This layout has rounded corner borders ..."
android:gravity="center"
android:padding="5dp"/>
</LinearLayout>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="@dimen/dimen_4"
app:cardElevation="@dimen/dimen_4"
app:contentPadding="@dimen/dimen_10">
...
</androidx.cardview.widget.CardView>
<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:background="@drawable/shape">
...
</LinearLayout>
ShapeAppearanceModel shapeAppearanceModelLL1 = new ShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED,radius16)
.build();
MaterialShapeDrawable shapeDrawableLL1 = new MaterialShapeDrawable(shapeAppearanceModeLL1);
MaterialShapeDrawable shapeDrawableLL1 = MaterialShapeDrawable.createWithElevationOverlay(this, 4.0f);
shapeDrawableLL1.setShapeAppearanceModel(shapeAppearanceModelLL1);
shapeDrawableLL1.setFillColor(
ContextCompat.getColorStateList(this,R.color...));
shapeDrawableLL1.setStrokeWidth(2.0f);
shapeDrawableLL1.setStrokeColor(
ContextCompat.getColorStateList(this,R.color...));
LinearLayout linearLayout1= findViewById(R.id.ll_1);
ViewCompat.setBackground(linearLayout1,shapeDrawableLL1);
float radius = context.getResources().getDimension(R.dimen.border_radius_hug);
shapeAppearanceModel = new ShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED,radius)
.build();
imageView.setShapeAppearanceModel(shapeAppearanceModel)
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/thumb"
android:layout_width="80dp"
android:layout_height="60dp"
app:shapeAppearanceOverlay="@style/circleImageView"
/>
<style name="circleImageView" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">10%</item>
</style>
fun setCorners() {
val mOutlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
val left = 0
val top = 0;
val right = view.width
val bottom = view.height
val cornerRadiusDP = 16f
val cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, cornerRadiusDP, resources.displayMetrics).toInt()
// all corners
outline.setRoundRect(left, top, right, bottom, cornerRadius.toFloat())
/* top corners
outline.setRoundRect(left, top, right, bottom+cornerRadius, cornerRadius.toFloat())*/
/* bottom corners
outline.setRoundRect(left, top - cornerRadius, right, bottom, cornerRadius.toFloat())*/
/* left corners
outline.setRoundRect(left, top, right + cornerRadius, bottom, cornerRadius.toFloat())*/
/* right corners
outline.setRoundRect(left - cornerRadius, top, right, bottom, cornerRadius.toFloat())*/
/* top left corner
outline.setRoundRect(left , top, right+ cornerRadius, bottom + cornerRadius, cornerRadius.toFloat())*/
/* top right corner
outline.setRoundRect(left - cornerRadius , top, right, bottom + cornerRadius, cornerRadius.toFloat())*/
/* bottom left corner
outline.setRoundRect(left, top - cornerRadius, right + cornerRadius, bottom, cornerRadius.toFloat())*/
/* bottom right corner
outline.setRoundRect(left - cornerRadius, top - cornerRadius, right, bottom, cornerRadius.toFloat())*/
}
}
myView.apply {
outlineProvider = mOutlineProvider
clipToOutline = true
}
}