我有一个只有一些文本的AlertDialog
、一个NumberPicker
、一个OK和一个Cancel。
package org.dyndns.schep.example;
import android.os.Bundler;
import android.view.View;
import android.widget.NumberPicker;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
public class FooFragment extends DialogFragment {
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mParent = (MainActivity) activity;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
mParent.setFoo(foo());
}
})
.setNegativeButton(android.R.string.cancel, null);
View view = getActivity().getLayoutInflater.inflate(
R.layout.dialog_foo, null);
mPicker = (NumberPicker) view.findViewById(R.id.numberPicker1);
mPicker.setValue(mParent.getFoo());
builder.setView(view);
return builder.create();
}
public int foo() {
return mPicker.getValue();
}
private MainActivity mParent;
private NumberPicker mPicker;
}
(我知道,这个对话框还没有做它应该做的事情来保持暂停和恢复的状态。)
我希望软键盘或其他输入法上的"完成"操作可以像按下"确定"一样关闭对话框,因为只有一个小部件可以编辑。
看起来处理IME"完成"的最佳方法通常是在TextView
上使用setOnEditorActionListener
。但我没有任何TextView
变量,而且NumberPicker
显然没有公开任何TextView
或类似的编辑器回调。(也许NumberPicker
包含一个具有恒定ID的TextView
,我可以使用findViewById
搜索?)
NumberPicker.setOnValueChangedListener
确实会在"完成"操作时触发,但它也会在点击或轻弹数字列表时触发,这绝对不应该关闭对话框。
基于这个问题,我尝试查看setOnKeyListener
,但在使用软键盘时,该界面根本没有触发。这并不完全令人惊讶,因为KeyEvent
文档表明它更多地用于硬件事件,而在最近的API中,软键盘根本不会发送它们。
如何将输入法"完成"连接到对话框的"确定"操作?
编辑:从源代码的外观来看,NumberPicker
布局确实包含EditText
,但其id是包com.android.internal
中的id/numberpicker_input
。使用它并不容易,而且显然是不鼓励的。但似乎只有破解的方法才能得到我想要的行为。
如何将输入法"完成"连接到对话框的"确定"操作?
问题是,如果当前使用IME的TextView
小部件上没有设置侦听器,则无法传递IME的事件。做你想做的事情的一种方法是将我们自己的逻辑连接到NumberPicker
的子项上,该子项与IME一起工作(就像你在问题的最后一部分中已经谈到的那样)。为了避免使用某些id或其他布局技巧(这可能会有问题)来获取该小部件,您可以使用贪婪策略,将侦听器设置为NumberPicker
中任何可能触发所需事件的小部件(TextViews
或TextView
的任何子类)。类似这样的东西:
private AlertDialog mCurrentDialog;
private List<TextView> mTargets = new ArrayList<TextView>();
private OnEditorActionListener mListener = new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
// if a child of NumberPicker triggers the DONE editor event
// get a reference to the positive button(which you use in your
// code) and click it
mCurrentDialog.getButton(Dialog.BUTTON_POSITIVE).performClick();
}
return false;
}
};
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// ...
mPicker = (NumberPicker) view.findViewById(R.id.numberPicker1);
mPicker.setValue(mParent.getFoo());
// clear any previous targets
mTargets.clear();
// find possible targets in the NumberPicker
findTextViews(mPicker);
// setup those possible targets with our own logic
setupEditorListener();
builder.setView(view);
// get a reference to the current showed dialog
mCurrentDialog = builder.create();
return mCurrentDialog;
}
方法在哪里:
private void findTextViews(ViewGroup parent) {
final int count = parent.getChildCount();
for (int i = 0; i < count; i++) {
final View child = parent.getChildAt(i);
if (child instanceof ViewGroup) {
findTextViews((ViewGroup) child);
} else if (child instanceof TextView) {
mTargets.add((TextView) child);
}
}
}
private void setupEditorListener() {
final int count = mTargets.size();
for (int i = 0; i < count; i++) {
final TextView target = mTargets.get(i);
target.setOnEditorActionListener(mListener);
}
}
另一个可能的(也是合理的)解决方案(就像Naveen在他的评论中提到的那样)是使用NumberPicker
类的一个端口(或修改SDK中的端口),并插入您自己的小部件ID(这将使引用小部件成为一项简单的任务)。这将更容易实现,但从长远来看不方便维护。
我的搜索和实验结果也是两手空空。也就是说,我不会鼓励这种行为,因为这没有多大意义。
如果你需要NumberPicker,那是因为你想要滚动到你需要的值的功能,而不是输入它(尽管这是可能的)。如果你想输入值,你可以使用EditText,这样你就可以毫无问题地实现你需要的东西。
或者,您必须从源代码复制NumberPicker实现,然后根据需要进行更改(通过添加ime选项进行fx)。