Mặc dù tôi đã phát hiện ra một số câu trả lời hay dựa vào ràng buộc dữ liệu, tôi không thấy bất kỳ điều gì sẽ đi đến toàn bộ với cách tiếp cận đó - theo nghĩa là cho phép phân giải đoạn trong khi cho phép định nghĩa bố cục không có đoạn trong XML.
Vì vậy, giả sử ràng buộc dữ liệu được kích hoạt, đây là một giải pháp chung tôi có thể đề xuất; Một chút dài nhưng nó chắc chắn hoạt động (với một số hãy cẩn thận):
Bước 1: Thực hiện OnClick tùy chỉnh
Điều này sẽ chạy một tìm kiếm nhận biết phân đoạn thông qua các bối cảnh được liên kết với chế độ xem khai thác (ví dụ: nút):
// CustomOnClick.kt
@file:JvmName("CustomOnClick")
package com.example
import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import java.lang.reflect.Method
fun onClick(view: View, methodName: String) {
resolveOnClickInvocation(view, methodName)?.invoke(view)
}
private data class OnClickInvocation(val obj: Any, val method: Method) {
fun invoke(view: View) {
method.invoke(obj, view)
}
}
private fun resolveOnClickInvocation(view: View, methodName: String): OnClickInvocation? =
searchContexts(view) { context ->
var invocation: OnClickInvocation? = null
if (context is Activity) {
val activity = context as? FragmentActivity
?: throw IllegalStateException("A non-FragmentActivity is not supported (looking up an onClick handler of $view)")
invocation = getTopFragment(activity)?.let { fragment ->
resolveInvocation(fragment, methodName)
}?: resolveInvocation(context, methodName)
}
invocation
}
private fun getTopFragment(activity: FragmentActivity): Fragment? {
val fragments = activity.supportFragmentManager.fragments
return if (fragments.isEmpty()) null else fragments.last()
}
private fun resolveInvocation(target: Any, methodName: String): OnClickInvocation? =
try {
val method = target.javaClass.getMethod(methodName, View::class.java)
OnClickInvocation(target, method)
} catch (e: NoSuchMethodException) {
null
}
private fun <T: Any> searchContexts(view: View, matcher: (context: Context) -> T?): T? {
var context = view.context
while (context != null && context is ContextWrapper) {
val result = matcher(context)
if (result == null) {
context = context.baseContext
} else {
return result
}
}
return null
}
Lưu ý: dựa trên cách triển khai Android ban đầu (xem https://android.googlesource.com/pl platform / frameworks / base / + / a175a5b / core / java / android / view / View.java # 3025 )
Bước 2: Ứng dụng khai báo trong tệp bố cục
Sau đó, trong XML nhận biết ràng buộc dữ liệu:
<layout>
<data>
<import type="com.example.CustomOnClick"/>
</data>
<Button
android:onClick='@{(v) -> CustomOnClick.onClick(v, "myClickMethod")}'
</Button>
</layout>
Hãy cẩn thận
- Giả sử
FragmentActivity
thực hiện dựa trên 'hiện đại'
- Chỉ có thể tra cứu phương pháp của đoạn "trên cùng" (tức là cuối cùng ) trong ngăn xếp (mặc dù điều đó có thể được sửa, nếu cần)