0

I have created a custom view class extending Android's WebView, but when I add it to an xml layout, it appears as a gray block. I would like to show a custom layout in place of the gray block to be able to preview it.

The definition of the custom view is as follows:

class CustomView(context: Context, attrs: AttributeSet?) : WebView(context, attrs) {

    constructor(context: Context) : this(context, null)

    init {
        if (isInEditMode) {
            //show preview layout
            context.getSystemService<LayoutInflater>()!!
                .inflate(R.layout.widget_match_preview, this, true)
        }
    }
}

As can be seen in the code above, I have tried to show a preview in the init block, but it stills shows the gray block in the Android Studio layout preview.

Trace171
  • 13
  • 6
  • 1
    I think this is because you're trying to add this layout to a `WebView` which has its own rendering situation going on - if you change it to a normal `ViewGroup` (even `AbsoluteLayout` which `WebView` subclasses) it displays fine. I'm not sure there's a way to force a certain preview display (there's no XML attribute on `WebView` for it) unless you want to dig into the source and work out how to override its behaviour. If you really need a preview image for some reason, your custom view might need to be something like a `FrameLayout` that *contains* a `WebView` (or doesn't if it's a preview) – cactustictacs Dec 22 '22 at 00:59

3 Answers3

1

AFAIK this can not be done, as @cactustictacs said, WebView implements its own drawing and can not be changed to another layout. What I ended up doing is overrride the onDraw(canvas: Canvas) method, and add the following to render a preview icon at the center of the view:

@SuppressLint("DrawAllocation")
override fun onDraw(canvas: Canvas) {
    if (isInEditMode.not()) {
        super.onDraw(canvas)
        return
    }
    canvas.drawColor(Color.WHITE)
    val bitmap = ResourcesCompat.getDrawable(resources, R.drawable.widget_preview, null)!!.toBitmap()
    val size = minOf(width, height) / 2
    val rect = Rect((width - size) / 2, (height - size) / 2, (width + size) / 2, (height + size) / 2)
    canvas.drawBitmap(bitmap, null, rect, null)
}

Draw allocation is not a problem since will only be done once while in preview mode in the IDE. The only downside is that the icon is being drawn behind the "CustomView" text but is not big of a deal.

Trace171
  • 13
  • 6
0

I think you're missing addView:

class CustomView(context: Context, attrs: AttributeSet?) : WebView(context, attrs) {

    constructor(context: Context) : this(context, null)

    init {
        if (isInEditMode) {
            // inflate the preview layout
            val previewLayout = context.getSystemService<LayoutInflater>()!!
                .inflate(R.layout.widget_match_preview, null)

            // add the preview layout as a child view of the CustomView
            addView(previewLayout)
        }
    }
}
Chuck D
  • 1,629
  • 2
  • 16
  • 32
  • I have tried your solution and rebuild, but I'm afraid the problem persists. – Trace171 Dec 21 '22 at 23:22
  • Have you reviewed this [SO Post](https://stackoverflow.com/questions/16592965/android-studio-layout-editor-cannot-render-custom-views) – Chuck D Dec 22 '22 at 16:56
0

You should:

class CustomView : LinearLayout {

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    init {
        LayoutInflater.from(context).inflate(R.layout.widget_match_preview, this, true)
        if (!isInEditMode) {
            // skip code
        }
    }
}
  • Result: previewlayout

  • In xml:

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout 
       xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="@color/red"/>
    
Cuong Nguyen
  • 970
  • 6
  • 17
  • This does only work if the parent class of the custom view is a LinearLayout, as stated in the question, CustomView must extend WebView – Trace171 Dec 22 '22 at 06:40