69

ListView各行にEditTextコントロールがある場所があります。TextChangedListener各行に a を追加したい。1つは、どの行にEditTextあったかを示す余分なデータを含みます。問題は、getView呼び出されると複数TextWatchersが追加されることです。はconvertViewすでにTextWatcher(および別の行を指すもの) を持っているためです。

MyTextWatcher watcher = new MyTextWatcher(currentQuestion);
EditText text = (EditText)convertView.findViewById(R.id.responseText);
text.addTextChangedListener(watcher);

MyTextWatcherを実装する私のクラスですTextWatcher。テキストイベントを処理します。CurrentQuestion は、どの行に作用しているかを教えてくれます。ボックスに入力すると; の複数のインスタンスTextWatcherが呼び出されます。

TextWatchers新しいものを追加する前に削除する方法はありますか? メソッドが表示されますremoveTextChangedListenerが、特定のメソッドを渡す必要があり、既に存在するメソッドTextWatcherへのポインターを取得する方法がわかりません。TextWatcher

4

13 に答える 13

52

現在のEditTextインターフェイスを直接使用してこれを行う方法はありません。考えられる解決策は 2 つあります。

  1. 特定のインスタンスに何TextWatcherが追加されているかを常に把握できるように、アプリケーションを再設計します。EditText
  2. EditTextすべてのウォッチャーをクリアする可能性を拡張および追加します。

2 番目のアプローチの例を次に示しExtendedEditTextます。

public class ExtendedEditText extends EditText
{   
    private ArrayList<TextWatcher> mListeners = null;

    public ExtendedEditText(Context ctx)
    {
        super(ctx);
    }

    public ExtendedEditText(Context ctx, AttributeSet attrs)
    {
        super(ctx, attrs);
    }

    public ExtendedEditText(Context ctx, AttributeSet attrs, int defStyle)
    {       
        super(ctx, attrs, defStyle);
    }

    @Override
    public void addTextChangedListener(TextWatcher watcher)
    {       
        if (mListeners == null) 
        {
            mListeners = new ArrayList<TextWatcher>();
        }
        mListeners.add(watcher);

        super.addTextChangedListener(watcher);
    }

    @Override
    public void removeTextChangedListener(TextWatcher watcher)
    {       
        if (mListeners != null) 
        {
            int i = mListeners.indexOf(watcher);
            if (i >= 0) 
            {
                mListeners.remove(i);
            }
        }

        super.removeTextChangedListener(watcher);
    }

    public void clearTextChangedListeners()
    {
        if(mListeners != null)
        {
            for(TextWatcher watcher : mListeners)
            {
                super.removeTextChangedListener(watcher);
            }

            mListeners.clear();
            mListeners = null;
        }
    }
}

ExtendedEditTextxml レイアウトで使用する方法は次のとおりです。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <ua.inazaruk.HelloWorld.ExtendedEditText 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        android:text="header"
        android:gravity="center" /> 

</LinearLayout>
于 2011-06-07T19:39:37.880 に答える
30

EditText から TextWatcher を削除できます。まず、TextWatcher 宣言を editText.addTextChangedListener(...) の外に移動することをお勧めします。

protected TextWatcher yourTextWatcher = new TextWatcher() {

    @Override
    public void afterTextChanged(Editable s) {
        // your logic here
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // your logic here
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
       // your logic here
    }
};

その後、TextWather を少し簡単に設定できるようになります。

editText.addTextChangedListener(yourTextWatcher);

次のように TextWatcher を削除できます。

editText.removeTextChangedListener(yourTextWatcher);

必要に応じて別の設定を行います。

于 2013-02-12T13:46:53.320 に答える
12

また、解決策を見つけるのに多くの時間を費やし、最終的に以下のようなタグの助けを借りて解決しました。convertView のタグから参照を取得することで、以前の TextWatcher インスタンスを削除します。問題を完全に解決します。CustomAdapter ファイルで、次のような新しい内部クラスを設定します。

private static class ViewHolder {

        private TextChangedListener textChangedListener;
        private EditText productQuantity;

        public EditText getProductQuantity() {
            return productQuantity;
        }    

        public TextChangedListener getTextChangedListener() {
            return textChangedListener;
        }

        public void setTextChangedListener(TextChangedListener textChangedListener) {
            this.textChangedListener = textChangedListener;
        }
    }

次に、オーバーライドされた public View getView(int position, View convertView, ViewGroup parent) メソッドで、以下のようなロジックを実装します。

@Override
public View getView(int position, View convertView, ViewGroup parent) {

     EditText productQuantity;
    TextChangedListener textChangedListener;

    if(convertView==null) {
        LayoutInflater mInflater = (LayoutInflater)
                context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        convertView = mInflater.inflate(R.layout.cart_offer_item, parent, false);

        productQuantity=(EditText)convertView.findViewById(R.id.productQuantity);
        addTextChangedListener(viewHolder, position);
        convertView.setTag(viewHolder);
    }
    else
    {
        ViewHolder viewHolder=(ViewHolder)convertView.getTag();
        productQuantity=viewHolder.getProductQuantity();
        removeTextChangedListener(viewHolder);
        addTextChangedListener(viewHolder, position);
    }

    return convertView;
}



private void removeTextChangedListener(ViewHolder viewHolder)
{
    TextChangedListener textChangedListener=viewHolder.getTextChangedListener();
    EditText productQuantity=viewHolder.getProductQuantity();
    productQuantity.removeTextChangedListener(textChangedListener);
}

private void addTextChangedListener(ViewHolder viewHolder, int position)
{
    TextChangedListener textChangedListener=new TextChangedListener(position);
    EditText productQuantity=viewHolder.getProductQuantity();
    productQuantity.addTextChangedListener(textChangedListener);
    viewHolder.setTextChangedListener(textChangedListener);
}

次に、以下のように TextWatcher クラスを実装します。

private class TextChangedListener implements TextWatcher
{
    private int position;
    TextChangedListener(int position)
    {
        this.position=position;
    }
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }
    @Override
    public void afterTextChanged(Editable s) {
    Log.d("check", "text changed in EditText");

    }
}

convertView のタグから参照を取得することで、以前の TextWatcher インスタンスを削除します。

于 2015-01-20T09:18:40.343 に答える
4

この質問が出されてから長い時間が経ちましたが、誰かがこれを役に立つと思うかもしれません. Recyclerview の TextWatcher の問題は、ビューがリサイクルされる前に、TextWatcher が削除されていることを確認する必要があることです。そうしないと、TextWatcher のインスタンスが失われ、OnBindViewHolder() で removeTextChangedListener(textWatcher) を呼び出すと、TextWatcher の現在のインスタンスのみが削除されます。

この問題を解決する方法は、FocusChangedListener 内に TextChangedListener を追加することです。

editText.setOnFocusChangeListener(new OnFocusChangeListener() {          
public void onFocusChange(View v, boolean hasFocus) {
    if(hasFocus) {
        editText.addTextChangedListener(textWatcher)
    }
    else{
        editText.removeTextChangedListener(textWatcher)
    }
  }
});

このようにして、editText にフォーカスがない場合は確実にテキストウォッチャーが削除され、フォーカスがある場合は再度追加されます。そのため、recyclerview がリサイクルされると、editText から textChangeListener が削除されます。

于 2021-02-05T01:14:44.370 に答える
1

ここでわかるように: TextView の CodeSearch には、すべてのリスナーを削除する方法はありません。唯一の方法は、登録に使用したウォッチャーを提供することです。

なぜ他のリスナーがすでに登録されているのか、私はまだ完全には理解していません。ただし、EditText をサブクラス化し、addTextChangedListener(..) をオーバーライドして、追加されたすべての参照のコピーを保持し、スーパークラスの実装に委譲することができます。次に、すべてのリスナーを削除する追加のメソッドを提供することもできます。

さらに説明が必要な場合は、お問い合わせください。

于 2011-06-07T19:39:38.503 に答える
0

テキストウォッチャーを削除するために私がしたことは非常に簡単です。テキストウォッチャーを配置する配列を作成しました。

final TextWatcher[] textWatchers = new TextWatcher[3];

私はそれらを追加しました:

final int CURRENT_PIN_CHECK = 0, NEW_PIN = 1, CONFIRM_PIN_CHECK = 2;

textWatchers[CURRENT_PIN_CHECK] = returnTextWatcherCheckPIN(CURRENT_PIN_CHECK);
textWatchers[NEW_PIN] = returnTextWatcherCheckPIN(NEW_PIN);
textWatchers[CONFIRM_PIN_CHECK] = returnTextWatcherCheckPIN(CONFIRM_PIN_CHECK);

私の returnTextWatcherCheckPIN メソッドは、afterTextChanged で異なるチェッカー (4 つの editText すべてをチェックするための switchMethod) で textWatcher をインスタンス化します。

次に、テキストウォッチャーを削除するたびに、配列から参照しました。

etPin4.removeTextChangedListener(textWatchers[CURRENT_PIN_CHECK]);

デバッグ時に editText のリスナーのサイズを確認します。

ここに画像の説明を入力

削除されました!それは私の問題を解決しました!

于 2016-03-02T00:50:42.443 に答える