我正在尝试使用软键盘的完成按钮通过数据绑定激活方法。就像onClick一样。有没有办法做到这一点?
示例:
<EditText
android:id="@+id/preSignUpPg2EnterPhone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
onOkInSoftKeyboard="@{(v) -> viewModel.someMethod()}"
/>
onOkInSoftKeyboard不存在......有什么东西可以创造这种行为吗?
谢谢!
答案 0 :(得分:10)
我不会声称自己是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();
}
}
});
}
}
答案 1 :(得分:3)
katlin使用Kotlin产生:
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
内创建一个关于类型的显式变量,则可以将该变量作为绑定的参数传递。 (或只使用一个类)
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"/>
答案 2 :(得分:2)
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
可以为 null,因此通过将 KeyEvent
放在那里使 ?
可以为 null。
答案 3 :(得分:0)
您只需使用EditText动作完成事件。
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
public class Demo {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document originalDocument = db.parse(new File("input.xml"));
Node originalRoot = originalDocument.getDocumentElement();
Document copiedDocument = db.newDocument();
Node copiedRoot = copiedDocument.importNode(originalRoot, true);
copiedDocument.appendChild(copiedRoot);
}
}
<EditText
android:id="@+id/preSignUpPg2EnterPhone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionDone"
/>
答案 4 :(得分:0)
您可以通过实现setOnEditorActionListener
到Edittext来直接调用loginModel在ViewModel内部的方法,并引用binging类
loginFragmentBinding.etPassword.setOnEditorActionListener(TextView.OnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
loginViewModel.login()
return@OnEditorActionListener true
}
false
})
答案 5 :(得分:0)
Android 框架已经实现了这一点。看看TextViewBindingAdapter
您会看到这些属性,the documentation 有点掩盖了这意味着什么,但简而言之:
attribute
= 当此属性出现在布局文件中时type
= 然后在这个类中寻找实现method
= 在类型定义的类中具有此名称的方法有关这方面的更多信息,请查看 this blog post。
答案 6 :(得分:-1)
正如我自己看这个,这里有一个更简单的版本,其中函数直接从数据绑定中调用:
在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)}"