在自定义android组件中将视图模型中的方法作为表达式传递
我有一个自定义组件,它将状态更改侦听器作为输入,在OnClick方法中触发onChecked和onUnchecked事件。现在我想将此组件迁移到数据绑定,并尝试将onClick方法分离为以下两种方法:在自定义android组件中将视图模型中的方法作为表达式传递,android,xml,xml-parsing,android-databinding,Android,Xml,Xml Parsing,Android Databinding,我有一个自定义组件,它将状态更改侦听器作为输入,在OnClick方法中触发onChecked和onUnchecked事件。现在我想将此组件迁移到数据绑定,并尝试将onClick方法分离为以下两种方法: <declare-styleable name="CustomView"> <attr name="onChecked" format="string" /> <attr name="onUnc
<declare-styleable name="CustomView">
<attr name="onChecked" format="string" />
<attr name="onUnchecked" format="string" />
<declare-styleable name="ToggleImageView">
private interface OnStateChangedListener {
fun onChecked(v: View)
fun onUnchecked(v: View) {}
}
class DeclaredOnStateChangedListener(
private val mHostView: View,
private val checkedMethodName: String,
private val uncheckedMethodName: String
) :
OnStateChangedListener {
private var mResolvedMethod: Method? = null
private var mResolvedContext: Context? = null
private fun resolveMethod(contextInput: Context?, mMethodName: String) {
var context = contextInput
while (context != null) {
try {
if (!context.isRestricted) {
val method = context.javaClass.getMethod(
mMethodName,
View::class.java
)
mResolvedMethod = method
mResolvedContext = context
return
}
} catch (e: NoSuchMethodException) {
// Failed to find method, keep searching up the hierarchy.
}
context = if (context is ContextWrapper) {
context.baseContext
} else {
// Can't search up the hierarchy, null out and fail.
null
}
}
val id = mHostView.id
val idText =
if (id == View.NO_ID) "" else " with id '" + mHostView.context.resources.getResourceEntryName(
id
) + "'"
throw IllegalStateException(
"Could not find method " + mMethodName
+ "(View) in a parent or ancestor Context for android:onClick "
+ "attribute defined on view " + mHostView.javaClass + idText
)
}
private fun doExecuteMathod(mMethodName: String, v: View) {
if (mResolvedMethod == null) {
resolveMethod(mHostView.context, mMethodName)
}
try {
mResolvedMethod!!.invoke(mResolvedContext, v)
} catch (e: IllegalAccessException) {
throw IllegalStateException(
"Could not execute non-public method for app:${mMethodName}", e
)
} catch (e: InvocationTargetException) {
throw IllegalStateException(
"Could not execute method for app:${mMethodName}", e
)
}
}
override fun onChecked(v: View) {
if (checkedMethodName.isNotEmpty())
doExecuteMathod(checkedMethodName, v)
}
override fun onUnchecked(v: View) {
if (uncheckedMethodName.isNotEmpty())
doExecuteMathod(uncheckedMethodName, v)
}
}
其中DeclaredInstalledListener的实现方式如下:
<declare-styleable name="CustomView">
<attr name="onChecked" format="string" />
<attr name="onUnchecked" format="string" />
<declare-styleable name="ToggleImageView">
private interface OnStateChangedListener {
fun onChecked(v: View)
fun onUnchecked(v: View) {}
}
class DeclaredOnStateChangedListener(
private val mHostView: View,
private val checkedMethodName: String,
private val uncheckedMethodName: String
) :
OnStateChangedListener {
private var mResolvedMethod: Method? = null
private var mResolvedContext: Context? = null
private fun resolveMethod(contextInput: Context?, mMethodName: String) {
var context = contextInput
while (context != null) {
try {
if (!context.isRestricted) {
val method = context.javaClass.getMethod(
mMethodName,
View::class.java
)
mResolvedMethod = method
mResolvedContext = context
return
}
} catch (e: NoSuchMethodException) {
// Failed to find method, keep searching up the hierarchy.
}
context = if (context is ContextWrapper) {
context.baseContext
} else {
// Can't search up the hierarchy, null out and fail.
null
}
}
val id = mHostView.id
val idText =
if (id == View.NO_ID) "" else " with id '" + mHostView.context.resources.getResourceEntryName(
id
) + "'"
throw IllegalStateException(
"Could not find method " + mMethodName
+ "(View) in a parent or ancestor Context for android:onClick "
+ "attribute defined on view " + mHostView.javaClass + idText
)
}
private fun doExecuteMathod(mMethodName: String, v: View) {
if (mResolvedMethod == null) {
resolveMethod(mHostView.context, mMethodName)
}
try {
mResolvedMethod!!.invoke(mResolvedContext, v)
} catch (e: IllegalAccessException) {
throw IllegalStateException(
"Could not execute non-public method for app:${mMethodName}", e
)
} catch (e: InvocationTargetException) {
throw IllegalStateException(
"Could not execute method for app:${mMethodName}", e
)
}
}
override fun onChecked(v: View) {
if (checkedMethodName.isNotEmpty())
doExecuteMathod(checkedMethodName, v)
}
override fun onUnchecked(v: View) {
if (uncheckedMethodName.isNotEmpty())
doExecuteMathod(uncheckedMethodName, v)
}
}
我的问题当我想这样使用它时:我在绑定方面遇到了问题,并且项目没有构建
<CustomView
....
app:onChecked="@{()->viewModel.doNavigate()}"
app:onUnchecked="@{()-> viewModel.removeFromFavorite()}"
.... />
你知道如何在Android视图中使用onClick属性吗