在数据绑定中使用键盘上的完成按钮
Use Done button on Keyboard in Databinding
我正在尝试使用软键盘的完成按钮通过数据绑定激活方法。就像点击一样。有办法吗?
示例:
<EditText
android:id="@+id/preSignUpPg2EnterPhone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
onOkInSoftKeyboard="@{(v) -> viewModel.someMethod()}"
/>
onOkInSoftKeyboard 不存在...是否有创建此行为的方法?
谢谢!
我不会自称是 onEditorAction()
或软键盘方面的专家。也就是说,假设您使用 Firoz Memon 建议的堆栈溢出问题的解决方案,您可以实现它。即使有其他更好的解决方案,这也可以让您了解如何添加自己的事件处理程序。
您需要一个采用某种处理程序的绑定适配器。假设您有一个像这样的空监听器:
public class OnOkInSoftKeyboardListener {
void onOkInSoftKeyboard();
}
那么你需要一个BindingAdapter:
@BindingAdapter("onOkInSoftKeyboard") // I like it to match the listener method name
public static void setOnOkInSoftKeyboardListener(TextView view,
final OnOkInSoftKeyboardListener listener) {
if (listener == null) {
view.setOnEditorActionListener(null);
} else {
view.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public void onEditorAction(TextView v, int actionId, KeyEvent event) {
// ... solution to receiving event
if (somethingOrOther) {
listener.onOkInSoftKeyboard();
}
}
});
}
}
正如我自己看到的那样,这是一个更简单的版本,其中直接从数据绑定调用该函数:
在您的 ViewModel 中使用此函数:
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
return false; // if you want the default action of the actionNext or so on
return true; // if you want to intercept
}
并且在布局中:
android:onEditorAction="@{(view,actionId,event) -> viewModel.onEditorAction(view,actionId,event)}"
使用 Kotlin,kapt 产生:
e: [kapt] An exception occurred: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
****/ data binding error ****msg:Listener class kotlin.jvm.functions.Function1 with method invoke did not match signature of any method viewModel::signIn
(因为viewModel::signIn
是KFunction1
类型)所以我们不能使用方法引用。但是,如果我们在 viewModel
中创建一个明确类型的变量,那么我们可以将该变量作为绑定的参数传递。 (或者只使用 class)
Bindings.kt:
@BindingAdapter("onEditorEnterAction")
fun EditText.onEditorEnterAction(f: Function1<String, Unit>?) {
if (f == null) setOnEditorActionListener(null)
else setOnEditorActionListener { v, actionId, event ->
val imeAction = when (actionId) {
EditorInfo.IME_ACTION_DONE,
EditorInfo.IME_ACTION_SEND,
EditorInfo.IME_ACTION_GO -> true
else -> false
}
val keydownEvent = event?.keyCode == KeyEvent.KEYCODE_ENTER
&& event.action == KeyEvent.ACTION_DOWN
if (imeAction or keydownEvent)
true.also { f(v.editableText.toString()) }
else false
}
}
MyViewModel.kt:
fun signIn(password: String) {
Toast.makeText(context, password, Toast.LENGTH_SHORT).show()
}
val signIn: Function1<String, Unit> = this::signIn
layout.xml:
<EditText
android:id="@+id/password"
app:onEditorEnterAction="@{viewModel.signIn}"
android:imeOptions="actionDone|actionSend|actionGo"
android:singleLine="true"/>
您可以通过对 Edittext 实施 setOnEditorActionListener
来直接调用 ViewModel 中的登录方法,参考 binging class
loginFragmentBinding.etPassword.setOnEditorActionListener(TextView.OnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
loginViewModel.login()
return@OnEditorActionListener true
}
false
})
Android 框架已经实现了这个。看看TextViewBindingAdapter
您会看到这些属性,the documentation 有点掩盖了这意味着什么,但简而言之:
attribute
= 当此属性出现在布局文件中时
type
= 然后在这个 class 中寻找实现
method
= 在类型 中定义的 class 中具有此名称的方法
有关此的更多信息,请查看 this blog post。
Kotlin,无需编写自定义绑定适配器
在布局中,
<EditText
...
android:onEditorAction="@{(view, actionId, event) -> viewModel.onDoneClicked(view, actionId, event)}" />
视图模型
fun onDoneClicked(view: View, actionId: Int, event: KeyEvent?): Boolean {
if(actionId == EditorInfo.IME_ACTION_DONE) {
// handle here
return true
}
return false
}
注意: event
可以为空,因此通过将 ?
放在那里使 KeyEvent
可以为空。
我正在尝试使用软键盘的完成按钮通过数据绑定激活方法。就像点击一样。有办法吗?
示例:
<EditText
android:id="@+id/preSignUpPg2EnterPhone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
onOkInSoftKeyboard="@{(v) -> viewModel.someMethod()}"
/>
onOkInSoftKeyboard 不存在...是否有创建此行为的方法?
谢谢!
我不会自称是 onEditorAction()
或软键盘方面的专家。也就是说,假设您使用 Firoz Memon 建议的堆栈溢出问题的解决方案,您可以实现它。即使有其他更好的解决方案,这也可以让您了解如何添加自己的事件处理程序。
您需要一个采用某种处理程序的绑定适配器。假设您有一个像这样的空监听器:
public class OnOkInSoftKeyboardListener {
void onOkInSoftKeyboard();
}
那么你需要一个BindingAdapter:
@BindingAdapter("onOkInSoftKeyboard") // I like it to match the listener method name
public static void setOnOkInSoftKeyboardListener(TextView view,
final OnOkInSoftKeyboardListener listener) {
if (listener == null) {
view.setOnEditorActionListener(null);
} else {
view.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public void onEditorAction(TextView v, int actionId, KeyEvent event) {
// ... solution to receiving event
if (somethingOrOther) {
listener.onOkInSoftKeyboard();
}
}
});
}
}
正如我自己看到的那样,这是一个更简单的版本,其中直接从数据绑定调用该函数:
在您的 ViewModel 中使用此函数:
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
return false; // if you want the default action of the actionNext or so on
return true; // if you want to intercept
}
并且在布局中:
android:onEditorAction="@{(view,actionId,event) -> viewModel.onEditorAction(view,actionId,event)}"
使用 Kotlin,kapt 产生:
e: [kapt] An exception occurred: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
****/ data binding error ****msg:Listener class kotlin.jvm.functions.Function1 with method invoke did not match signature of any method viewModel::signIn
(因为viewModel::signIn
是KFunction1
类型)所以我们不能使用方法引用。但是,如果我们在 viewModel
中创建一个明确类型的变量,那么我们可以将该变量作为绑定的参数传递。 (或者只使用 class)
Bindings.kt:
@BindingAdapter("onEditorEnterAction")
fun EditText.onEditorEnterAction(f: Function1<String, Unit>?) {
if (f == null) setOnEditorActionListener(null)
else setOnEditorActionListener { v, actionId, event ->
val imeAction = when (actionId) {
EditorInfo.IME_ACTION_DONE,
EditorInfo.IME_ACTION_SEND,
EditorInfo.IME_ACTION_GO -> true
else -> false
}
val keydownEvent = event?.keyCode == KeyEvent.KEYCODE_ENTER
&& event.action == KeyEvent.ACTION_DOWN
if (imeAction or keydownEvent)
true.also { f(v.editableText.toString()) }
else false
}
}
MyViewModel.kt:
fun signIn(password: String) {
Toast.makeText(context, password, Toast.LENGTH_SHORT).show()
}
val signIn: Function1<String, Unit> = this::signIn
layout.xml:
<EditText
android:id="@+id/password"
app:onEditorEnterAction="@{viewModel.signIn}"
android:imeOptions="actionDone|actionSend|actionGo"
android:singleLine="true"/>
您可以通过对 Edittext 实施 setOnEditorActionListener
来直接调用 ViewModel 中的登录方法,参考 binging class
loginFragmentBinding.etPassword.setOnEditorActionListener(TextView.OnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
loginViewModel.login()
return@OnEditorActionListener true
}
false
})
Android 框架已经实现了这个。看看TextViewBindingAdapter
您会看到这些属性,the documentation 有点掩盖了这意味着什么,但简而言之:
attribute
= 当此属性出现在布局文件中时type
= 然后在这个 class 中寻找实现
method
= 在类型 中定义的 class 中具有此名称的方法
有关此的更多信息,请查看 this blog post。
Kotlin,无需编写自定义绑定适配器
在布局中,
<EditText
...
android:onEditorAction="@{(view, actionId, event) -> viewModel.onDoneClicked(view, actionId, event)}" />
视图模型
fun onDoneClicked(view: View, actionId: Int, event: KeyEvent?): Boolean {
if(actionId == EditorInfo.IME_ACTION_DONE) {
// handle here
return true
}
return false
}
注意: event
可以为空,因此通过将 ?
放在那里使 KeyEvent
可以为空。