核心ViewHelper,使用ViewOutlineProvider實現圓角
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="viewOutLineStrategy"> <attr name="clip_radius" format="dimension"></attr> <attr name="clip_side" format="enum"> <enum name="all" value="0"></enum> <enum name="left" value="1"></enum> <enum name="top" value="2"></enum> <enum name="right" value="3"></enum> <enum name="bottom" value="4"></enum> </attr> </declare-styleable> </resources>
ViewHelper.javahtml
import android.annotation.TargetApi; import android.content.res.TypedArray; import android.graphics.Outline; import android.util.AttributeSet; import android.view.View; import android.view.ViewOutlineProvider; public class ViewHelper { public static final int RADIUS_ALL = 0; public static final int RADIUS_LEFT = 1; public static final int RADIUS_TOP = 2; public static final int RADIUS_RIGHT = 3; public static final int RADIUS_BOTTOM = 4; public static void setViewOutline(View view, AttributeSet attributes, int defStyleAttr, int defStyleRes) { TypedArray array = view.getContext().obtainStyledAttributes(attributes, R.styleable.viewOutLineStrategy, defStyleAttr, defStyleRes); int radius = array.getDimensionPixelSize(R.styleable.viewOutLineStrategy_clip_radius, 0); int hideSide = array.getInt(R.styleable.viewOutLineStrategy_clip_side, 0); array.recycle(); setViewOutline(view, radius, hideSide); } public static void setViewOutline(View owner, final int radius, final int radiusSide) { owner.setOutlineProvider(new ViewOutlineProvider() { @Override @TargetApi(21) public void getOutline(View view, Outline outline) { int w = view.getWidth(), h = view.getHeight(); if (w == 0 || h == 0) { return; } if (radiusSide != RADIUS_ALL) { int left = 0, top = 0, right = w, bottom = h; if (radiusSide == RADIUS_LEFT) { right += radius; } else if (radiusSide == RADIUS_TOP) { bottom += radius; } else if (radiusSide == RADIUS_RIGHT) { left -= radius; } else if (radiusSide == RADIUS_BOTTOM) { top -= radius; } outline.setRoundRect(left, top, right, bottom, radius); return; } int top = 0, bottom = h, left = 0, right = w; if (radius <= 0) { outline.setRect(left, top, right, bottom); } else { outline.setRoundRect(left, top, right, bottom, radius); } } }); //開啓剪裁 owner.setClipToOutline(radius > 0); owner.invalidate(); } }
CornerFrameLayout
import android.content.Context; import android.util.AttributeSet; import android.widget.FrameLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; public class CornerFrameLayout extends FrameLayout { public CornerFrameLayout(@NonNull Context context) { this(context, null); } public CornerFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public CornerFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public CornerFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); ViewHelper.setViewOutline(this, attrs, defStyleAttr, defStyleRes); } public void setViewOutline(int radius, int radiusSide) { ViewHelper.setViewOutline(this, radius, radiusSide); } }
CornerLinearLayout
import android.content.Context; import android.util.AttributeSet; import android.widget.LinearLayout; import androidx.annotation.Nullable; public class CornerLinearLayout extends LinearLayout { public CornerLinearLayout(Context context) { this(context, null); } public CornerLinearLayout(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public CornerLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public CornerLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); ViewHelper.setViewOutline(this, attrs, defStyleAttr, defStyleRes); } }