一.遇到的问题

最近在开发中会遇到Android布局切圆角的需求,大多数是对一个layout布局切下圆角。这里和图片切圆角有一些雷同的地方,可以相互借鉴,但是也不全一样。图片切圆角的一些总结和实践准备下次有空再写出来。

假设我们要对一种LinearLayout布局切圆角,不知道你能想出来哪些办法。我这里先提供下我的思路,亲自实践过的主要包括下面五种:

   1.利用xml背景文件配置shape属性实现切圆角

   2.利用GradientDrawable实现切圆角

   3.利用clipPath实现切圆角

   4.利用CardView实现切圆角

    5.利用ViewOutlineProvider实现切圆角

下面分别对这几种方式进行实践与优缺点分析,原理讲解较少,感兴趣可以自己再深入了解下。

二.利用xml背景文件配置shape属性实现

2.1方案实现

    这种方式相比大家都比较熟悉了,就是在drawable文件夹下新建一个App Action XML File,然后作为background属性添加到Layout XML File中。

如果要生成四个角都为10dp圆角的形状我们可以在drawable文件夹下新建如下shape_10dp_corners.xml文件

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><corners android:radius="10dp" /><solid android:color="@color/colorAccent" />
</shape>

如果仅要生成上方两个10dp圆角的形状我们可以在drawable文件夹下新建如下shape_10dp_top_corners.xml文件

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><solid android:color="@color/colorPrimary"/><cornersandroid:topLeftRadius="10dp"android:topRightRadius="10dp" />
</shape>

如果仅要生成上方两个10dp圆角的形状我们可以在drawable文件夹下新建如下shape_10dp_bottom_right_corners.xml文件

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><corners android:bottomRightRadius="10dp"/><solid android:color="@color/colorAccent"/>
</shape>

然后在XmlShapeActivity的布局XML文件中为对应的三个LinearLayout分别设置background属性如下

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".xmlshape.XmlShapeActivity"><LinearLayoutandroid:id="@+id/lly1"android:layout_width="0dp"android:layout_height="100dp"android:layout_marginStart="16dp"android:layout_marginLeft="16dp"android:layout_marginTop="16dp"android:layout_marginEnd="16dp"android:layout_marginRight="16dp"android:background="@drawable/shape_10dp_corners"android:orientation="vertical"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="四个圆角10dp"android:textSize="24sp"android:textColor="#FFFFFF" /></LinearLayout><LinearLayoutandroid:id="@+id/lly2"android:layout_width="0dp"android:layout_height="100dp"android:layout_marginStart="16dp"android:layout_marginLeft="16dp"android:layout_marginTop="16dp"android:layout_marginEnd="16dp"android:layout_marginRight="16dp"android:background="@drawable/shape_10dp_top_corners"android:orientation="vertical"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/lly1" ><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="上方圆角10dp"android:textSize="24sp"android:textColor="#FFFFFF"/></LinearLayout><LinearLayoutandroid:id="@+id/lly3"android:layout_width="0dp"android:layout_height="100dp"android:layout_marginStart="16dp"android:layout_marginLeft="16dp"android:layout_marginTop="16dp"android:layout_marginEnd="16dp"android:layout_marginRight="16dp"android:background="@drawable/shape_10dp_bottom_right_corners"android:orientation="vertical"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/lly2" ><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="右下圆角10dp"android:textSize="24sp"android:textColor="#FFFFFF"/></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

然后勉为其难地贴一下打酱油的XmlShapeActivity代码

package com.openld.roundcornerdemmo.xmlshape;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import com.openld.roundcornerdemmo.R;public class XmlShapeActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_xml_shape);}
}

2.1运行效果

2.3优缺点

优点:

1.最简单

2.四个圆角可以单独定制,也可以统一处理

3.还可以一并设置背景颜色等属性

4.圆角无锯齿

缺点:

1.圆角属性是提前确定的并写在客户端本地的drawable中,如果是动态下发再去配置的话这种方式无法支持。

2.如果子View长宽都match_parent并且设置一个有色background属性的话,圆角就消失了。

三.利用GradientDrawable实现切圆角

3.1 方案实现

有没有想过动态地在Java代码中为layout设置圆角,那就想到了GradientDrawable。其实是和第一种XML方式呼应的,只不过没有办法让你你动态去配置XML,那就用GradientDrawable吧,XML shape中能设置的属性这里也能哦!

这里先贴一下GradientDrawableActivity的布局XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".gradientdrawable.GradientDrawableActivity"><LinearLayoutandroid:id="@+id/lly1"android:layout_width="0dp"android:layout_height="100dp"android:layout_marginStart="16dp"android:layout_marginLeft="16dp"android:layout_marginTop="16dp"android:layout_marginEnd="16dp"android:layout_marginRight="16dp"android:orientation="vertical"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="四个圆角10dp"android:textSize="24sp" /></LinearLayout><LinearLayoutandroid:id="@+id/lly2"android:layout_width="0dp"android:layout_height="100dp"android:layout_marginStart="16dp"android:layout_marginLeft="16dp"android:layout_marginTop="16dp"android:layout_marginEnd="16dp"android:layout_marginRight="16dp"android:orientation="vertical"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/lly1"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="左边两个10dp圆角"android:textSize="24sp" /></LinearLayout><LinearLayoutandroid:id="@+id/lly3"android:layout_width="0dp"android:layout_height="100dp"android:layout_marginStart="16dp"android:layout_marginLeft="16dp"android:layout_marginTop="16dp"android:layout_marginEnd="16dp"android:layout_marginRight="16dp"android:orientation="vertical"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/lly2"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="左上角10dp圆角"android:textSize="24sp" /></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

再贴一下GradientDrawableActivity的代码

package com.openld.roundcornerdemmo.gradientdrawable;import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.widget.LinearLayout;import androidx.appcompat.app.AppCompatActivity;import com.openld.roundcornerdemmo.R;
import com.openld.roundcornerdemmo.utils.DisplayUtils;public class GradientDrawableActivity extends AppCompatActivity {private LinearLayout mLly1;private LinearLayout mLly2;private LinearLayout mLly3;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_gradient_drawable);initWidgets();}private void initWidgets() {mLly1 = findViewById(R.id.lly1);GradientDrawable gradientDrawable1 = new GradientDrawable();gradientDrawable1.setShape(GradientDrawable.RECTANGLE);gradientDrawable1.setCornerRadius(DisplayUtils.dp2px(this, 10F));gradientDrawable1.setColor(getResources().getColor(R.color.colorPrimary));mLly1.setBackground(gradientDrawable1);mLly2 = findViewById(R.id.lly2);GradientDrawable gradientDrawable2 = new GradientDrawable();gradientDrawable2.setShape(GradientDrawable.RECTANGLE);gradientDrawable2.setColor(getResources().getColor(R.color.colorAccent));float[] radii = new float[]{DisplayUtils.dp2px(this, 10F), DisplayUtils.dp2px(this, 10F),0F, 0F,0F, 0F,DisplayUtils.dp2px(this, 10F), DisplayUtils.dp2px(this, 10F)};gradientDrawable2.setCornerRadii(radii);mLly2.setBackground(gradientDrawable2);mLly3 = findViewById(R.id.lly3);GradientDrawable gradientDrawable3 = new GradientDrawable();gradientDrawable3.setShape(GradientDrawable.RECTANGLE);gradientDrawable3.setColor(getResources().getColor(R.color.colorPrimary));float[] radii1 = new float[]{DisplayUtils.dp2px(this, 10F), DisplayUtils.dp2px(this, 10F),0F, 0F,0F, 0F,0F, 0F};gradientDrawable3.setCornerRadii(radii1);mLly3.setBackground(gradientDrawable3);}
}

核心代码都在initWidgets()方法中,里面实例化一个GradientDrawable对象,设置一下对应的属性。setCornerRadii()或者se'tCornerRadius()方法即为设置圆角,具体可以看下API,这里不再赘述。

3.2 运行效果

3.3 优缺点

优点:

1.支持动态配置啊

2.四个圆角可以单独定制,也可以统一处理

3.还可以一并设置背景颜色等属性

4.圆角无锯齿

缺点

1.如果子View长宽都match_parent并且设置一个有色background属性的话,圆角就消失了。

四. 利用clipPath实现切圆角

4.1 方案实现

继承现有的布局,在draw()方法中使用clipPath()方法切割你想要的形状,只要切割出一个圆角矩形即可。

比如新建一个继承LinearLayout的CornersLinearLayout

package com.openld.roundcornerdemmo.clippath;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.LinearLayout;import androidx.annotation.Nullable;import com.openld.roundcornerdemmo.R;/*** author: lllddd* created on: 2020/6/9 10:55* description:*/
public class CornersLinearLayout extends LinearLayout {private Context mContext;private float mCorners;private float mLeftTopCorner;private float mRightTopCorner;private float mLeftBottomCorner;private float mRightBottomCorner;private int mWidth;private int mHeight;public CornersLinearLayout(Context context) {this(context, null);}public CornersLinearLayout(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public CornersLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mContext = context;TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CornersLinearLayout);mCorners = typedArray.getDimension(R.styleable.CornersLinearLayout_corner, 0F);mLeftTopCorner = typedArray.getDimension(R.styleable.CornersLinearLayout_leftTopCorner, 0F);mRightTopCorner = typedArray.getDimension(R.styleable.CornersLinearLayout_rightTopCorner, 0F);mRightBottomCorner = typedArray.getDimension(R.styleable.CornersLinearLayout_rightBottomCorner, 0F);mLeftBottomCorner = typedArray.getDimension(R.styleable.CornersLinearLayout_leftBottomCorner, 0F);typedArray.recycle();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mWidth = getMeasuredWidth();mHeight = getMeasuredHeight();setMeasuredDimension(mWidth, mHeight);}@Overridepublic void draw(Canvas canvas) {canvas.save();Path path = new Path();RectF rectF = new RectF(0, 0, mWidth, mHeight);if (mCorners > 0F) {path.addRoundRect(rectF, mCorners, mCorners, Path.Direction.CCW);} else {float[] radii = new float[]{mLeftTopCorner, mLeftTopCorner,mRightTopCorner, mRightTopCorner,mRightBottomCorner, mRightBottomCorner,mLeftBottomCorner, mLeftBottomCorner};path.addRoundRect(rectF, radii, Path.Direction.CCW);}canvas.clipPath(path);super.draw(canvas);}
}

相关的属性声明在style.xml文件中配置,这里不涉及。draw()方法是在onDraw()之前的一个方法,在这里可以使用clipPath()裁剪出一个圆角矩形轮廓。调用canvas.clipPath(path)生效,之后再执行super方法即可。

4.2 运行效果

4.3 优缺点

优点:

1.整个外层轮廓都切成圆角矩形,子View的background不会影响到圆角

2.四个角可以单独配置也可以统一配置

缺点:

1.无法抗锯齿,在一些老的手机上面效果可能差强人意

2.需要实现自己的自定义布局

五.利用CardView实现切圆角

5.1 方案实现

CardView是v7包中的组件(ViewGroup),主要用来设置布局的边框为圆角、z轴的偏移量(这个是5.0以后才有的概念,也就是阴影的效果)。这里我们仅仅使用圆角功能。

实现一个带CardView的布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".cardview.CardViewActivity"><androidx.cardview.widget.CardViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginStart="16dp"android:layout_marginLeft="16dp"android:layout_marginTop="16dp"android:layout_marginEnd="16dp"android:layout_marginRight="16dp"android:layout_marginBottom="16dp"app:cardBackgroundColor="@color/colorAccent"app:cardCornerRadius="10dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="10dp的圆角"android:textColor="#FFFFFF"android:textSize="24sp" /></androidx.cardview.widget.CardView></androidx.constraintlayout.widget.ConstraintLayout>

对应activity的代码就没必要贴了,XML布局中

app:cardCornerRadius="10dp"

即配置四个角为10dp的圆角

5.2 运行效果

5.3 优缺点

优点:

1.Google的控件,效果和稳定性都是杠杠的,还支持阴影等其他的配置

2.抗锯齿

缺点:

1.四个角要一起配置,不支持其中若干个角单独配置

2.使用时外层要嵌套CardView

六.利用ViewOutlineProvider实现切圆角

6.1 方案实现

利用ViewOutlineProvider设置轮廓切圆角。

对应ViewOutlineProviderActivity的布局XML如下

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".viewoutlineprovider.ViewOutlineProviderActivity"><LinearLayoutandroid:id="@+id/lly"android:layout_width="0dp"android:layout_height="0dp"android:layout_marginStart="16dp"android:layout_marginLeft="16dp"android:layout_marginTop="16dp"android:layout_marginEnd="16dp"android:layout_marginRight="16dp"android:layout_marginBottom="16dp"android:orientation="vertical"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"android:background="@color/colorAccent"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="10dp的圆角"android:textSize="24sp" /></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

ViewOutlineProviderActivity代码如下

package com.openld.roundcornerdemmo.viewoutlineprovider;import android.graphics.Outline;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.widget.LinearLayout;import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;import com.openld.roundcornerdemmo.R;
import com.openld.roundcornerdemmo.utils.DisplayUtils;public class ViewOutlineProviderActivity extends AppCompatActivity {private LinearLayout mLly;@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_view_outline_provider);initWidgets();}@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)private void initWidgets() {mLly = findViewById(R.id.lly);mLly.setOutlineProvider(new ViewOutlineProvider() {@Overridepublic void getOutline(View view, Outline outline) {outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), DisplayUtils.dp2px(ViewOutlineProviderActivity.this, 10F));}});mLly.setClipToOutline(true);}
}

关键就是mLly.setOutlineProvider()与mLly.setClipToOutline()两个方法的使用。

6.2 运行效果

6.3 优缺点

优点:

1.支持动态下发与配置

缺点:

1.只能四个角同时配置不支持每个角单独配置

七.源码位置

链接地址

Android 布局圆角方案总结相关推荐

  1. android布局优化方案,Android启动优化-布局优化

    Android启动优化-布局优化 安卓应用开发发展到今天,已经成为一个非常成熟的技术方向,从目前的情况看,安卓开发还是一个热火朝天的发展,但高级人才却相对较少,如今移动互联网的开发者也逐渐开始注重插入 ...

  2. android 屏幕圆角,Android通用圆角布局(兼容Android P)

    Android通用圆角布局(兼容Android P) Android通用圆角布局,可以解决Android P版本xfermode方案裁剪黑边问题和xfermode在列表view中使用滑动时EGL内存泄 ...

  3. android 布局加圆角,Android通用圆角布局

    名称 rclayout 语言 Android 平台 GitHub 作者 GcsSloop 该布局是一个可以任意设定布局圆角的大小,宽度,颜色等.可满足基于的开发工作中遇到的圆角布局需求. 效果图 效果 ...

  4. android布局的作用,Android UI布局经验总结

    如何在Android中动态设置颜色透明?10%20%到100% Android布局分析工具HierarchyView Android使用include/merge/ViewStub优化布局 List的 ...

  5. android屏幕适配教程,Android屏幕适配方案,android屏幕适配

    Android屏幕适配方案,android屏幕适配 文章转载禁止用于商业用途,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处莫高雷草原以及作者@JiongBull. Android屏幕适配方 ...

  6. android 布局适配虚拟键适配

    今天,看到关于虚拟键盘的内容,于是记录一下. 如果是控件,可以直接使用Android:fitsSystemWindows="true"),但是如果是popwindow,那就必须获取 ...

  7. Android布局加载慢,Android布局优化(四)X2C — 提升布局加载速度200%

    系列文章 前言 在Android布局优化(一)从布局加载原理说起中我们说到了布局加载的两大性能瓶颈,通过IO操作将XML加载到内存中并进行解析和通过反射创建View.这里介绍一种避免运行时通过IO操作 ...

  8. 2021年最详细的Android屏幕适配方案汇总

    1 Android屏幕适配的度量单位和相关概念 建议在阅读本文章之前,可以先阅读快乐李同学写的文章<Android屏幕适配的度量单位和相关概念>,这篇文章包含了阅读本文的一些基础知识,推荐 ...

  9. android imageview 锯齿,[置顶] android 自定义圆角ImageView以及锯齿的处理

    看到很多人开发过程中要使用圆角图片时,解决方法有: 1.重新绘制一张图片 2.通过布局来配置 3.通过重写View来实现 其中1,2在这里就不讲了,重点讲讲方法三的实现. 实现一:通过截取画布一个圆形 ...

最新文章

  1. 69亿美元英伟达史上最大收购!这家基金又赢了
  2. 一个检查分区内存并且发送邮件的shell脚本
  3. Juce源代码分析(一)Juce的优势
  4. zabbix专题:第三章 Zabbix Agent客户端安装详解
  5. git 理解 HEAD^与HEAD~
  6. 腾讯技术运营岗实习面试面经
  7. Session 的几种存储方式及优缺点
  8. RequireJS进阶(一)
  9. 51nod1183编辑距离----DP--字符串最小变化
  10. 由数字规律谈历史的前定
  11. 【电机学复习笔记】第二章 变压器
  12. 从青铜到王者的路线,javasocket编程聊天室
  13. linux更新字体库失败,wps for linux 字体库缺失问题的解决办法
  14. class 文件比较
  15. 计算机出错英语翻译,计算机各种错误信息翻译
  16. 使用代理爬去微信公众号_使用代理处理反爬抓取微信文章
  17. Debian 安装手记
  18. 使用Psycopg2连接openGauss 3.0(python3)
  19. Django富文本编辑——Ckeditor的配置、使用和踩坑(应该全)
  20. 安卓手机查看充放电电压、电流及功率

热门文章

  1. 计算机应用基础课程作业2016,2016浙大远程教育计算机应用基础作业
  2. PDF编辑器哪个好用,怎么在PDF上修改文字
  3. 银行也想拥抱区块链,但发现实在太难了
  4. 初试401 英语86分上岸苏州大学经验分享
  5. Word图表的中英题注及引用
  6. Burpsuite的基本使用介绍
  7. 【建议搜藏】Spring+SpringMVC+MyBatis简易版Boss直聘系统
  8. chrome浏览器中使用adblockplus拦截广告
  9. 1.1.2 Linux epoll详解
  10. 瘫痪患者借助脑机接口可进行数字绘画