2011-01-06 69 views
4

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

更清楚这里是代码:

内MyCheckButton延伸的TextView我:

setOnClickListener(mClickListener); 

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

但是我包括MyCheckButton到我的活动,当然我需要的时候做一些它点击所以我将另一个OnClickListener它:

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

}); 

通过调用setOnClickListener两次看来,我取代了原来的侦听器,TOG从不调用改变外观的gle()。如果已经使用onClick处理程序更改其外观,那么在单击此按钮时如何在我的活动中执行某些操作?我想我只会看到两个OnClickListeners被调用。

+0

是的我认为你是对的,你也可以尝试在你的xml文件中给它一个onClick属性,并在设置onClickListener之后查看它是否仍然会调用你的方法。 – schwiz 2011-01-06 20:39:51

+0

我猜这不是一个事件冒泡问题,我的问题是你不能将两个OnClickListeners添加到相同的视图?这是其他地方的标准做法,所以我很困惑。 – Mark 2011-01-06 20:41:23

+0

如果我使用xml onClick,setOnClickListener将覆盖它。 – Mark 2011-01-06 20:49:27

回答

4

这是一个有点脏,但方式,如果你我会做这个需要多个听众的是注册一个知道另一个的人。第一个(实际注册的)根据事件的条件需要知道何时委派给其他听众。实际上,实际上并不需要有两个类。第二类可以实现你想要的任何接口。另外,不需要为你需要的创建一个特殊的界面。

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

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

-1

您可以通过以下方式附上一个onclick监听器按钮:

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

    }); 

相若方式,你的TextView应该有它在的OnClick听众。

+0

我的问题是两个OnClickListeners和一个'按钮',其中我的按钮是我扩展的TextView。 – Mark 2011-01-06 20:39:03

1

因为看起来我每个View只能有一个onClickListener。我想,我需要做的就是定义一个接口:

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

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

让我知道是否有更好的方法。我考虑在活动或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延伸活动{

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

}

2

更清洁的方法是使用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会经历这个覆盖,被添加到列表中,并在事件被触发时被调用。希望能帮助到你。

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做任何动作是期望的,并且在最后,softclick虚拟按钮:

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

在第二类中,定义一个按钮及其OnClickListener与任何动作是另外期望。

通过registerMyVirtualButton将按钮发送到第一类。 单击第一个类的对象后,这两个动作都会被执行。