【问题标题】:Android intercept paste\copy\cut on editTextAndroid在editText上拦截粘贴\复制\剪切
【发布时间】:2013-02-05 11:26:06
【问题描述】:

如何拦截此类事件?

当用户尝试将一些文本粘贴到我的EditText 中时,我需要添加一些逻辑,我知道我可以使用TextWatcher,但是这个入口点对我不利,因为我只需要在粘贴的情况下拦截,而不是每次都拦截用户按下我的EditText的时间,

【问题讨论】:

  • 很好的挑战。看我的回答。

标签: android textview android-edittext textwatcher


【解决方案1】:

使用 API 似乎无能为力:android paste event

Source reading to the rescue!

我深入研究了TextView 的Android 源代码(EditText 是具有一些不同配置的TextView)并发现用于提供剪切/复制/粘贴选项的菜单只是修改后的@987654323 @ (source)。

对于普通的上下文菜单,视图必须创建菜单 (source),然后在回调方法 (source) 中处理交互。

由于处理方法是public,我们可以简单地通过扩展EditText 并覆盖该方法以对不同的操作作出反应来挂钩它。这是一个示例实现:

import android.content.Context;
import android.util.AttributeSet;
import android.widget.EditText;
import android.widget.Toast;

/**
 * An EditText, which notifies when something was cut/copied/pasted inside it.
 * @author Lukas Knuth
 * @version 1.0
 */
public class MonitoringEditText extends EditText {

    private final Context context;

    /*
        Just the constructors to create a new EditText...
     */
    public MonitoringEditText(Context context) {
        super(context);
        this.context = context;
    }

    public MonitoringEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }

    public MonitoringEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
    }

    /**
     * <p>This is where the "magic" happens.</p>
     * <p>The menu used to cut/copy/paste is a normal ContextMenu, which allows us to
     *  overwrite the consuming method and react on the different events.</p>
     * @see <a href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3_r1/android/widget/TextView.java#TextView.onTextContextMenuItem%28int%29">Original Implementation</a>
     */
    @Override
    public boolean onTextContextMenuItem(int id) {
        // Do your thing:
        boolean consumed = super.onTextContextMenuItem(id);
        // React:
        switch (id){
            case android.R.id.cut:
                onTextCut();
                break;
            case android.R.id.paste:
                onTextPaste();
                break;
            case android.R.id.copy:
                onTextCopy();
        }
        return consumed;
    }

    /**
     * Text was cut from this EditText.
     */
    public void onTextCut(){
        Toast.makeText(context, "Cut!", Toast.LENGTH_SHORT).show();
    }

    /**
     * Text was copied from this EditText.
     */
    public void onTextCopy(){
        Toast.makeText(context, "Copy!", Toast.LENGTH_SHORT).show();
    }

    /**
     * Text was pasted into the EditText.
     */
    public void onTextPaste(){
        Toast.makeText(context, "Paste!", Toast.LENGTH_SHORT).show();
    }
}

现在,当用户使用剪切/复制/粘贴时,会显示Toast(当然你也可以做其他事情)。

巧妙的是,这适用于 Android 1.5,您无需重新创建上下文菜单(如上述链接问题中所建议的那样),这将 保持平台外观不变(例如使用 HTC Sense)。

【讨论】:

【解决方案2】:

有一个更简单的方法,虽然不是 100% 可靠。

将 TextChangedListener 添加到您的编辑框:

EditText et = (EditText) mView.findViewById(R.id.yourEditText);
et.addTextChangedListener(new TextWatcher() {

  @Override
  public void onTextChanged(CharSequence s, int start, int before, int count) {
     if (count > 2) toast("text was pasted");
  }

  @Override
  public void beforeTextChanged(CharSequence s, int start, int count, int after) {

  }

  public void afterTextChanged(Editable s) {
               
  }
});

如果文本更改超过 2 个字符,您可以假定它已被粘贴(有些笑脸占用两个字符)。

当然,当用户粘贴1或2个字符时它不会检测到粘贴,如果文本的变化是由其他东西触发的,它会错误地报告粘贴。

但对于大多数目的,它可以完成工作 ?

【讨论】:

  • 如果您的编辑文本仅限于 1 个字符并且您想复制到多个编辑文本(例如每个数字带有 1 个 et 的代码),则此方法不起作用
  • tiagocarvalho92:是的,描述中写了。
  • 这似乎没问题。因为我会考虑与系统集成,并可能使用自动填充或自动读取消息的 OTP 提供程序。这是一个更好的用户体验。还有一个“粘贴”按钮可以解决问题。在那种情况下,真的没有理由被限制在 EditText 上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-07
  • 1970-01-01
  • 1970-01-01
  • 2010-12-10
  • 2013-05-13
相关资源
最近更新 更多