5

我有一个可点击的自定义 TextView。它定义了自己的 onClick 处理程序,以便根据点击更改其外观。但是,如果我随后在我的活动中定义第二个 onClick 处理程序以便根据被单击的按钮执行某些操作,则只会调用其中一个 onClick 函数。onClick 是一个无效函数 - 有什么办法可以说我没有处理此点击,请将其传递给其他 onClick 处理程序?

更清楚的是这里的代码:

在扩展 TextView 的 MyCheckButton 内部,我有:

    setOnClickListener( mClickListener );

    private OnClickListener mClickListener = new OnClickListener() {
        public void onClick(View v) {
            toggle();
        }
    };

但是,我将 MyCheckButton 包含到我的 Activity 中,当然我需要在单击它时做一些事情,所以我将另一个 OnClickListener 附加到它:

MyCheckButton button= (MyCheckButtonButton) findViewById(R.id.cb);
button.setOnClickListener(new OnClickListener(){
    @Override
    public void onClick(View v) {
        // do something in the app
    }

});

通过调用 setOnClickListener 两次,看来我正在替换原始侦听器,因此永远不会调用更改外观的 toggle()。如果单击此按钮已在使用 onClick 处理程序更改其外观,我该如何在我的活动中执行某些操作?我以为我只会看到两个 OnClickListeners 都被调用。

4

8 回答 8

7

这有点脏,但是如果您需要多个侦听器,我会这样做的方法是注册一个知道另一个侦听器的侦听器。第一个(实际注册的)然后需要知道什么时候根据事件的条件委托给另一个侦听器。实际上,实际上并没有真正需要有两个OnClickListener类。第二个类可以实现你想要的任何接口。此外,无需为您的需要创建一个特殊的界面。

public class MyClickListener implements OnClickListener{
  private SomeCustomClass mSecondListener = new SomeCustomClass();
  public void onClick(View v){
    if (needToForward){
      mSecondListener.handleClick(v);
    }else{
      //handle the click
    }
  }
}

然后,在您的活动代码中,您将执行此操作

MyClickListener lstn = new MyClickListener();
mCheckBox.setOnClickListener(lstn);

这对你不起作用有什么原因吗?

或者,如果您愿意,第二个类也可以实现该OnClickListener接口。

此外,如果您需要真正的冒泡,您可以定义自己的接口,该接口支持将多个点击侦听器添加到恰好实现该OnClickListener接口的中间类。从那里,在该类的onClick()方法中,您将遍历调用适当方法的注册侦听器。

于 2011-01-06T23:33:14.177 回答
4

更清洁的方法是使用该CompositeListener模式。

取自: 如何为一个事件设置多个侦听器?

您必须在项目中添加此类:

/**
 * Aux class to collect multiple click listeners.
 */
class CompositeListener implements OnClickListener {
    private List<OnClickListener> registeredListeners = new ArrayList<OnClickListener>();

    public void registerListener (OnClickListener listener) {
        registeredListeners.add(listener);
    }

    @Override
    public void onClick(View v) {

        for(OnClickListener listener:registeredListeners) {
            listener.onClick(View v);
        }
    }
}

然后将其添加到您的MyCheckButton

private CompositeListener clickListener = new CompositeListener();

public MyCheckButton()
{
    super.setOnClickListener(clickListener); //multi event listener initialization
}

@Override
public void setOnClickListener(OnClickListener l) {
    clickListener.registerListener(l);
}

您的两个调用都setOnClickListener将通过此覆盖,被添加到列表中并在事件触发时被调用。希望能帮助到你。

于 2016-03-25T15:43:07.937 回答
1

因为看起来我每个视图只能有一个 onClickListener。我认为我要做的是定义一个接口:

public interface MyOnClickListener {
    public void onMyClick(View v);
}

从我的活动中实现它并覆盖 onMyClick 函数来做任何我想做的事情,在 MyCheckButton 类中,我需要在构造函数中传递一个 MyOnClickListener 保存它并在 onClick 处理程序中调用 listener.onMyClick。

让我知道是否有更好的方法。我考虑在 Activity 或 MyCheckButton 类中使用 onTouch 处理程序,但稍后如果我将 onTouch 或 onClick 添加到任何一个,我都会遇到一个难以注意到的错误。

我的想法行不通,因为我不知道如何从构造函数中获取对活动的引用:

public class TVCheckButton extends TextView {

    private MyOnClickListener mListener;

    public TVCheckButton(Context context, AttributeSet attrs) {
        super(context, attrs);

        mListener = ???;
    }
}
于 2011-01-06T20:54:55.627 回答
1

由于只有一个 OnclickListener 适用于 Android 2.1 [我不知道更高版本)使视图私有和静态并创建一个可以更改它的静态函数,例如

公共类 ExampleActivity 扩展 Activity{

private SomeOtherclass someOtherClass;
private static Button b_replay;

 public void onCreate(Bundle savedInstanceState){
     someOtherClass = new SomeOtherclass();

   b_replay = (Button) findViewById(R.id.b_replay);
   b_replay.setOnClickListener(someOtherClass);
 }

 public static void changeReplayText(String text){
   b_replay.setText(text);
 }

}

于 2012-01-25T11:34:41.027 回答
0

一个很好的通用方法是使用侦听器列表,例如Beryl 库中的ListenerListWeakListenerList

于 2012-04-24T08:39:43.610 回答
0

出于某种原因,我无法使用上面的答案,所以这里有一个替代方案://我在一个方法中拥有所有这些,我有两个按钮,并且基于外部因素,一个是可见的,另一个不会又名“消失”。所以,我检查了!希望它可以帮助某人!

Button b = (Button) findViewById(R.id.b_reset);
Button breakk = (Button) findViewById(R.id.b_break);

    if ((findViewById(R.id.b_reset)).getVisibility() == View.VISIBLE) {
        b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

//一些代码和方法...

            }
        });
    } else if ((findViewById(R.id.b_break)).getVisibility() == View.VISIBLE) {

        breakk.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

//一些代码和方法...

            }
        });
    }
于 2017-07-17T04:59:08.453 回答
0

在第一个类中,定义一个虚拟按钮:

private static Button myVirtualButton = new Button(context);

...以及注册它的公共方法:

public static void registerMyVirtualButton(Button b) { myVirtualButton = b;}

OnClickListener执行所需的任何操作中,最后,软单击虚拟按钮:

if (myVirtualButton!=null) { myVirtualButton.callOnClick(); }

在第二个类中,定义一个按钮及其OnClickListener任何额外需要的操作。

通过 将按钮传递给头等舱registerMyVirtualButton。单击第一个类的对象后,将执行两个动作。

于 2017-12-20T15:14:04.230 回答
-3

您可以通过以下方式将 OnClick 侦听器附加到按钮:

Button button= (Button) findViewById(R.id.button1);
    button.setOnClickListener(new OnClickListener(){
      @Override
      public void onClick(View v) {
          // do something
      }

    });

同样,您的 TextView 应该在 OnClick 侦听器上。

于 2011-01-06T19:33:10.440 回答