我该如何拦截这类事件?
当用户尝试将一些文本粘贴到我的 EditText
中时,我需要添加一些逻辑。我知道我可以使用 TextWatcher
,但是这个入口对我来说不好,因为我只需要在粘贴的情况下拦截,而不是每次用户按我的 EditText
。
我该如何拦截这类事件?
当用户尝试将一些文本粘贴到我的 EditText
中时,我需要添加一些逻辑。我知道我可以使用 TextWatcher
,但是这个入口对我来说不好,因为我只需要在粘贴的情况下拦截,而不是每次用户按我的 EditText
。
看起来通过使用 API,你似乎不能做太多事情:android paste event
我深入研究了 TextView
的 Android 源码(EditText
是一个带有不同配置的 TextView
),发现用于提供剪切、复制和粘贴选项的菜单只是修改过的 ContextMenu
(源代码)。
至于普通上下文菜单,视图必须创建菜单(源代码),然后在回调方法中处理交互(源代码)。
因为处理方法是 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)。
Context
实例(如果你的代码在Activity中,你可以传递this
)。 - Lukas KnuthTextWatcher
并记录更改。如果发生更改并且您获得了适当的剪切/复制/粘贴操作,则可以确定内容的哪个部分发生了更改。 - Lukas Knuth有一种更简单的方法,虽然不是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个字符时,它当然不会检测到粘贴,如果文本变化是由其他事情触发的,则会错误地报告粘贴。
但对于大多数目的而言,它足以完成工作。