8

我有一个AlertDialog只有一些文本、一个NumberPicker、一个确定和一个取消。

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 上的“完成”操作可以关闭对话框,就像按下“确定”一样,因为只有一个小部件要编辑。

看起来处理 IME “完成”的最佳方法通常是setOnEditorActionListenerTextView. 但我没有任何TextView变量,NumberPicker也没有明显公开任何TextView或类似的编辑器回调。(也许NumberPicker包含一个TextView我可以搜索使用的恒定 ID findViewById?)

NumberPicker.setOnValueChangedListener确实会在“完成”操作上触发,但在点击或轻弹数字列表时也会触发,这绝对不应该关闭对话框。

基于这个问题,我尝试检查setOnKeyListener,但使用软键盘时该界面根本没有触发。并不完全令人惊讶,因为KeyEvent文档表明它更多地用于硬件事件,并且在最近的 API 中,软键盘根本不会发送它们。

如何将 IME“完成”连接到对话框的“确定”操作?

编辑:从源代码的外观来看,NumberPicker布局确实包含 a EditText,但它的 idid/numberpicker_input在 package 中com.android.internal。使用它并不容易,显然是不鼓励的。但似乎可能只有破解方法来获得我想要的行为。

4

2 回答 2

9

如何将 IME“完成”连接到对话框的“确定”操作?

问题是,如果您没有在TextView当前与 IME 一起使用的小部件上设置侦听器,则无法传递 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(这将使参考小部件一个简单的任务)。这现在更容易实现,但从长远来看不方便维护。

于 2013-02-20T10:31:01.420 回答
0

我的搜索和实验也结果是空手而归。也就是说,我不会鼓励这种行为,因为它没有多大意义。

如果您需要 NumberPicker,那是因为您想要滚动到所需值的功能,而不是输入它(尽管这是可能的)。如果您想输入值,您将使用 EditText 并且您将能够毫无问题地实现您需要的内容。

或者,您必须从源代码复制 NumberPicker 实现,然后根据您的需要进行更改(通过添加 ime 选项来实现)。

于 2013-02-20T09:50:41.817 回答