I have a custom view with 2 linear layouts: the first is the view's header and the second is the the details view.
我有一个自定义视图,有2个线性布局:第一个是视图的标题,第二个是详细信息视图。
In the custom view, the OnClickListener of the header Linearlayout is already defined: when it fires, it collapses/expandes the second linearlayout.
在自定义视图中,已定义标题Linearlayout的OnClickListener:当它触发时,它会折叠/展开第二个linearlayout。
What I want to do is to add more functionalities to my header's OnClickListener event (i.e.: collapse/expand the second layout and show a Toast).
我想要做的是为我的标题的OnClickListener事件添加更多功能(即:折叠/展开第二个布局并显示Toast)。
I can't modify the source code of the custom view. I tried to set a new OnClickListener but it hides the initial event (collapse/expand).
我无法修改自定义视图的源代码。我尝试设置一个新的OnClickListener,但它隐藏了初始事件(折叠/展开)。
How should I implement this?
我该如何实现呢?
The source code of My Custom View:
我的自定义视图的源代码:
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();
}
});
}
}
What I want to do is to add some code to the already defined OnClickListener event in my activity. Something like that:
我想要做的是在我的活动中为已经定义的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 个解决方案
#1
9
Simple solution would be to get original OnClickListener and then fire it in new one:
简单的解决方案是获取原始的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();
}
}
});
Sadly, View
does not have getOnClickListner()
, but I guess you can use reflection to get it. It is stored in the field mOnClickListener
(source).
遗憾的是,View没有getOnClickListner(),但我想你可以使用反射来获取它。它存储在字段mOnClickListener(source)中。
This is how you can get OnClickListener
defined for your layout:
这是为您的布局定义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();
}
});
I didn't really bother to handle all exception correctly, but it's enough to get the idea. It might look messy, but it's actually just 5 lines of new code to solve your problem.
我没有真正麻烦地正确处理所有异常,但它足以得到这个想法。它可能看起来很乱,但它实际上只有5行新代码来解决你的问题。
#2
77
You can programmatically raise click event on a View to call it's OnClickListener
as below:
您可以以编程方式在视图上引发单击事件以将其命名为OnClickListener,如下所示:
view.performClick();
Now if you call this on your second layout under first layout's OnClickListener then i hope it should do the magic
现在,如果你在第一个布局的OnClickListener下的第二个布局上调用它,那么我希望它应该做的魔术
#3
7
Since SDK 15 you can just call method:
从SDK 15开始,您只需调用方法:
view.callOnClick()
#4
0
If you cannot modify the code of CustomView then you have the below option.
如果您无法修改CustomView的代码,则可以使用以下选项。
- Extend the CustomView.
- Override the onClick() method and bind this as a Listener to the first layout.
- Inside onClick() first call super.onClick() then add your additional functionality below.
扩展CustomView。
重写onClick()方法并将其绑定为第一个布局的侦听器。
在onClick()里面首先调用super.onClick(),然后在下面添加你的附加功能。
This way you are keeping the existing code and adding additional functionality as well.
这样您就可以保留现有代码并添加其他功能。
#1
9
Simple solution would be to get original OnClickListener and then fire it in new one:
简单的解决方案是获取原始的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();
}
}
});
Sadly, View
does not have getOnClickListner()
, but I guess you can use reflection to get it. It is stored in the field mOnClickListener
(source).
遗憾的是,View没有getOnClickListner(),但我想你可以使用反射来获取它。它存储在字段mOnClickListener(source)中。
This is how you can get OnClickListener
defined for your layout:
这是为您的布局定义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();
}
});
I didn't really bother to handle all exception correctly, but it's enough to get the idea. It might look messy, but it's actually just 5 lines of new code to solve your problem.
我没有真正麻烦地正确处理所有异常,但它足以得到这个想法。它可能看起来很乱,但它实际上只有5行新代码来解决你的问题。
#2
77
You can programmatically raise click event on a View to call it's OnClickListener
as below:
您可以以编程方式在视图上引发单击事件以将其命名为OnClickListener,如下所示:
view.performClick();
Now if you call this on your second layout under first layout's OnClickListener then i hope it should do the magic
现在,如果你在第一个布局的OnClickListener下的第二个布局上调用它,那么我希望它应该做的魔术
#3
7
Since SDK 15 you can just call method:
从SDK 15开始,您只需调用方法:
view.callOnClick()
#4
0
If you cannot modify the code of CustomView then you have the below option.
如果您无法修改CustomView的代码,则可以使用以下选项。
- Extend the CustomView.
- Override the onClick() method and bind this as a Listener to the first layout.
- Inside onClick() first call super.onClick() then add your additional functionality below.
扩展CustomView。
重写onClick()方法并将其绑定为第一个布局的侦听器。
在onClick()里面首先调用super.onClick(),然后在下面添加你的附加功能。
This way you are keeping the existing code and adding additional functionality as well.
这样您就可以保留现有代码并添加其他功能。