Android - 两个onClick监听器和一个按钮

问题描述 投票:4回答:8

我有一个可点击的自定义TextView。它定义了自己的onClick处理程序,以便根据点击次数更改其外观。但是,如果我在我的活动中定义第二个onClick处理程序,以便根据被单击的按钮执行某些操作,则只调用其中一个onClick函数。 onClick是一个void函数 - 有没有办法说我没有处理这个点击,请把它传递给其他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被调用。

android event-bubbling
8个回答
5
投票

这有点脏,但是如果你需要多个监听器我会这样做的方法是注册一个知道另一个的人。第一个(实际注册的那个)将需要知道何时根据事件的条件委托给另一个监听器。实际上,实际上,没有必要有两个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()方法中,您将遍历已注册的侦听器,并调用适当的方法。


3
投票

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

取自:how can I set up multiple listeners for one event?

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

/**
 * 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的调用都会经过这个覆盖,被添加到列表中并在事件被触发时被调用。希望能帮助到你。


1
投票

因为看起来每个View只能有一个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 = ???;
    }
}

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);
 }

}


0
投票

一个很好的通用方法是使用一个监听器列表,例如来自ListenerListWeakListenerListBeryl library


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) {

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

            }
        });
    }

0
投票

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

private static Button myVirtualButton = new Button(context);

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

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

OnClickListener中做任何需要的动作,最后,点击虚拟按钮:

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

在第二节课中,定义一个按钮及其OnClickListener,其中包含额外需要的任何动作。

通过registerMyVirtualButton将按钮传送到第一堂课。单击第一个类的对象后,将执行这两个操作。


-2
投票

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

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

    });

类似地,你的TextView应该在OnClick监听器上。

© www.soinside.com 2019 - 2024. All rights reserved.