我试图创建一个与常规WebView完全相同的自定义WebView,除了它有圆角。圆角需要透明,因为我想将此WebView放在对话框中。
我尝试制作我的自定义类:
public class RoundedWebView extends WebView
{
private Context context;
private int width;
private int height;
public RoundedWebView(Context context)
{
super(context);
initialize(context);
}
public RoundedWebView(Context context, AttributeSet attrs)
{
super(context, attrs);
initialize(context);
}
public RoundedWebView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
initialize(context);
}
private void initialize(Context context)
{
this.context = context;
}
// This method gets called when the view first loads, and also whenever the
// view changes. Use this opportunity to save the view's width and height.
@Override protected void onSizeChanged(int newWidth, int newHeight, int oldWidth, int oldHeight)
{
this.width = newWidth;
this.height = newHeight;
super.onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
}
@Override protected void onDraw(Canvas canvas)
{
int radius = Utilities.dpToPx(context, 5);
Path clipPath = new Path();
clipPath.addRoundRect(new RectF(0, 0, width, height), radius, radius, Path.Direction.CW);
canvas.clipPath(clipPath);
super.onDraw(canvas);
}
}
这个实现大部分都有效。但是,只要网址完成加载并在屏幕上显示自己,我就会丢失WebView的圆角。知道发生了什么吗?
答案 0 :(得分:6)
这是我找到的解决方案。在我的onDraw()方法中,我创建了一个倒置的,填充的圆角矩形,然后使用Porter Duff Xfer模式来清除"清除"屏幕上的那个区域。这给我留下了一个具有很好倾斜边缘的WebView,包括WebView完成加载URL的情况。
public class RoundedWebView extends WebView
{
private Context context;
private int width;
private int height;
private int radius;
public RoundedWebView(Context context)
{
super(context);
initialize(context);
}
public RoundedWebView(Context context, AttributeSet attrs)
{
super(context, attrs);
initialize(context);
}
public RoundedWebView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
initialize(context);
}
private void initialize(Context context)
{
this.context = context;
}
// This method gets called when the view first loads, and also whenever the
// view changes. Use this opportunity to save the view's width and height.
@Override protected void onSizeChanged(int newWidth, int newHeight, int oldWidth, int oldHeight)
{
super.onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
width = newWidth;
height = newHeight;
radius = Utilities.dpToPx(context, 5);
}
@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());
}
private Paint createPorterDuffClearPaint()
{
Paint paint = new Paint();
paint.setColor(Color.TRANSPARENT);
paint.setStyle(Style.FILL);
paint.setAntiAlias(true);
paint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
return paint;
}
}
答案 1 :(得分:0)
在onDraw(Canvas canvas)
中,您最后调用super
方法。这意味着您在自定义绘制方法中执行的任何操作都将通过super方法撤消。尝试先调用super,然后再进行自定义绘图。
答案 2 :(得分:0)
它可能对其他人有帮助。在加载数据之前,您需要设置
webView.getSettings().setUseWideViewPort(true);
并将您应用于XML文件中。
它对我有用。
答案 3 :(得分:0)
这是解决方案。经过三天的研究。
public class RoundedWebView extends WebView
{
private final static float CORNER_RADIUS = 100.0f;
private Bitmap maskBitmap;
private Paint paint, maskPaint;
private float cornerRadius;
public RoundedWebView(Context context) {
super(context);
init(context, null, 0);
initView(context);
}
public RoundedWebView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
initView(context);
}
public RoundedWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
initView(context);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
setWillNotDraw(false);
}
@Override
public void draw(Canvas canvas) {
Bitmap offscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
Canvas offscreenCanvas = new Canvas(offscreenBitmap);
super.draw(offscreenCanvas);
if (maskBitmap == null) {
maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
}
offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint);
canvas.drawBitmap(offscreenBitmap, 0f, 0f, paint);
}
private Bitmap createMask(int width, int height) {
Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
Canvas canvas = new Canvas(mask);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
canvas.drawRect(0, 0, width, height, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);
return mask;
}
void initView(Context context){
// i am not sure with these inflater lines
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// you should not use a new instance of MyWebView here
// MyWebView view = (MyWebView) inflater.inflate(R.layout.custom_webview, this);
this.getSettings().setUseWideViewPort(true);
this.getSettings().setLoadWithOverviewMode(true);
}
}
答案 4 :(得分:0)
这是@Luke答案的Kotlin版本。
我还改进了代码,以避免在onDraw方法期间分配对象。
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.graphics.RectF
import android.util.AttributeSet
import android.webkit.WebView
import net.onefivefour.android.bitpot.extensions.dpToPx
class RoundedWebView : WebView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
private lateinit var roundedRect: RectF
private val cornerRadius = 10f.dpToPx(context)
private val pathPaint = Path().apply {
fillType = Path.FillType.INVERSE_WINDING
}
private val porterDuffPaint = Paint().apply {
color = Color.TRANSPARENT
style = Paint.Style.FILL
isAntiAlias = true
xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
}
override fun onSizeChanged(newWidth: Int, newHeight: Int, oldWidth: Int, oldHeight: Int) {
super.onSizeChanged(newWidth, newHeight, oldWidth, oldHeight)
roundedRect = RectF(0f, scrollY.toFloat(), width.toFloat(), (scrollY + height).toFloat())
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
pathPaint.reset()
pathPaint.addRoundRect(roundedRect, cornerRadius, cornerRadius, Path.Direction.CW)
canvas.drawPath(pathPaint, porterDuffPaint)
}
}
这也是将dp计算为像素的扩展方法:
fun Float.dpToPx(context: Context): Float {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, context.resources.displayMetrics)
}