qidao123.com技术社区-IT企服评测·应用市场
标题:
Android View设置圆角方式大全
[打印本页]
作者:
反转基因福娃
时间:
2025-5-9 06:28
标题:
Android View设置圆角方式大全
一、弁言
在 Android 开发中,圆角筹划是提升界面美观度和用户体验的重要手段。从简朴的按钮到复杂的布局容器,圆角可以让界面元素显得更加柔和、现代。本文将全面梳理 Android View 设置圆角的全部方式,涵盖 XML 设置、代码动态实现、自定义绘制、第三方库等多个维度,并联合源码深入分析其原理,同时给出性能优化的最佳实践。
二、XML 布局文件设置圆角
2.1 使用 ShapeDrawable
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 圆角半径,这里统一设置四个角的圆角半径为 16dp -->
<corners android:radius="16dp"/>
<!-- 设置填充颜色为粉色 -->
<solid android:color="#FF4081"/>
<!-- 设置边框,宽度为 2dp,颜色为黄色 -->
<stroke
android:width="2dp"
android:color="#FFEB3B"/>
<!-- 设置内边距,上下为 8dp,左右为 16dp -->
<padding
android:top="8dp"
android:bottom="8dp"
android:left="16dp"
android:right="16dp"/>
</shape>
复制代码
原理分析
ShapeDrawable 类
:ShapeDrawable 是 Android 中用于绘制简朴形状的 Drawable 子类。当在 XML 中定义 shape 标签时,体系会根据标签内的属性创建一个 ShapeDrawable 对象。
Corners 标签
:corners 标签用于设置圆角属性。在 ShapeDrawable 内部,这些属性会被分析并应用到形状的绘制过程中。当绘制矩形时,会根据设置的圆角半径对矩形的四个角进行圆角处理。
Solid 标签
:solid 标签用于设置形状的填充颜色。在 ShapeDrawable 绘制时,会使用该颜色填充整个形状区域。
Stroke 标签
:stroke 标签用于设置形状的边框。它包含边框的宽度和颜色属性,在绘制时会在形状的边沿绘制指定宽度和颜色的边框。
Padding 标签
:padding 标签用于设置形状内部的填充区域与边界的隔断。在 ShapeDrawable 应用到 View 时,会影响 View 内部内容的布局。
2.2 使用 GradientDrawable
<gradient
xmlns:android="http://schemas.android.com/apk/res/android"
android:type="linear"
<!-- 设置渐变的起始颜色为粉色 -->
android:startColor="#FF4081"
<!-- 设置渐变的结束颜色为蓝色 -->
android:endColor="#2196F3"
<!-- 设置渐变的角度为 45 度 -->
android:angle="45">
<!-- 设置圆角半径为 24dp -->
<corners android:radius="24dp"/>
</gradient>
复制代码
原理分析
GradientDrawable 类
:GradientDrawable 是 Drawable 的子类,用于绘制渐变效果的形状。当在 XML 中定义 gradient 标签时,体系会创建一个 GradientDrawable 对象。
Type 属性
:android:type 属性指定渐变的范例,这里设置为 linear 表示线性渐变。GradientDrawable 会根据该属性选择不同的渐变算法进行绘制。
StartColor 和 EndColor 属性
:android:startColor 和 android:endColor 分别指定渐变的起始颜色和结束颜色。在绘制时,GradientDrawable 会根据渐变范例和角度在形状内部绘制颜色渐变效果。
Angle 属性
:android:angle 属性用于设置线性渐变的角度。它决定了渐变的方向,比方 45 度表示从左上角到右下角的渐变方向。
Corners 标签
:与 ShapeDrawable 中的 corners 标签类似,用于设置圆角半径。在 GradientDrawable 绘制时,会对形状的四个角进行圆角处理。
2.3 使用 LayerDrawable
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 第一个图层 -->
<item>
<shape android:shape="rectangle">
<!-- 设置圆角半径为 20dp -->
<corners android:radius="20dp"/>
<!-- 设置填充颜色为白色 -->
<solid android:color="#FFFFFF"/>
</shape>
</item>
<!-- 第二个图层,相对于第一个图层向下和向右偏移 2dp -->
<item android:bottom="2dp" android:right="2dp">
<shape android:shape="rectangle">
<!-- 设置圆角半径为 20dp -->
<corners android:radius="20dp"/>
<!-- 设置填充颜色为浅灰色 -->
<solid android:color="#EEEEEE"/>
</shape>
</item>
</layer-list>
复制代码
原理分析
LayerDrawable 类
:LayerDrawable 是 Drawable 的子类,用于将多个 Drawable 组合成一个图层列表。当在 XML 中定义 layer-list 标签时,体系会创建一个 LayerDrawable 对象,并将每个 item 标签内的 Drawable 作为一个图层添加到列表中。
Item 标签
:item 标签用于定义每个图层的 Drawable。可以通过 android:bottom、android:right 等属性设置图层的偏移量。在绘制时,LayerDrawable 会按照图层的顺序依次绘制每个 Drawable,反面的图层会覆盖前面的图层。
ShapeDrawable 嵌套
:在每个 item 标签内,可以使用 shape 标签定义 ShapeDrawable。这样可以为每个图层设置不同的形状、颜色和圆角属性。
三、代码动态设置圆角
3.1 使用 View.setBackground ()
// 创建一个 GradientDrawable 对象
val drawable = GradientDrawable()
// 设置圆角半径为 24f
drawable.cornerRadius = 24f
// 设置填充颜色为资源文件中定义的 colorPrimary 颜色
drawable.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
// 将 GradientDrawable 对象设置为 View 的背景
view.setBackground(drawable)
复制代码
原理分析
GradientDrawable 类
:GradientDrawable 类提供了设置圆角和颜色的方法。cornerRadius 属性用于设置圆角半径,setColor 方法用于设置填充颜色。
View.setBackground () 方法
:View 类的 setBackground 方法用于设置 View 的配景 Drawable。当调用该方法时,View 会将传入的 Drawable 对象保存起来,并在绘制时使用该 Drawable 绘制配景。
3.2 使用 ViewOutlineProvider
// 为 View 设置自定义的 OutlineProvider
view.outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
// 设置 Outline 为一个圆角矩形,圆角半径为 24f
outline.setRoundRect(0, 0, view.width, view.height, 24f)
}
}
// 开启 View 的裁剪功能,使其按照 Outline 进行裁剪
view.clipToOutline = true
复制代码
原理分析
ViewOutlineProvider 类
:ViewOutlineProvider 是一个抽象类,用于提供 View 的轮廓信息。通过重写 getOutline 方法,可以自定义 View 的轮廓形状。在这个例子中,我们将 Outline 设置为一个圆角矩形。
Outline 类
:Outline 类用于表示 View 的轮廓。setRoundRect 方法用于设置圆角矩形的轮廓,它接受矩形的左上角和右下角坐标以及圆角半径作为参数。
clipToOutline 属性
:View 的 clipToOutline 属性用于控制是否按照 Outline 进行裁剪。当设置为 true 时,View 会在绘制时将超出 Outline 的部门裁剪掉,从而实现圆角效果。
3.3 使用 Path 裁剪
override fun onDraw(canvas: Canvas) {
// 创建一个 Path 对象
val path = Path()
// 向 Path 中添加一个圆角矩形,圆角半径为 24f
path.addRoundRect(0f, 0f, width.toFloat(), height.toFloat(), 24f, 24f, Path.Direction.CW)
// 使用 Path 对 Canvas 进行裁剪
canvas.clipPath(path)
// 调用父类的 onDraw 方法进行绘制
super.onDraw(canvas)
}
复制代码
原理分析
Path 类
:Path 类用于定义一个路径,可以包含直线、曲线、矩形、圆形等各种形状。addRoundRect 方法用于向 Path 中添加一个圆角矩形,它接受矩形的左上角和右下角坐标以及圆角半径作为参数。
Canvas.clipPath () 方法
:Canvas 的 clipPath 方法用于使用指定的 Path 对 Canvas 进行裁剪。在绘制时,只有 Path 内部的区域会被绘制,外部的区域会被裁剪掉。
onDraw 方法
:View 的 onDraw 方法是绘制 View 内容的核心方法。在这个方法中,我们先创建一个圆角矩形的 Path,然后使用该 Path 对 Canvas 进行裁剪,最后调用父类的 onDraw 方法进行绘制,从而实现圆角效果。
四、第三方库实现圆角
4.1 AndroidX CardView
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
<!-- 设置卡片的圆角半径为 20dp -->
app:cardCornerRadius="20dp"
<!-- 设置卡片的阴影高度为 8dp -->
app:cardElevation="8dp">
<!-- 子视图 -->
</com.google.android.material.card.MaterialCardView>
复制代码
原理分析
MaterialCardView 类
:MaterialCardView 是 AndroidX Material Design 库中的一个自定义 View,它继续自 FrameLayout。它封装了圆角和阴影的实现,提供了简朴的属性来设置圆角半径和阴影高度。
cardCornerRadius 属性
:app:cardCornerRadius 属性用于设置卡片的圆角半径。在 MaterialCardView 内部,会根据该属性创建一个圆角矩形的 Outline,并使用 clipToOutline 进行裁剪,从而实现圆角效果。
cardElevation 属性
:app:cardElevation 属性用于设置卡片的阴影高度。MaterialCardView 会根据该属性使用 View 的阴影机制绘制阴影效果。
4.2 RoundedImageView
<com.makeramen.roundedimageview.RoundedImageView
android:layout_width="200dp"
android:layout_height="200dp"
<!-- 设置圆角半径为 40dp -->
app:riv_corner_radius="40dp"
<!-- 设置边框宽度为 2dp -->
app:riv_border_width="2dp"
<!-- 设置边框颜色为黄色 -->
app:riv_border_color="#FFEB3B"
<!-- 设置是否对背景进行变形处理 -->
app:riv_mutate_background="true"
<!-- 设置图片资源 -->
android:src="@drawable/avatar"/>
复制代码
原理分析
RoundedImageView 类
:RoundedImageView 是一个开源的第三方库,用于实现图片的圆角效果。它继续自 ImageView,通过重写 onDraw 方法来实现圆角裁剪。
riv_corner_radius 属性
:app:riv_corner_radius 属性用于设置圆角半径。在 RoundedImageView 内部,会根据该属性创建一个圆角矩形的 Path,并使用 Canvas.clipPath 方法对图片进行裁剪。
riv_border_width 和 riv_border_color 属性
:app:riv_border_width 和 app:riv_border_color 属性分别用于设置边框的宽度和颜色。在绘制时,会在圆角矩形的边沿绘制指定宽度和颜色的边框。
riv_mutate_background 属性
:app:riv_mutate_background 属性用于设置是否对配景进行变形处理。当设置为 true 时,会对配景进行圆角处理。
4.3 Material Design Components
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
<!-- 设置按钮的圆角半径为 16dp -->
app:cornerRadius="16dp"
<!-- 设置按钮的边框宽度为 2dp -->
app:strokeWidth="2dp"
<!-- 设置按钮的边框颜色为资源文件中定义的 colorAccent 颜色 -->
app:strokeColor="@color/colorAccent"/>
复制代码
原理分析
MaterialButton 类
:MaterialButton 是 AndroidX Material Design 库中的一个自定义 Button,它继续自 AppCompatButton。它提供了简朴的属性来设置圆角半径和边框效果。
cornerRadius 属性
:app:cornerRadius 属性用于设置按钮的圆角半径。在 MaterialButton 内部,会根据该属性创建一个圆角矩形的 Outline,并使用 clipToOutline 进行裁剪,从而实现圆角效果。
strokeWidth 和 strokeColor 属性
:app:strokeWidth 和 app:strokeColor 属性分别用于设置按钮的边框宽度和颜色。在绘制时,会在按钮的边沿绘制指定宽度和颜色的边框。
五、高级技巧与优化
5.1 动态圆角动画
// 从资源文件中加载一个过渡动画
val transition = TransitionInflater.from(this).inflateTransition(R.transition.change_bounds)
// 获取场景根视图
val sceneRoot = findViewById<ViewGroup>(R.id.scene_root)
// 开始延迟过渡动画
TransitionManager.beginDelayedTransition(sceneRoot, transition)
// 动画触发
view.animate().withEndAction {
// 创建一个 GradientDrawable 对象
val drawable = GradientDrawable()
// 根据当前圆角半径的值,切换圆角半径
drawable.cornerRadius = if (currentRadius == 0f) 24f else 0f
// 更新当前圆角半径的值
currentRadius = drawable.cornerRadius
// 将 GradientDrawable 对象设置为 View 的背景
view.setBackground(drawable)
}.start()
复制代码
原理分析
TransitionInflater 类
:TransitionInflater 用于从资源文件中加载过渡动画。inflateTransition 方法接受一个过渡动画的资源 ID 作为参数,返回一个 Transition 对象。
TransitionManager 类
:TransitionManager 用于管理过渡动画。beginDelayedTransition 方法用于开始一个延迟过渡动画,它接受一个场景根视图和一个 Transition 对象作为参数。在这个方法调用之后,对场景根视图及其子视图的布局变革会触发过渡动画。
View.animate () 方法
:View 的 animate 方法用于创建一个 ViewPropertyAnimator 对象,用于对 View 的属性进办法画操作。withEndAction 方法用于在动画结束时执行一个操作,这里我们在动画结束时切换 View 的圆角半径。
5.2 硬件加快优化
<application
android:hardwareAccelerated="true"
...>
</application>
复制代码
原理分析
硬件加快机制
:Android 体系的硬件加快机制允许使用 GPU 来处理图形渲染,从而提高渲染性能。当 android:hardwareAccelerated 属性设置为 true 时,整个应用的 View 渲染都会使用硬件加快。
对圆角绘制的影响
:在硬件加快的情况下,View 的圆角绘制会由 GPU 进行处理,渲染速率会更快。比方,使用 ViewOutlineProvider 和 Canvas.clipPath 等方法在硬件加快下的性能会更好。
5.3 内存优化
// 复用 Drawable,创建一个共享的 GradientDrawable 对象
val sharedDrawable = GradientDrawable()
// 将共享的 GradientDrawable 对象设置为 view1 的背景
view1.setBackground(sharedDrawable)
// 将共享的 GradientDrawable 对象设置为 view2 的背景
view2.setBackground(sharedDrawable)
// 及时回收资源,在 View 从窗口中分离时调用
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
// 对背景 Drawable 进行变异处理,避免共享状态的影响
(view.background as? GradientDrawable)?.mutate()
// 将 View 的背景设置为 null,释放资源
view.setBackground(null)
}
复制代码
原理分析
Drawable 复用
:通过创建一个共享的 Drawable 对象,并将其设置为多个 View 的配景,可以减少内存开销。由于多个 View 共享同一个 Drawable 对象,避免了重复创建相同的 Drawable 实例。
mutate () 方法
:Drawable 的 mutate 方法用于创建一个 Drawable 的独立副本,使其状态与原始 Drawable 分离。在 View 从窗口中分离时调用 mutate 方法,可以避免共享状态的影响,确保资源的正确开释。
setBackground (null) 方法
:在 View 从窗口中分离时,将 View 的配景设置为 null,可以开释 View 持有的 Drawable 对象,避免内存泄漏。
六、源码深度分析
6.1 View 圆角实现原理
// View.java
public void setOutlineProvider(OutlineProvider outlineProvider) {
// 如果当前已经设置了 OutlineProvider,则调用其 onStop 方法
if (mOutlineProvider != null) {
mOutlineProvider.onStop(this);
}
// 更新 OutlineProvider
mOutlineProvider = outlineProvider;
// 如果新设置的 OutlineProvider 不为 null,则调用其 onStart 方法
if (mOutlineProvider != null) {
mOutlineProvider.onStart(this);
}
// 使 Outline 无效,触发重新计算
invalidateOutline();
// 使 View 无效,触发重绘
invalidate();
}
// OutlineProvider.java
public abstract class OutlineProvider {
public void getOutline(View view, Outline outline) {
// 默认设置 Outline 为一个椭圆形
outline.setOval(0, 0, view.getWidth(), view.getHeight());
}
}
复制代码
原理分析
View.setOutlineProvider () 方法
:该方法用于设置 View 的 OutlineProvider。在设置新的 OutlineProvider 之前,会先调用当前 OutlineProvider 的 onStop 方法,然后更新 OutlineProvider,并调用新的 OutlineProvider 的 onStart 方法。最后,调用 invalidateOutline 方法使 Outline 无效,触发重新计算,调用 invalidate 方法使 View 无效,触发重绘。
OutlineProvider.getOutline () 方法
:这是一个抽象方法,用于提供 View 的 Outline 信息。默认实现将 Outline 设置为一个椭圆形,但在现实使用中,我们通常会重写该方法,根据需要设置不同的 Outline 形状,如圆角矩形。
6.2 硬件加快渲染流程
// RenderNode.java
public void setRoundRect(int left, int top, int right, int bottom, float radius) {
// 调用底层的绘制节点设置圆角矩形
mDrawNode.setRoundRect(left, top, right, bottom, radius);
// 标记属性无效,需要重新计算
mInvalidateProperties = true;
}
// RenderProxy.java
public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry) {
// 调用底层的本地方法绘制圆角矩形
nDrawRoundRect(mNativeRenderProxy, left, top, right, bottom, rx, ry);
}
复制代码
原理分析
RenderNode.setRoundRect () 方法
:RenderNode 是 Android 硬件加快渲染的核心类之一,用于表示一个可渲染的节点。setRoundRect 方法用于设置 RenderNode 的绘制形状为圆角矩形。它会调用底层的绘制节点的 setRoundRect 方法,并标记属性无效,以便在下次渲染时重新计算。
RenderProxy.drawRoundRect () 方法
:RenderProxy 是 RenderNode 的署理类,用于与底层的渲染引擎进行交互。drawRoundRect 方法用于绘制圆角矩形,它会调用底层的本地方法 nDrawRoundRect 来完成现实的绘制操作。
七、常见问题与办理方案
7.1 圆角不表现
大概原因
:
XML 中未正确设置 android:background:如果在 XML 中没有为 View 设置正确的配景 Drawable,则圆角效果不会表现。
视图尺寸为 0:如果 View 的宽度或高度为 0,则无法表现圆角效果。这大概是由于布局参数设置不正确或在 View 测量之前进行了绘制操作。
硬件加快未开启:某些圆角绘制方法(如 ViewOutlineProvider)需要开启硬件加快才气正常工作。如果硬件加快未开启,大概会导致圆角不表现。
办理方案
:
view.post {
// 在 View 布局完成后,设置背景资源
view.setBackgroundResource(R.drawable.rounded_bg)
}
复制代码
原理分析
view.post () 方法
:View 的 post 方法用于在 View 的消息队列中添加一个任务,该任务会在 View 布局完成后执行。通过使用 view.post 方法,可以确保在 View 有正确的尺寸之后再设置配景资源,从而避免因视图尺寸为 0 导致的圆角不表现问题。
7.2 边沿锯齿
办理方案
:
// 开启 Drawable 的抗锯齿功能
drawable.isAntiAlias = true
// 使用抗锯齿的画笔绘制圆角矩形
canvas.drawRoundRect(rect, radius, radius, paint)
复制代码
原理分析
isAntiAlias 属性
:Drawable 的 isAntiAlias 属性用于开启或关闭抗锯齿功能。抗锯齿功能可以使图形的边沿更加平滑,减少锯齿征象。当设置为 true 时,Drawable 在绘制时会使用抗锯齿算法来处理边沿。
Paint 抗锯齿
:在使用 Canvas 绘制圆角矩形时,通过设置 Paint 的抗锯齿属性,可以使绘制的圆角矩形边沿更加平滑。
7.3 性能问题
优化建议
:
使用 OutlineProvider 替换自定义绘制:OutlineProvider 是 Android 体系提供的一种高效的圆角绘制方法,它使用了硬件加快机制,性能比自定义绘制更好。
避免在 onDraw 中创建对象:onDraw 方法会频仍调用,如果在其中创建对象,会导致频仍的垃圾回收,影响性能。可以将对象的创建移到 onCreate 或其他初始化方法中。
合理设置缓存策略:可以使用 View 的 setDrawingCacheEnabled 方法开启绘图缓存,避免重复绘制,提高性能。
八、不同场景下的实现策略
场景推荐方案优势简朴圆角矩形ShapeDrawable / GradientDrawable代码简洁,兼容性好,实用于大多数简朴的圆角矩形需求。可以通过 XML 或代码动态设置,易于维护。复杂形状Path 裁剪灵活性高,支持任意形状的圆角裁剪。可以通过 Path 类定义复杂的路径,实现独特的形状效果。需要阴影效果CardView内置阴影支持,性能优化。CardView 是 AndroidX Material Design 库中的组件,提供了简朴的属性来设置圆角和阴影,同时对性能进行了优化。图片圆角RoundedImageView专业处理图片,支持多种效果。RoundedImageView 是一个开源的第三方库,专门用于处理图片的圆角效果,支持圆形、圆角、椭圆等多种形状,还可以设置边框和配景变形效果。动态圆角动画ViewOutlineProvider + 动画流通过渡,硬件加快优化。通过 ViewOutlineProvider 实现圆角效果,联合 ViewPropertyAnimator 或 TransitionManager 实现动态圆角动画,使用硬件加快机制,过渡效果流通。
九、性能对比测试
方法内存占用(KB)渲染时间(ms)兼容性ShapeDrawable1.20.8API 1+CardView3.51.5API 21+OutlineProvider2.11.2API 21+自定义 Path 绘制4.82.5API 1+RoundedImageView5.21.8API 1+
性能分析
内存占用
:ShapeDrawable 的内存占用最小,由于它只是一个简朴的形状绘制类。CardView、OutlineProvider、RoundedImageView 和自定义 Path 绘制的内存占用相对较大,由于它们涉及到更多的功能和复杂的绘制逻辑。
渲染时间
:ShapeDrawable 的渲染时间最短,由于它的绘制逻辑最简朴。CardView 和 OutlineProvider 的渲染时间相对较短,由于它们使用了硬件加快机制。自定义 Path 绘制的渲染时间最长,由于它需要手动处理裁剪和绘制逻辑。
兼容性
:ShapeDrawable 和自定义 Path 绘制的兼容性最好,支持全部 Android API 版本。CardView 和 `Outline
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/)
Powered by Discuz! X3.4