2013-02-10 60 views
7

我有一个AlertDialog只有一些文字,一个NumberPicker,一个确定,一个取消。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“完成”的最佳方式通常是setOnEditorActionListenerTextView上。但是我没有任何TextView变量,并且NumberPicker也没有显示任何TextView或类似的编辑器回调。 (也许NumberPicker包含TextView以恒定的ID,我可以搜索使用findViewById?)

NumberPicker.setOnValueChangedListener不会被触发的“完成”的行动,但它也激发敲击或轻弹数,名单时绝对不应该关闭对话框。

根据this问题,我试着检查出setOnKeyListener,但是在使用软键盘时该界面根本没有触发。这并不令人惊讶,因为KeyEvent文档表明它对硬件事件的意义更大,在最近的API中软键盘根本不会发送它们。

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

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

+0

您是否尝试过任何与旧版Android兼容的自定义数字选择器?我相信你可以访问他们的'EditText'编号。你可以检查这个:https://github.com/SimonVT/android-numberpicker – Naveen 2013-02-20 06:30:54

回答

8

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

问题是,如果在当前与IME配合使用的TextView小部件上没有设置侦听器,则无法传递IME的事件。一种做你想做的事的方法是把我们自己的逻辑与IME工作的孩子联系起来(就像你在问题的最后部分已经讨论过的那样)。为了避免使用某些ID或其他布局技巧(可能有问题)来获取该小部件,可以使用贪婪策略,将侦听器设置为可触发期望事件的任何小部件(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); 
     } 
    } 

其他可能的(合理的)解决方案(如纳文在他的评论中已经提到)是使用NumberPicker的港口之一(或者从SDK中修改一个),并插入你自己的窗口小部件id(这将使获得对窗口小部件的引用成为一项简单的任务)。现在更容易实施,但从长远来看不方便。

+0

你认为使用TextViews列表是否值得麻烦,而不是仅仅在找到一个搜索循环时打破搜索循环? – aschepler 2013-02-20 13:29:41

+0

@aschepler这是值得的麻烦(只是为了安全)。我不确定是否允许(由android联盟)这样做,但设备制造商可以制作自己的NumberPicker窗口小部件,其中包含一个或多个附加的TextViews/EditTexts(例如,为什么不是头部?)输入'EditText'。此外,拥有该列表并不会降低性能(递归方法将解析一个小视图层次结构)或内存消耗(因为这些小部件已经在布局中,您只是存储对它们的引用)。 – Luksprog 2013-02-20 13:39:28

+0

创建自定义的'NumberPicker'并做同样的事情会更好吗?代码将更加清洁 – Jin35 2013-02-21 12:56:28

0

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

如果你需要一个NumberPicker,这是因为你想要滚动到你需要的值的功能,而不是输入它(虽然这是可能的)。如果你想输入你使用EditText的值,你将能够实现你所需要的而没有问题。

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