25

2つの線形レイアウトを持つカスタムビューがあります。1つはビューのヘッダーで、2つ目は詳細ビューです。

カスタムビューでは、ヘッダーLinearlayoutのOnClickListenerがすでに定義されています。起動すると、2番目のlinearlayoutが折りたたまれたり展開されたりします。

私がやりたいのは、ヘッダーのOnClickListenerイベントに機能を追加することです(つまり、2番目のレイアウトを折りたたみ/展開してトーストを表示します)。

カスタムビューのソースコードを変更できません。新しいOnClickListenerを設定しようとしましたが、最初のイベント(折りたたみ/展開)が非表示になります。

これをどのように実装すればよいですか?

マイカスタムビューのソースコード:

public class ExpandoLayout extends ViewGroup
{
    /* some declarations */
    private Linearlayout header;
    private linearlayout footer;

    /* some code */
    @override
    protected void onFinishInflate() {
    header= new LinearLayout(context);
    header.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                toggleExpand();
            }
        });
    }
}

私がやりたいのは、アクティビティですでに定義されているOnClickListenerイベントにコードを追加することです。そんな感じ:

public class myActivity extends Activity {
private Linearlayout myCustomView;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.rsdetail);
    myCustomView= (MyCustomView) findViewById(R.id.expanded);

    myCustomView.getChildAt(0).setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            if(v instanceof LinearLayout)
            {
                v.performClick();

                Toast.makeText(getActivity(), "ExpandoOnClickListener", 2000).show();
            }
        }
    });
}
4

4 に答える 4

86

ビューでクリックイベントをプログラムで発生させて、次のように呼び出すことができOnClickListenerます。

view.performClick();

これを最初のレイアウトのOnClickListenerの下の2番目のレイアウトで呼び出すと、魔法がかかることを願っています

于 2012-06-05T09:15:51.373 に答える
10

簡単な解決策は、元のOnClickListenerを取得してから、新しいOnClickListenerで起動することです。

final OnClickListener preDefinedListener = myCustomView.getChildAt(0).getOnClickListner();

myCustomView.getChildAt(0).setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        if(v instanceof LinearLayout)
        {
            preDefinedListener.onClick(v); // calls default (defined by MyCustomView)

            Toast.makeText(getActivity(), "ExpandoOnClickListener", 2000).show();
        }
    }
});

残念ながら、Viewはありませんが、リフレクションgetOnClickListner()を使用して取得できると思います。フィールドソース)に保存されます。 mOnClickListener

OnClickListenerレイアウトを定義するには、次のようにします。

OnClickListener tmpOnClickListener = null;
try {
    Class<View> cls = (Class<View>) Class.forName("android.view.View");
    Field fld = cls.getDeclaredField("mOnClickListener");
    fld.setAccessible(true); // because it is protected

    tmpOnClickListener = (OnClickListener) fld.get(myCustomView.getChildAt(0));

    fld.setAccessible(false); // restore it's original property
} catch (SecurityException e) {
    e.printStackTrace();
} catch (NoSuchFieldException e) {
    e.printStackTrace();
} catch (IllegalArgumentException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} 

final OnClickListener preDefinedListener = tmpOnClickListener;

if (preDefinedListener != null) {
    myCustomView.getChildAt(0).setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View paramView) {
            preDefinedListener.onClick(paramView);

            Toast.makeText(getActivity(), "ExpandoOnClickListener", Toast.LENGTH_LONG).show();
        }
});

私は本当にすべての例外を正しく処理することを気にしませんでしたが、それはアイデアを得るのに十分です。面倒に見えるかもしれませんが、実際には問題を解決するための新しいコードは5行です。

于 2012-06-05T10:12:24.707 に答える
8

SDK 15以降、メソッドを呼び出すことができます。

view.callOnClick()
于 2015-09-02T11:28:32.580 に答える
0

CustomViewのコードを変更できない場合は、以下のオプションがあります。

  • CustomViewを拡張します。
  • onClick()メソッドをオーバーライドし、これをリスナーとして最初のレイアウトにバインドします。
  • onClick()内で、最初にsuper.onClick()を呼び出してから、以下に機能を追加します。

このようにして、既存のコードを維持し、機能を追加することもできます。

于 2012-06-05T09:25:44.437 に答える