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

发布于 2024-10-10 17:04:31 字数 952 浏览 5 评论 0原文

我有一个可点击的自定义 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 被调用。

I have a custom TextView which is clickable. It defines its own onClick handler in order to change its appearance based on clicks. However if I then define a second onClick handler in my activity in order to do something based on the button being clicked, only one of the onClick functions is called. onClick is a void function - is there any way to say I didn't process this click, please pass it on to other onClick handlers?

To be more clear here is the code:

Inside MyCheckButton which extends TextView I have:

    setOnClickListener( mClickListener );

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

However I include MyCheckButton into my Activity, and of course I need to do something when its clicked so I attach another OnClickListener to it:

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

});

By calling setOnClickListener twice it appears that I am replacing the original listener so toggle() which changes the appearance is never called. How can I do something in my activity when this button is clicked if it is already using the onClick handler to change its appearance? I thought I would simply see both OnClickListeners getting called.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

冰葑 2024-10-17 17:04:31

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

This is a bit dirty, but the way I would do this if you need multiple listeners is to register one that knows about the other. The first one (the one that's actually registered) will then need to know when to delegate to the other listener based on the conditions of the event. Actually, in reality, there's no real need to have two OnClickListener classes. The second class can implement whatever interface you want. Additionally, there's no need to create a special interface for what you need.

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

Then, in your code for your activity, you would do this

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

Is there a reason this wouldn't work for you?

Alternatively, if you wanted, the second class could also implement the OnClickListener interface.

Additionally, if you need true bubbling, you could define your own interface that supports adding multiple click listeners to an intermediate class that happens to implement the OnClickListener interface. From there, in that class's onClick() method, you would iterate through the registered listeners calling the appropriate method.

动听の歌 2024-10-17 17:04:31

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

摘自:
如何为一个事件设置多个侦听器?< /a>

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

/**
 * 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 的调用都将经过此覆盖,并添加到列出并在事件触发时被调用。希望有帮助。

A cleaner approach would be to use the CompositeListener pattern.

Taken from:
how can I set up multiple listeners for one event?

You'd have to add this class in your project:

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

Then add this on your MyCheckButton

private CompositeListener clickListener = new CompositeListener();

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

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

Both your calls to setOnClickListener would go through this override, get added to the list and get called when the event is fired. Hope it helps.

李不 2024-10-17 17:04:31

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

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

从我的活动中实现它并重写 onMyClick 函数来执行我想要的任何操作,在 MyCheckButton 类中我需要在构造函数中传递 MyOnClickListener 保存它并调用listener.onMyClick在 onClick 处理程序内。

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

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

public class TVCheckButton extends TextView {

    private MyOnClickListener mListener;

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

        mListener = ???;
    }
}

Since it appears I can only have one onClickListener per View. What I think I have to do is define an interface:

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

Implement it from my activity and override the onMyClick function to do whatever I want and in the MyCheckButton class I'll need to pass a MyOnClickListener in the constructor save it and call listener.onMyClick inside the onClick handler.

Let me know if theres a better way. I considered using the onTouch handler in either the activity or the MyCheckButton class, but later if I add onTouch or onClick to either one I will get a difficult to notice bug.

My idea doesn't work because I don't know how to get a reference to the activity from my constructor:

public class TVCheckButton extends TextView {

    private MyOnClickListener mListener;

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

        mListener = ???;
    }
}
明明#如月 2024-10-17 17:04:31

由于只有一个 OnclickListener 在 Android 2.1 上工作[我不知道以后的版本],因此将视图设为私有和静态,并创建一个可以更改它的静态函数,例如

public class ExampleActivity extends 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);
 }

}

Since only one OnclickListener works on Android 2.1 [I don't know about later versions) make the view private and static and create a static function that can change it e.g.

public class ExampleActivity extends 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);
 }

}

离去的眼神 2024-10-17 17:04:31

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

A nice generic approach is to use a list of listeners, such as ListenerList and WeakListenerList from the Beryl library.

如何视而不见 2024-10-17 17:04:31

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

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

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

            }
        });
    }

For some reason I could not use the answers above so here is an alternative:
//I had all of this in one method where I had two buttons, and based on external factors one would be visible and other would not aka 'gone'. So, I had that checked out! Hope it helps someone!!

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

//some code and methods...

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

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

//some code and methods...

            }
        });
    }
笑叹一世浮沉 2024-10-17 17:04:31

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

private static Button myVirtualButton = new Button(context);

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

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

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

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

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

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

In the first class, define a virtual button:

private static Button myVirtualButton = new Button(context);

... and a public method to register it:

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

In the OnClickListener do whatever action is desired, and in the end, softclick the virtual button:

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

In the second class, define a button and its OnClickListener with whatever action is additionally desired.

Transmit the button to the first class via registerMyVirtualButton.
Upon clicking the object of the first class, both actions will be executed.

北笙凉宸 2024-10-17 17:04:31

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

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

    });

类似地,您的 TextView 应该将其放在 OnClick 侦听器上。

You can attach an OnClick listener to the button in the following way :

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

    });

Similarily, your TextView should have it's on OnClick listener.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文