我有一个EditText对话框。 EditText在创建时已经填充。当用户将光标放在文本的某些部分上或附近时,将弹出Toast。
我的问题是监听光标位置的变化。另一个post提出同样的问题,并且接受的解决方案是
您可以覆盖onSelectionChanged(int selStart,int selEnd)以获得有关选择更改的通知。如果移动光标,也会调用它(在本例中为selStart == selEnd)
onSelectionChanged (int selStart, int selEnd)是TextView类的受保护方法。如何覆盖它?
解决方案对我有用...嗨大师,谢谢你的回复,它的工作原理。如果其他人有兴趣,这就是我做的详细...
第一步:创建子类
package com.example;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.EditText;
import android.widget.Toast;
public class EditTextCursorWatcher extends EditText {
public EditTextCursorWatcher(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public EditTextCursorWatcher(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EditTextCursorWatcher(Context context) {
super(context);
}
@Override
protected void onSelectionChanged(int selStart, int selEnd) {
Toast.makeText(getContext(), "selStart is " + selStart + "selEnd is " + selEnd, Toast.LENGTH_LONG).show();
}
}
第二步:参考布局文件中的类(例如main.xml(通过我的是自定义对话框布局))。不要忘记使用完整的包名(在本例中为com.example.EditText Cursor Watcher,egg
<com.example.EditTextCursorWatcher
android:id="@+id/etEdit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="top"
android:minLines="5"
android:inputType="textMultiLine"/>
只需子类化或扩展EditText类,并将以下代码添加到新创建的类中:
@Override
protected void onSelectionChanged(int selStart, int selEnd) {
// Do ur task here.
}
不要忘记将构造函数添加到子类中。 :)
实际上,您可以在不对EditText
进行子类化的情况下聆听选择更改。它有点复杂但仍然易于管理。要做到这一点,你需要在文本中添加SpanWatcher
并处理选择范围的更改。
final SpanWatcher watcher = new SpanWatcher() {
@Override
public void onSpanAdded(final Spannable text, final Object what,
final int start, final int end) {
// Nothing here.
}
@Override
public void onSpanRemoved(final Spannable text, final Object what,
final int start, final int end) {
// Nothing here.
}
@Override
public void onSpanChanged(final Spannable text, final Object what,
final int ostart, final int oend, final int nstart, final int nend) {
if (what == Selection.SELECTION_START) {
// Selection start changed from ostart to nstart.
} else if (what == Selection.SELECTION_END) {
// Selection end changed from ostart to nstart.
}
}
};
editText.getText().setSpan(watcher, 0, 0, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
我在不同版本的Android上调试了一个相关问题(随意评论你的发现,我会将它们添加到列表中)。
调查结果摘要:
4.1.6(三星设备)
onSelectionChanged()
仅在TEXT EDITS上被调用。
4.0.6(HTC设备)
4.0.4(由Samsung Note 1设备上的用户Arch1tect报告)
onSelectionChanged()
会在光标变化(点击,移动等)上调用,但不会在文本编辑上调用。
在上面没有通知部分更改(某些Android版本中的文本编辑)的情况下,您必须使用TextWatcher
执行此操作,例如在afterTextChanged()
方法中。
哦,天哪,非常感谢这个想法。绝对没有理由不在SDK中使用此功能。我有一个快速的子类来实现这个想法,但在选择更改时添加了监听器的附加功能。希望它有用
public class EditTextSelectable extends EditText {
public interface onSelectionChangedListener {
public void onSelectionChanged(int selStart, int selEnd);
}
private List<onSelectionChangedListener> listeners;
public EditTextSelectable(Context context) {
super(context);
listeners = new ArrayList<onSelectionChangedListener>();
}
public EditTextSelectable(Context context, AttributeSet attrs){
super(context, attrs);
listeners = new ArrayList<onSelectionChangedListener>();
}
public EditTextSelectable(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
listeners = new ArrayList<onSelectionChangedListener>();
}
public void addOnSelectionChangedListener(onSelectionChangedListener o){
listeners.add(o);
}
protected void onSelectionChanged(int selStart, int selEnd){
for (onSelectionChangedListener l : listeners)
l.onSelectionChanged(selStart, selEnd);
}
如果有人仍在寻找不对EditText
进行Subclass的解决方案:
(代码在kotlin)
editText.setAccessibilityDelegate(object : View.AccessibilityDelegate() {
override fun sendAccessibilityEvent(host: View?, eventType: Int) {
super.sendAccessibilityEvent(host, eventType)
if (eventType == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED){
// here you can access selection of the editText
// with `editText.selectionStart`
// and `editText.selectionEnd``
}
}
})
以上答案的java版本,
mEtEditor.setAccessibilityDelegate(new View.AccessibilityDelegate(){
/**
* Sends an accessibility event of the given type. If accessibility is not
* enabled this method has no effect.
* <p>
* The default implementation behaves as {@link View#sendAccessibilityEvent(int)
* View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
* been set.
* </p>
*
* @param host The View hosting the delegate.
* @param eventType The type of the event to send.
* @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
*/
@Override
public void sendAccessibilityEvent(View host, int eventType) {
super.sendAccessibilityEvent(host, eventType);
if (eventType == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED){
// here you can access selection of the editText
// with `editText.selectionStart`
// and `editText.selectionEnd``
}
}
});
这是Extension
的@Saeed Entezari posted版本:
fun EditText.setSelectionChangedListener(onSelectionChangedListener: (editText: EditText, selectionStart: Int, selectionEnd: Int) -> Unit) {
setAccessibilityDelegate(object : View.AccessibilityDelegate() {
override fun sendAccessibilityEvent(host: View?, eventType: Int) {
super.sendAccessibilityEvent(host, eventType)
if (eventType == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED){
val editText = this@setSelectionChangedListener
onSelectionChangedListener.invoke(editText, editText.selectionStart, editText.selectionEnd)
}
}
})
}