https://kotlinlang.org logo
#compose
Title
# compose
c

coolchandrakumar

06/05/2020, 7:41 AM
Facing unresolved reference while using TextView/WebView inside composable.
Copy code
@Composable
fun inflateAndroidView() {
    Column(modifier = Modifier.fillMaxWidth().wrapContentSize(), horizontalGravity = Alignment.Start) {
        Text(text = "AndroidView-Compose", modifier = Modifier.padding(all = 16.dp))

        AndroidView(view = TextView(ContextAmbient.current).apply {
            text = "InsideTextView Android Widget"
        })

        AndroidView(view = WebView(ContextAmbient.current).apply {
            loadData("InsideWebView Android Widget", "text/html", "UTF-8")
        })
    }
}
Looking to achieve the same in developement
p

pavi2410

06/05/2020, 11:13 AM
Move WebView into a variable and set it to AndroidView
m

Mark Murphy

06/05/2020, 11:38 AM
what exactly is unresolved? can you be more specific?
c

coolchandrakumar

06/05/2020, 1:36 PM
Compile time error for TextView/WebView Unresolved reference error
z

Zach Klippenstein (he/him) [MOD]

06/05/2020, 4:32 PM
Android views are handled specially by the Compose compiler. When in a
@Composable
function, View constructor calls are intercepted and transformed into a function call that has a named parameter for every property of the view. The compiler will look for any
fun setFoo(foo)
or
var foo
properties in the View class and generate named parameters for each of those. So for
TextView
, you could write this:
TextView(text = "hello")
. The first time this call is performed in a composition, the view will be created and added to the view hierarchy. On subsequent compositions, the view will not be recreated, but any new values will just be passed to those property setters. This transformation also means that the View’s actual constructor, the one that takes a
Context
, is not accessible from inside a
@Composable
function. To call the actual constructor, you can either wrap the call in the
escapeCompose { }
function (anything inside that lambda will be exempted from the special processing), or pull your view constructor out into a regular, non-Composable function.
Note that Android Studio is not yet aware of this transformation, so it will complain that the function doesn’t exist, that it’s missing parameters, and that the generated property parameters don’t exist, but the code will actually compile.
The
WebComponent
uses this feature. You can see the call to the generated function on line 83: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-master-dev:ui/ui-android-view/src/main/java/androidx/ui/androidview/WebComponent.kt;l=83?q=WebComponent&ss=androidx And the extension functions on lines 60 and 64 are what tells the compiler to create those
ref
and
url
parameters on lines 84 and 85.
AndroidView
does the same thing. It’s a composable function that delegates to the
AndroidViewHolder
class, and instantiates it by either setting the
view
property or the
resId
(and callback) properties. https://cs.android.com/androidx/platform/frameworks/support/+/androidx-master-dev:ui/ui-core/src/main/java/androidx/ui/viewinterop/ComposedView.kt;l=51?q=%22fun%20AndroidView%22&ss=androidx
c

coolchandrakumar

06/08/2020, 6:48 AM
Thanks @Zach Klippenstein (he/him) [MOD] on checking of the answer written following snippet.
Copy code
@Composable
fun inflateAndroidView() {
    Column(modifier = Modifier.fillMaxWidth().wrapContentSize(), horizontalGravity = Alignment.Start) {
        Text(text = "AndroidView-Compose", modifier = Modifier.padding(all = 16.dp))
        TextView(text = "Hello World")
    }
}

@Composable
fun TextView(text: String) {
    escapeCompose {
        TextView(ContextAmbient.current).apply {
            setText("$text - InsideTextView")
        }
    }
}
it throws run time error
Copy code
java.lang.NullPointerException
        at androidx.ui.core.AndroidViewsHandler.onDescendantInvalidated(AndroidViewsHandler.kt:39)
        at android.view.HwApsImpl.isNonEmptyFrameCase(HwApsImpl.java:353)
        at android.view.ViewGroup.invalidateChild(ViewGroup.java:5984)
        at android.view.View.invalidateInternal(View.java:17751)
        at android.view.View.invalidate(View.java:17702)
        at android.view.View.setFrame(View.java:22267)
        at android.widget.TextView.setFrame(TextView.java:7293)
        at android.view.View.layout(View.java:22111)
        at androidx.ui.viewinterop.AndroidViewHolder.onLayout(ComposedView.kt:87)...
which is at
Copy code
layoutNode[child]!!.onInvalidate()
the same way tried for web view. which is also not working
p

pavi2410

06/08/2020, 4:44 PM
I'm using WebView like this
Copy code
@Preview(showDecoration = true)
@Composable
fun MarkDownParser() {
    val kotlin = """
   # Hello World
     
   **I'm your boss**
   
   ![haha](//hello.com)
   """.trimIndent()
    val ctx = ContextAmbient.current
    val html = parseMd(kotlin)

    Column {
        Text(text = html)
        AndroidView(view = webview(ctx, html))
    }
}

private fun webview(ctx: Context, html: String) =
    WebView(ctx).apply { loadData(html, "text/html", "utf-8") }
Can you check if the above snippet works for you?
c

coolchandrakumar

06/09/2020, 4:52 AM
@pavi2410 Thanks for sharing. With your code, still I’m facing the run time error which is related to
layoutNode[child]!!.onInvalidate()
Copy code
ext.kotlin_version = "1.3.72"
Here I am attached my gradle file
10 Views