用于光标位置更改的Android EditText侦听器

时间:2011-05-11 09:53:29

标签: android android-edittext

我在其中有一个包含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.EditTextCursorWatcher,例如

    <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"/> 

9 个答案:

答案 0 :(得分:27)

只需子类或扩展EditText类,并将以下代码添加到新创建的类:

 @Override 
 protected void onSelectionChanged(int selStart, int selEnd) {
        // Do ur task here.
    }

不要忘记将构造函数添加到子类中。 :)

答案 1 :(得分:12)

您可以实际收听选择更改,而无需继承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);

答案 2 :(得分:11)

我在不同版本的Android上调试了相关问题(随意评论您的发现,我会将它们添加到列表中)。

调查结果摘要:


4.1.6(三星设备)

仅在TEXT EDITS上调用

onSelectionChanged()


4.0.6(HTC Device)

4.0.4(由Samsung Note 1设备上的用户Arch1tect报告)

onSelectionChanged()会在光标更改(点击,移动等)上调用,但不会在文本编辑上调用。


如果您未收到有关版块更改(某些Android版本中的文字编辑)的通知,则必须使用TextWatcher进行此操作,例如afterTextChanged()方法

答案 3 :(得分:10)

哦,天哪,非常感谢这个想法。绝对没有理由不在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);        

}

答案 4 :(得分:2)

如果有人仍在寻找不对EditText进行子类化的解决方案:

(代码在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``
            }
        }
    })

答案 5 :(得分:1)

问题提问者最初将他们的答案发布到问题中。我将其移至答案中以使问题与答案分开。

第一步:创建子类

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.EditTextCursorWatcher,例如

    <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"/> 

答案 6 :(得分:0)

上述答案的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``                    
            }
        }
    });

答案 7 :(得分:0)

这是@Saeed Entezari postedExtension版本:

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)
            }
        }
    })
}

答案 8 :(得分:-1)

editText.doAfterTextChanged {
    doSomething(editText.selectionStart , editText.selectionEnd)  
}

editText.setOnClickListener {
    doSomething(editText.selectionStart , editText.selectionEnd)  
}