如何以编程方式触发Onclick事件?

Zak*_*ria 23 android onclicklistener

我有一个带有2个线性布局的自定义视图:第一个是视图的标题,第二个是详细信息视图.

在自定义视图中,已定义标题Linearlayout的OnClickListener:当它触发时,它会折叠/展开第二个linearlayout.

我想要做的是为我的标题的OnClickListener事件添加更多功能(即:折叠/展开第二个布局并显示Toast).

我无法修改自定义视图的源代码.我尝试设置一个新的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();
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

我想要做的是在我的活动中为已经定义的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();
            }
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

waq*_*lam 81

您可以通过编程方式在视图上引发单击事件以将其调用OnClickListener如下:

view.performClick();
Run Code Online (Sandbox Code Playgroud)

现在,如果你在第一个布局的OnClickListener下的第二个布局上调用它,那么我希望它应该做的魔术


Vla*_*mir 9

简单的解决方案是获取原始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();
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

可悲的是,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();
        }
});
Run Code Online (Sandbox Code Playgroud)

我没有理由正确地处理所有异常,但这足以让我有所了解.它可能看起来很乱,但它实际上只有5行新代码来解决你的问题.

  • 没问题=)好吧,通过反射获取字段和调用方法比"正常"更加昂贵,但在这种情况下差异很小,不会影响任何事情.但是有一个警告 - 因为字段是通过名称访问的,如果它的名称发生了变化(可能不会发生),这段代码将停止工作 - 它不会崩溃,但是会抛出`NoSuchFieldException`,并且`preDefinedListener `将结束`null`,这使得侦听器设置为完整的布局. (2认同)

Vad*_*dim 8

从SDK 15开始,您只需调用方法:

view.callOnClick()
Run Code Online (Sandbox Code Playgroud)