RelativeLayout圆角处理

RelativeLayout圆角处理RelativeLayo 圆角处理以后 可以变相对子 view 进行圆角处理 如 ImageView VideoView 等 RoundRelativ 具体实现比较简单 只需要在初始化时设置一下 layout 的 ViewOutlineP 方便起见 这里写死 radius 为 20dp 一个可以把 RelativeLayo 裁剪成圆角的自定义 RelativeLayo 布局 由于 layout 里面的子 view 同样会被裁剪 例如 VideoView ImageVi

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

RelativeLayout圆角处理

 

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; } @Override public 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 1.0f. * * @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. * 

* 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. *

* 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. *

* 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 outline mRenderNode.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 { // 省略无关代码... @CriticalNative private 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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/217720.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午8:55
下一篇 2026年3月18日 上午8:55


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号