这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战
前言
项目中遇到一个跟H5交互的问题,需要我们做一个弹框来显示一个H5的编辑页面,本来很简单的东西,就是写一个自定义Dialog,添加一个webview,设置好webview的属性,然后直接加载就好了,需求很简单,只是UI设计上,需要给弹框设置圆角,其实也没问题,那就设置呗,但是却遇到了问题。。。
UI添加圆角的方法
1.通过shape文件,设置圆角:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/white" />
<corners
android:bottomLeftRadius="0px"
android:bottomRightRadius="0px"
android:topLeftRadius="12px"
android:topRightRadius="12px" />
</shape>
复制代码
2.通过代码手动设置圆角:
public static StateListDrawable getBackGroundDrawable(int strokeRoundWidth, float roundRadius, int strokeColor, int fillColor) {
float[] radii = new float[]{roundRadius, roundRadius, roundRadius, roundRadius, roundRadius, roundRadius, roundRadius, roundRadius};
StateListDrawable drawable = new StateListDrawable();
GradientDrawable pressState = new GradientDrawable();//创建drawable
pressState.setColor(caculateColor(fillColor, Color.BLACK, 0.1f));
pressState.setCornerRadii(radii);
pressState.setStroke(strokeRoundWidth, strokeColor);
GradientDrawable eableState = new GradientDrawable();//创建drawable
eableState.setColor(caculateColor(fillColor, Color.WHITE, 0.5f));
eableState.setCornerRadii(radii);
eableState.setStroke(0, strokeColor);
GradientDrawable commonState = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, new int[]{Color.BLACK, fillColor});
commonState.setColor(fillColor);
commonState.setCornerRadii(radii);
commonState.setStroke(strokeRoundWidth, strokeColor);
drawable.addState(new int[]{-android.R.attr.state_enabled}, eableState);
drawable.addState(new int[]{android.R.attr.state_pressed}, pressState);
drawable.addState(new int[]{}, commonState);
return drawable;
}
复制代码
通过setBackGround(Drawable drawable) 方法设置背景
给webview 设置圆角
1.通过给webview 添加外层布局,给布局设置圆角,设置内边距,实现加载页面有圆角
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<RelativeLayout
android:id="@+id/rel_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="2dp"
android:background="@drawable/drawable_webview_bg"
>
<com.tencent.smtt.sdk.WebView
android:id="@+id/wv_course_detail_summary"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</com.tencent.smtt.sdk.WebView>
</RelativeLayout>
</RelativeLayout>
复制代码
2.通过设置webview的Background
1、先将layout文件中的 WebView控件取消硬件加速 android:layerType="software",(以确保第2步有效) 2、在Java代码中,将WebView控件背景色设为透明 web.setBackgroundColor(0);
3、获取一个圆角的Bitmap实例(网上有大把的实现方法);
4、通过 Bitmap实例获取一个 BitmapDrawable实例 BitmapDrawable bitmapDrawable = new BitmapDrawable(bitmap); 5、将 BitmapDrawable实例 BitmapDrawable 设置成WebView控件的背景 web.setBackground(bitmapDrawable);
不过,由于 web.setBackground 是 Android v4.1.2 (API Level 16)才开始支持,因此,这个功能也只能在 API Level 16及其以上实现。
以上方法,方法一肯定可以,但是对我项目中的需求,满足不了,因为webview的显示内容会被padding缩小,导致如果webview有加载的内容,有其他弹框弹出,覆盖区域只有webview加载的内容,会有2dp的白色边框;方法二,没有实际测试,但是目测不太靠谱,大家可以试试
我使用了第三种方法 3.自定义webview,通过draw方法绘制圆角,进行裁剪边缘
public class MyRoundedWebView extends CoreWebView {
private Context context;
private int width;
private int height;
private int radius;
public MyRoundedWebView(Context context) {
super(context);
initialize(context);
}
public MyRoundedWebView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context);
}
private void initialize(Context context) {
this.context = context;
}
@Override
protected void onSizeChanged(int newWidth, int newHeight, int oldWidth, int oldHeight) {
super.onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
width = newWidth;
height = newHeight;
//设置圆角
radius = PHSizeUtils.mm2px(context, 46f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Path path = new Path();
path.setFillType(Path.FillType.INVERSE_WINDING);
path.addRoundRect(new RectF(0, getScrollY(), width, getScrollY() + height), radius, radius, Path.Direction.CW);
canvas.drawPath(path, createPorterDuffClearPaint());
}
//使用Porter Duff Xfer模式从屏幕"清除"该区域
private Paint createPorterDuffClearPaint() {
Paint paint = new Paint();
paint.setColor(Color.TRANSPARENT);
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
return paint;
}
}
复制代码
这样实现后,webview 加载完后,显示的是完整的控件,不管加载的url里面有什么弹框,都是按照webview显示的区域去显示
总结
以上就是针对 webview 设置圆角的方法,当然举一反三,其他的view也可以通过这样的方式设置圆角,具体实现根据具体需求来完成