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();
}
}
});
}
簡単な解決策は、元の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()
がありませんが、取得するには reflection を使用できると思います。 フィールドmOnClickListener
( source )に保存されます。
これは、レイアウトに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行の新しいコードです。
以下のように、ビューでクリックイベントをプログラムで発生させて、OnClickListener
を呼び出すことができます。
view.performClick();
これで、最初のレイアウトのOnClickListenerの下の2番目のレイアウトでこれを呼び出すと、魔法を実行することを願っています
SDK 15以降では、メソッドを呼び出すことができます。
view.callOnClick()
CustomViewのコードを変更できない場合、以下のオプションがあります。
この方法では、既存のコードを保持し、機能を追加することもできます。