在EditText中,当点击特定文本子集时弹出对话框

6
发现两种解决方案-请参见所选答案。 当用户在EditText的特定区域中单击时,我想弹出一个对话框。我使用onClick来捕获点击事件。这部分有效:第一次用户点击EditText时,软键盘弹出,对话框不会弹出。随后的点击会弹出键盘,然后再弹出对话框(键盘消失)。 我怀疑这与EditText获得焦点有关。 以下是代码片段:
public class PrefixEditText extends EditText implements TextWatcher, OnClickListener
{
  public PrefixEditText (Context context)
  {
    super (context);
    setOnClickListener (this);
  }

  @Override
  public void onClick(View v)
  {
    int selStart = getSelectionStart();
    if (selStart < some_particular_pos)
      bring_up_dialog();
  }
}

重要提示:我不想完全禁用正常的EditText行为。我希望用户能够进行区域选择(以进行复制和粘贴)。我可能仍然希望其获得焦点(这样在使用物理键盘的人使用应用程序时就不会破坏模型)。单击设置光标位置也是可以的。因此,覆盖onTouch并阻止EditText的所有onTouch操作的解决方案对我无效。

更新:我发现了更多信息。如果EditText正在获取焦点,则会调用onFocusChange而不调用onClick。如果它已经具有焦点,则会调用onClick而不调用onFocusChange。

其次,可以通过调用

setInputType (InputType.TYPE_NULL);

在onFocusChange中这么做是有效的——键盘永远不会出现。但是在onClick中这样做(假设在点击之前隐藏了键盘),显然为时已晚——键盘显示出来然后又消失了。

下一个尝试的想法是在onTouch期间隐藏键盘。然而,我不敢去碰这段代码——似乎无论我想出什么方法都会非常依赖于EditText的未来版本。

您对此有何想法?

5个回答

3
也许这可以起作用。
 EditText e = new EditText(context);
    e.setOnFocusChangeListener(new OnFocusChangeListener() {

        public void onFocusChange(View v, boolean hasFocus) {
            // TODO Auto-generated method stub
        if(hasFocus)
        {
            //dialogue popup
        }
        }
    });

您可以使用e.hasFocus();,然后使用e.setFocusable(false);使其不再聚焦。
/////////////// 我的代码
e.setInputType(InputType.TYPE_NULL);

e.setOnClickListener(new OnClickListener() {

    public void onClick(View v) {
        // TODO Auto-generated method stub
        AlertDialog.Builder sa = new Builder(ctx);
        sa.create().setOnDismissListener(new OnDismissListener() {

            public void onDismiss(DialogInterface dialog) {
                // TODO Auto-generated method stub
                e.setInputType(InputType.TYPE_CLASS_TEXT);
            }
        });
        sa.show();
    }
});

你能提供一点关于你在思考什么的见解吗?谢谢。 - Peri Hartman
最初使用 e.setFocusable(false) 来设置焦点为 false,然后在 onclick 函数中,在弹出对话框后使其可聚焦,这样弹出窗口将按照您的期望顺序进行。 - Kishor datta gupta
没有显着的差别。它仍然在第一次失败并在后续的点击中弹出键盘。我将setFocusable调用放在创建对话框的调用周围。 - Peri Hartman
将输入类型设置为 null,这样键盘就不会出现,在点击后设置输入类型。 - Kishor datta gupta
相同的行为。明确一点,我在启动对话框后立即将输入类型设置回TYPE_CLASS_TEXT。可能太快了,但不确定在哪里设置它。 - Peri Hartman
显示剩余3条评论

2

尝试将onClick更改为onTouch以捕获点击事件

    this.editText.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                                //dialogue popup
            }
            return false;
        }
    });

尝试过这个。也许可以使用onTouch来做些什么,但似乎非常困难。您建议的做法会破坏getSelectionStart - 我非常确定onTouch发生在光标位置设置之前。 - Peri Hartman
感谢您的建议,帮助我确定了一个可行的解决方案。给你点赞。 - Peri Hartman

1

如果有帮助的话,可以尝试这个。第一次编辑文本框时将表现为普通的文本框,在某些情况下您可以根据需要显示对话框。

 EditText editText;
mTim_edittext.setOnFocusChangeListener(new OnFocusChangeListener() {

      public void onFocusChange(View v, boolean hasFocus) {

     if(!hasFocus){

    //statement


 if(condition){

AlertDialog diaBox = Utils.showErrorDialogBox(  "Term in Months Cannot be 0", context);                             
diaBox.show();
              }


            }
        }
    });

感谢您的建议,帮助我确定了一个可行的解决方案。给你点赞。 - Peri Hartman

1

经过许多实验,这里有两个可行的解决方案!我在我的两个设备上测试了它们——Nexus 7运行4.2.1,Kyocera C5170运行4.0.4。我更喜欢解决方案2。

解决方案1

对于第一个解决方案,技巧是在onTouch中确定光标位置,而不是在EditText执行其工作之前——特别是在弹出键盘之前。

另外一点说明:确保在您的清单中为弹出窗口设置android:windowSoftInputMode="stateHidden",否则您将会得到键盘和弹出窗口。

以下是整个代码:

public class ClickText extends EditText implements OnTouchListener
{
  public ClickText (Context context, AttributeSet attrs)
  {
    super (context, attrs);
    setOnTouchListener (this);
  }

  @Override
  public boolean onTouch (View v, MotionEvent event)
  {
    if (event.getActionMasked() == MotionEvent.ACTION_DOWN)
    {
      int line = getLayout().getLineForVertical ((int)event.getY());
      int onTouchCursorPos = getLayout().getOffsetForHorizontal (line, event.getX());
      if (onTouchCursorPos < 10) // or whatever condition
        showPopup (this); // or whatever you want to do
    }
    return false;
  }

  private void showPopup (final EditText text)
  {
    Intent intent = new Intent (getContext(), Popup.class);
    ((Activity)getContext()).startActivity (intent);
  }
}

解决方案2

这个方案实际上更简单,我认为也更好——副作用更少。

这里的诀窍是让EditText完成其所有点击处理,然后异步地覆盖它。大意是:等待触摸“松开”——MotionEvent.ACTION_UP——然后不是立即执行您的操作,而是将一个Runnable发布到事件队列中,在那里执行您的操作。

整个代码:

public class ClickText extends EditText implements OnTouchListener
{
  public ClickText (Context context, AttributeSet attrs)
  {
    super (context, attrs);
    setOnTouchListener (this);
  }

  @Override
  public boolean onTouch (View v, MotionEvent event)
  {
    switch (event.getActionMasked())
    {
      case MotionEvent.ACTION_UP:
      {
        post (new Runnable ()
        {
          // Do this asynch so that EditText can finish setting the selectino.
          @Override
          public void run()
          {
            int selStart = getSelectionStart();
            int selEnd = getSelectionEnd();

            // If selStart is different than selEnd, user has highlighed an area of
            // text; I chose to ignore the click when this happens.
            if (selStart == selEnd)
              if (selStart >= 0 && selStart < 10) // or whatever range you want
                showPopup (this);
          }            
        });

        break;
      }
    }

    return false;
  }

  private void showPopup (final EditText text)
  {
    Intent intent = new Intent (getContext(), Popup.class);
    ((Activity)getContext()).startActivity (intent);
  }
}

0
请使用以下代码片段。
this.editText.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                                //dialogue popup
            }
            return false;
        }
    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接