Skip to content

Commit

Permalink
WIP Create a LayoutRunner binding function that works with AndroidX V…
Browse files Browse the repository at this point in the history
…iewBindings.

Related to #984.
  • Loading branch information
zach-klippenstein committed Feb 26, 2020
1 parent 9e98500 commit 52db35c
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 7 deletions.
2 changes: 2 additions & 0 deletions kotlin/samples/hello-workflow/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ android {

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildFeatures.viewBinding = true
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,26 @@
*/
package com.squareup.sample.helloworkflow

import android.view.View
import android.widget.TextView
import android.view.LayoutInflater
import com.squareup.sample.helloworkflow.databinding.HelloGoodbyeLayoutBinding
import com.squareup.workflow.ui.ContainerHints
import com.squareup.workflow.ui.LayoutRunner
import com.squareup.workflow.ui.LayoutRunner.Companion.bind
import com.squareup.workflow.ui.ViewBinding

class HelloLayoutRunner(view: View) : LayoutRunner<HelloWorkflow.Rendering> {
private val messageView: TextView = view.findViewById(R.id.hello_message)
class HelloLayoutRunner(
private val binding: HelloGoodbyeLayoutBinding
) : LayoutRunner<HelloWorkflow.Rendering> {

override fun showRendering(
rendering: HelloWorkflow.Rendering,
containerHints: ContainerHints
) {
messageView.text = rendering.message
messageView.setOnClickListener { rendering.onClick() }
binding.helloMessage.text = rendering.message
binding.helloMessage.setOnClickListener { rendering.onClick() }
}

companion object : ViewBinding<HelloWorkflow.Rendering> by bind(
R.layout.hello_goodbye_layout, ::HelloLayoutRunner
HelloGoodbyeLayoutBinding::inflate, ::HelloLayoutRunner
)
}
2 changes: 2 additions & 0 deletions kotlin/workflow-ui/core-android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ apply from: rootProject.file('.buildscript/configure-dokka.gradle')
android rootProject.ext.defaultAndroidConfig

dependencies {
compileOnly "androidx.databinding:viewbinding:4.0.0-beta01"

api project(':workflow-core')
api project(':workflow-ui:core-common')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import android.view.ViewGroup
import androidx.annotation.LayoutRes
import kotlin.reflect.KClass

typealias ViewBindingInflater<BindingT> = (LayoutInflater, ViewGroup, Boolean) -> BindingT

/**
* A delegate that implements a [showRendering] method to be called when a workflow rendering
* of type [RenderingT] is ready to be displayed in a view inflated from a layout resource
Expand Down Expand Up @@ -82,6 +84,32 @@ interface LayoutRunner<RenderingT : Any> {
}
}

class ViewBindingBinding<BindingT : androidx.viewbinding.ViewBinding, RenderingT : Any>(
override val type: KClass<RenderingT>,
private val bindingInflater: ViewBindingInflater<BindingT>,
private val runnerConstructor: (BindingT) -> LayoutRunner<RenderingT>
) : ViewBinding<RenderingT> {
override fun buildView(
initialRendering: RenderingT,
initialContainerHints: ContainerHints,
contextForNewView: Context,
container: ViewGroup?
): View {
return LayoutInflater.from(container?.context ?: contextForNewView)
.cloneInContext(contextForNewView)
// This !! is problematic. Can we use the overload that only takes an inflater?
.let { bindingInflater(it, container!!, false) }
.also { binding ->
binding.root.bindShowRendering(
initialRendering,
initialContainerHints,
runnerConstructor.invoke(binding)::showRendering
)
}
.root
}
}

companion object {
/**
* Creates a [ViewBinding] that inflates [layoutId] to show renderings of type [RenderingT],
Expand All @@ -92,6 +120,11 @@ interface LayoutRunner<RenderingT : Any> {
noinline constructor: (View) -> LayoutRunner<RenderingT>
): ViewBinding<RenderingT> = Binding(RenderingT::class, layoutId, constructor)

inline fun <BindingT : androidx.viewbinding.ViewBinding, reified RenderingT : Any> bind(
noinline bindingInflater: ViewBindingInflater<BindingT>,
noinline constructor: (BindingT) -> LayoutRunner<RenderingT>
): ViewBinding<RenderingT> = ViewBindingBinding(RenderingT::class, bindingInflater, constructor)

/**
* Creates a [ViewBinding] that inflates [layoutId] to "show" renderings of type [RenderingT],
* with a no-op [LayoutRunner]. Handy for showing static views.
Expand Down

0 comments on commit 52db35c

Please sign in to comment.