android – 为NumberPicker捕获键盘’Done’

我有一个AlertDialog只有一些文本,一个NumberPicker,一个OK和一个取消.
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上执行“完成”操作来关闭对话框,就像按下了“OK”一样,因为只有一个小部件可以编辑.

看起来处理IME“Done”的最佳方法通常是在TextView上使用setOnEditorActionListener.但我没有任何TextView变量,而且NumberPicker显然没有暴露任何TextView或类似的编辑器回调. (也许NumberPicker包含一个带有常量ID的TextView,我可以使用findViewById进行搜索?)

NumberPicker.setOnValueChangedListener确实在“完成”操作时被触发,但在点击或轻拂数字列表时也会触发,这绝对不应该忽略对话框.

基于this问题,我尝试检出setOnKeyListener,但在使用软键盘时该界面根本没有触发.这并不奇怪,因为KeyEvent文档表明它对硬件事件的意义更大,而在最近的API中,软键盘根本不会发送它们.

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

编辑:从源的外观来看,NumberPicker布局确实包含EditText,但其id是包com.android.internal中的id / numberpicker_input.使用它并不容易,显然不鼓励.但似乎只有黑客可以获得我想要的行为方式.

解决方法

How can I connect the IME “Done” to my dialog’s “OK” action?

问题是,如果您没有在TextView小部件上设置一个侦听器,并且当前可以使用IME,则无法传递IME的事件.做你想做的事情的一种方法是将我们自己的逻辑挂钩到与IME一起工作的NumberPicker的孩子(就像你在问题的最后部分已经讨论过的那样).为了避免使用某些ID或其他布局技巧(可能有问题)来获取该窗口小部件,您可以使用贪婪的策略,将侦听器设置为NumberPicker中可以触发所需事件的任何窗口小部件(TextView或任何子类) of 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中的一个)并插入你自己的widget ID(这将使得获取对小部件的引用是一个简单的任务).这样现在更容易实现,但从长远来看维护起来不方便.

相关文章

AdvserView.java package com.earen.viewflipper; import an...
ImageView的scaleType的属性有好几种,分别是matrix(默认)...
文章浏览阅读8.8k次,点赞9次,收藏20次。本文操作环境:win1...
文章浏览阅读1.2w次,点赞15次,收藏69次。实现目的:由main...
文章浏览阅读3.8w次。前言:最近在找Android上的全局代理软件...
文章浏览阅读2.5w次,点赞17次,收藏6次。创建项目后,运行项...