23

Android のビューには getOnClickListener() が必要です。このようにして、一時的な OnClickListener をビューに割り当てることができます。私はそれを次のように使いたいです:

private View.OnClickListener oldListener;

public void assignTempListener(View view) {
    oldListener = view.getOnClickListener(); // doesn't exist

    view.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // some code

            v.setOnClickListener(oldListener);
        }
    });
}

問題は、この関数が存在しないことです。すべての種類のビューを assignTempListener に渡すことができるため、ビューから継承してこのメ​​ソッドを作成することもできません。これを使用する別の方法はありますか?

編集:私のコードで小さな間違いを犯しました。

4

5 に答える 5

27

これを行うには... REFLECTIONを使用します。*ドラムロール*

このルートは危険をはらんでいます。

クラスの内部構造はいつでも変更される可能性があるため、お勧めしませんが、本当にやむを得ない場合は、Android 4.2.2 までの現在の方法を次に示します。

/**
 * Returns the current View.OnClickListener for the given View
 * @param view the View whose click listener to retrieve
 * @return the View.OnClickListener attached to the view; null if it could not be retrieved
 */
public View.OnClickListener getOnClickListener(View view) {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        return getOnClickListenerV14(view);
    } else {
        return getOnClickListenerV(view);
    }
}

//Used for APIs lower than ICS (API 14)
private View.OnClickListener getOnClickListenerV(View view) {
    View.OnClickListener retrievedListener = null;
    String viewStr = "android.view.View";
    Field field;

    try {
        field = Class.forName(viewStr).getDeclaredField("mOnClickListener");
        retrievedListener = (View.OnClickListener) field.get(view);
    } catch (NoSuchFieldException ex) {
        Log.e("Reflection", "No Such Field.");
    } catch (IllegalAccessException ex) {
        Log.e("Reflection", "Illegal Access.");
    } catch (ClassNotFoundException ex) {
        Log.e("Reflection", "Class Not Found.");
    }

    return retrievedListener;
}

//Used for new ListenerInfo class structure used beginning with API 14 (ICS)
private View.OnClickListener getOnClickListenerV14(View view) {
    View.OnClickListener retrievedListener = null;
    String viewStr = "android.view.View";
    String lInfoStr = "android.view.View$ListenerInfo";

    try {
        Field listenerField = Class.forName(viewStr).getDeclaredField("mListenerInfo");
        Object listenerInfo = null;

        if (listenerField != null) {
            listenerField.setAccessible(true);
            listenerInfo = listenerField.get(view);
        }

        Field clickListenerField = Class.forName(lInfoStr).getDeclaredField("mOnClickListener");

        if (clickListenerField != null && listenerInfo != null) {
            retrievedListener = (View.OnClickListener) clickListenerField.get(listenerInfo);
        }
    } catch (NoSuchFieldException ex) {
        Log.e("Reflection", "No Such Field.");
    } catch (IllegalAccessException ex) {
        Log.e("Reflection", "Illegal Access.");
    } catch (ClassNotFoundException ex) {
        Log.e("Reflection", "Class Not Found.");
    }

    return retrievedListener;
}
于 2013-02-21T02:51:12.640 に答える
2

答えはとても簡単です

OnClickListener ocl = new OnClickListener { 
    @Override
    public void onClick(View view) {
        clickableView.performClick();
    }
}

1 つのことを除いて onclicklistener のすべての機能 - ビューを引数として渡すことはできずclickableView、ハンドラーになりますが、ほとんどの場合はそれで十分です

于 2018-06-21T10:29:16.893 に答える
1

使用する

 oldListener = new view.OnClickListener() {

        @Override
        public void onClick(View v) {
            // some code

          v.setOnClickListener(oldListener);
        }
    });

それ以外の

oldListener = view.getOnClickListener(); // doesn't exist

getOnClickListenerは、現在の API のViewまたはButtonのメソッドではありません。詳細については、ドキュメントを参照してください。

http://developer.android.com/reference/android/view/View.OnClickListener.html

于 2012-06-25T09:54:48.247 に答える
0

ニート!

与えられた回答の oldListener は、それぞれの場合に再定義されており、古い状態であるか、別のふりをしている名前に関係なく定義が失われています。

この手法に従ってください: Android View オブジェクトの現在の onClickListener を取得します 。「古い」リスナーは抽象クラスの onClick メソッドで設定され、一時的なリスナーはスーパーへの呼び出しとともに setOnClickListener を使用して、次の場合に古いリスナーを (再) 設定します。または適宜

一時リスナー設定コードは、「古い」リスナーが何であるかを知る必要はありませんが、そのリスナーまたはそれらのリスナーの作成者がリスナーを抽象化し、onClick メソッドを使用してオンクリック リスナーを設定するには、なんらかの調整が必要です。 、要するに、プロトコルに従うことです。

例外的に、onclicklistener View メンバーの保護またはプライベート修飾子をバイパスしたい場合があります: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/ view/View.java#View.0mOnClickListener を実行し、少しhttp://www.jguru.com/faq/view.jsp?EID=321191 を実行すると、リスナーが取得されます。

もちろん、実際に機能する場合は、インストロスペクションアプローチを使用する独自の getOnClickListener、またはそのためのゲッターを作成することもできます:)

:)

于 2013-02-21T00:34:49.673 に答える