RelativeLayout圆角处理

article/2025/9/26 5:39:29

RelativeLayout圆角处理以后,可以变相对子view进行圆角处理,如ImageView,VideoView等

 

RoundRelativeLayout具体实现

比较简单,只需要在初始化时设置一下layout的ViewOutlineProvider,方便起见,这里写死radius为20dp 

/*** 一个可以把RelativeLayout裁剪成圆角的自定义RelativeLayout布局* 由于layout里面的子view同样会被裁剪,例如VideoView,ImageView等,很实用** created by luninggithub*/
public class RoundRelativeLayout extends RelativeLayout {private static final int DEFAULT_ROUND_SIZE = 20;public RoundRelativeLayout(Context context) {this(context, null);}public RoundRelativeLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public RoundRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {this(context, attrs, defStyleAttr, 0);}public RoundRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);init();}/*** 初始化*/private void init() {RoundViewOutlineProvider outlineProvider = new RoundViewOutlineProvider(ScreenUtil.dp2px(DEFAULT_ROUND_SIZE));setOutlineProvider(outlineProvider);setClipToOutline(true);}/*** 圆角ViewOutlineProvider*/private static class RoundViewOutlineProvider extends ViewOutlineProvider {private final int roundSize;public RoundViewOutlineProvider(int roundSize) {this.roundSize = roundSize;}@Overridepublic void getOutline(View view, Outline outline) {outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), roundSize);}}
}

关键类ViewOutlineProvider

ViewOutlineProvider是一个抽象类,系统预定义了三种不同的outlineprovider,我们只需要实现getOutline方法,在方法内部设置自定义的outline即可。

package android.view;import android.graphics.Outline;
import android.graphics.drawable.Drawable;/*** Interface by which a View builds its {@link Outline}, used for shadow casting and clipping.*/
public abstract class ViewOutlineProvider {// 省略系统预定义的ViewOutlineProvider代码.../*** Called to get the provider to populate the Outline.** This method will be called by a View when its owned Drawables are invalidated, when the* View's size changes, or if {@link View#invalidateOutline()} is called* explicitly.** The input outline is empty and has an alpha of <code>1.0f</code>.** @param view The view building the outline.* @param outline The empty outline to be populated.*/public abstract void getOutline(View view, Outline outline);
}

由注释可知,getOutline会在view主动调invalidateOutline()方法是被调用

RoundRelativeLayout在初始化int是,会设置自定义的outlineprovider:setOutlineProvider(outlineProvider);

有系统代码可知,setOutlineProvider方法会主动调用,如下:

// 省略View的其他代码......
/*** Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines* the shape of the shadow it casts, and enables outline clipping.* <p>* The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline* from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the* outline provider with this method allows this behavior to be overridden.* <p>* If the ViewOutlineProvider is null, if querying it for an outline returns false,* or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.* <p>* Only outlines that return true from {@link Outline#canClip()} may be used for clipping.** @see #setClipToOutline(boolean)* @see #getClipToOutline()* @see #getOutlineProvider()*/
public void setOutlineProvider(ViewOutlineProvider provider) {mOutlineProvider = provider;invalidateOutline(); // 这里会主动调用自定义的getOutline方法
}
// 省略View的其他代码......
/*** Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}** @see #setOutlineProvider(ViewOutlineProvider)*/
public void invalidateOutline() {rebuildOutline();// 见下面方法notifySubtreeAccessibilityStateChangedIfNeeded();invalidateViewProperty(false, false);
}
// 省略View其他代码......
private void rebuildOutline() {// Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()if (mAttachInfo == null) return;if (mOutlineProvider == null) {// no provider, remove outlinemRenderNode.setOutline(null);} else {final Outline outline = mAttachInfo.mTmpOutline;outline.setEmpty();outline.setAlpha(1.0f);mOutlineProvider.getOutline(this, outline); // 这里调用mRenderNode.setOutline(outline); // 见下面方法}
}/*** Sets the outline, defining the shape that casts a shadow, and the path to* be clipped if setClipToOutline is set.** This will make a copy of the provided {@link Outline}, so any future modifications* to the outline will need to call {@link #setOutline(Outline)} with the modified* outline for those changes to be applied.** @param outline The outline to use for this RenderNode.* @return True if the value changed, false if the new value was the same as the previous value.*/
public boolean setOutline(@Nullable Outline outline) {if (outline == null) {return nSetOutlineNone(mNativeRenderNode);}switch (outline.mMode) {case Outline.MODE_EMPTY:return nSetOutlineEmpty(mNativeRenderNode);case Outline.MODE_ROUND_RECT: // 走到这里return nSetOutlineRoundRect(mNativeRenderNode,outline.mRect.left, outline.mRect.top,outline.mRect.right, outline.mRect.bottom,outline.mRadius, outline.mAlpha);case Outline.MODE_PATH:return nSetOutlinePath(mNativeRenderNode, outline.mPath.mNativePath,outline.mAlpha);}throw new IllegalArgumentException("Unrecognized outline?");
}
// 省略View代码......public final class RenderNode {// 省略无关代码...@CriticalNativeprivate static native boolean nSetOutlineRoundRect(long renderNode, int left, int top,int right, int bottom, float radius, float alpha);
}

这样一看就比较清晰了

init -→ setOutlineProvider  -→ invalidateOutline  -→ rebuildOutline   -→ setOutline -→ nSetOutlineRoundRect(Native接口)

Demo参考github:LnCustomViews


http://chatgpt.dhexx.cn/article/crgi4Mrg.shtml

相关文章

RelativeLayout(相对布局)的基本使用

RelativeLayout又称作相对布局&#xff0c;也是一种非常常用的布局。和LinearLayout的排列规则不同&#xff0c;RelativeLayout显得更加随意一些&#xff0c;它可以通过相对定位的方式让控件出现在布局的任何位置。也正因为如此&#xff0c;RelativeLayout中的属性非常多&#…

RelativeLayout相对布局详解

RelativeLayout相对布局在Android UI开发中也应用比较多&#xff0c;虽然它不及LinearLayout使用方便&#xff0c;但某些场景中使用RelativeLayout也是一种很不错的选择。在官网上介绍RelativeLayout是一个视图组&#xff0c;在相对位置显示子视图。RelativeLayout是用于设计用…

Android相对布局(RelativeLayout)

Android相对布局(RelativeLayout) 备注&#xff1a;这里的视图和元素是等同的概念。 RelativeLayout是一个允许子视图相对于其他兄弟视图或是父视图显示的视图组(通过ID指定)。每个视图的位置能够指定它相对于兄弟(比如在其他视图的左边或是下边)或是父视图(这里是指相对布局容…

【Android】相对布局(RelativeLayout)最全解析

【Android】相对布局&#xff08;RelativeLayout&#xff09;最全解析 一、相对布局&#xff08;RelativeLayout&#xff09;概述二、根据父容器定位三、根据兄弟控件定位 一、相对布局&#xff08;RelativeLayout&#xff09;概述 相对布局&#xff08;RelativeLayout&#x…

Flutter ListView详解

ListView详解 ListView常用构造ListViewListView 默认构建效果 ListView ListTileListTile 属性ListTile 使用效果 ListView builderbuilder属性详细介绍分析几个比较难理解的属性效果builder模式来设置分割线 ListView separatedseparatorBuilderseparated设置分割线效果 List…

UE4 ListView

UE4-ListView UE4ListView和U3D的思路不太一样&#xff0c;详细了解之后发现UE4的ListView还是蛮先进的&#xff0c;直接就实现了逻辑和显示分离&#xff0c;提高效率&#xff0c;相对的&#xff0c;他的用法也比Unity的ListView绕一些。举例&#xff0c;一个ListView如果设置…

Android 控件 —— ListView

ListView 的简单用法 在布局中加入 ListView 控件还算简单&#xff0c;先为 ListView 指定一个 id&#xff0c;然后将宽度和高度都设置为 match_parent&#xff0c;这样 ListView 就占满了整个布局的空间 <LinearLayout xmlns:android"http://schemas.android.com/ap…

ListView 组件

简介&#xff1a; ListView是最常用的可滚动组件之一 有三种构建方式&#xff1a; ListViewListView.builderListView.separated 主要参数说明&#xff1a; scrollDirection: Axis.horizontal 水平列表Axis.vertical 垂直列表 padding: 内边距 resolve: 组件反向排序 childr…

4.ListView

ListView 文章目录 ListView一、什么是ListView二、ListView入门1.ListView核心类2.代码编写步骤 三、ListView优化四、把复杂界面(通过xml文件实现)显示到ListView上1.View的静态方法2.获取LayoutInflater对象 五、SimpleAdapter & ArrayAdapter的使用1.ArrayAdapter2.Sim…

ListView及ListAdapter详解

ListView及ListAdapter详解 一、AdapterView 1. 简介 An AdapterView is a view whose children are determined by an Adapter. 简单地说就是其子视图是由适配器决定的视图组件 2. 子类 ListViewGridViewSpinnerGallery3. 常用方法 //功能:获取list中指定位置item get…

qt listview

运行图 .h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>#include <QStringListModel> #include <QModelIndex>namespace Ui { class Widget; }class Widget : public QWidget {Q_OBJECTpublic:explicit Widget(QWidget *parent 0);~Widget();pri…

flutter 之 ListView的使用与详解 map for listview.builder 的使用

1.ListView 配合ListTile 实现新闻列表样式 ListView(children: <Widget>[ListTile(title: const Text(我是 title),subtitle: const Text(我是 sub_title),leading: Image.asset(images/c.png,fit: BoxFit.cover,),trailing: const Icon(Icons.chevron_right,size: 22,…

android ListView

android ListView几个比较特别的属性 由于这两天在做listView的东西&#xff0c;所以整理出来一些我个人认为比较特别的属性&#xff0c;通过设置这样的属性可以做出更加美观的列表 首先是stackFromBottom属性&#xff0c;这只该属性之后你做好的列表就会显示你列表的最下面&am…

ListView使用总结

ListView使用总结 虽然随着RecyclerView的不断普及&#xff0c;相应的资源也越来越多&#xff0c;许多的项目都在使用RecyclerView&#xff0c;但作为他的前辈ListView&#xff0c;加深对ListView的使用有助于我们更好的适应到RecyclerView的使用中。 首先看一下我们实现的效…

Android有关ListView嵌套ListView的一些问题

本人在做评论回复功能的时候&#xff0c;查阅到ListView结合Adapter适配器具有以列表的形式 展示具体数据内容&#xff0c;并且能够根据数据的长度自适应屏幕显示的功能&#xff0c;因此打算在ListView中嵌套ListView完成点击事件后弹出输入框再输入数据后在下方显示回复内容&a…

ListView详解0

ListView常用方法总结 1、listview拖动变黑解决方法 在Android中&#xff0c;ListView是最常用的一个控件&#xff0c;在做UI设计的时候&#xff0c;很多人希望能够改变一下它的背景&#xff0c;使他能够符合整体的UI设计&#xff0c;改变背景背很简单只需要准备一张图片然后指…

C# ListView 的用法

ListView 是一种多列的列表视图控件&#xff0c;可以用于展示多个数据项及其相关信息。ListView 控件提供了丰富的属性和事件&#xff0c;可以用于实现各种各样的表格视图&#xff0c;包括带有单元格编辑、排序和分组等功能。 下面我们通过几个示例来演示如何使用 ListView 控…

Qt ListView使用

概述 Qt中ListView加载数据一般有两种方式&#xff0c;一种是直接qml文件中model直接定义并且放置数据&#xff0c;一种是C代码中定义Model&#xff0c;再setContextProperty的方式暴露给qml域。 步骤 &#xff08;1&#xff09;qml界面 import QtQuick 2.0 import QtQui…

Android控件listview ListView的用法

在Android开发中&#xff0c;ListView是一个比较常用的控件&#xff0c;它以列表的形式展示数据内容&#xff0c;并且能够根据列表的高度自适应屏幕显示。ListView的样式是由属性决定的&#xff0c;它的常用属性如下所示 android:listSelector 点击后改变背景颜色 android:divi…

Android之ListView实现

ListView 用来显示多个可滑动项&#xff08;Item&#xff09;列表的ViewGroup。 需要使用Adapter&#xff08;适配器&#xff09;将集合数据和每一个Item所对应的布局动态适配到ListView中显示 显示列表&#xff1a;listView.setAdapter(adapter) Adapter ArrayAdapter&#xf…