Reputation: 8281
One way to implement a button handler in Android since 1.6 is to put this in the XML where the button is declared . . .
...
android:onClick="TheButtonHandler"
...
and then just put the handler routine in the Activity class . . .
public void TheButtonHandler(View target) {
// ... button handler code
}
I have some Android code where all the buttons are created in Java at runtime during initialization, not in XML, but I want to do the same stuff as the above XML including specifying the button handler. N.B. that I want the button handlers to be in their own separate routines just as they would if I were declaring them in the XML in the above example, I don't want button handler code embedded in the my initialization code.
I've seen examples of using setOnClickListener, but the handler code was always embedded inline, e.g.,
demoButton.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View arg0) {
// ... button handler code
}});
... which is where I don't want it because that would put the button handler code up where the buttons are initialized. What's the Java runtime equivalent of android:onClick ?
Upvotes: 2
Views: 213
Reputation: 4243
As @laalto already pointed out, Android View itself simply takes the name of the handler and uses Java reflections to create an OnClickListener object. I digged the code out from View.java and wrapped it in a separate object:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.app.Activity;
import android.view.View;
public class ViewOnClickHandler implements View.OnClickListener{
Activity mActivity;
Method mHandler;
ViewOnClickHandler(Activity activity, View view, String handlerName){
mActivity = activity;
try {
mHandler = activity.getClass().getMethod(handlerName, View.class);
} catch (NoSuchMethodException e) {
int id = view.getId();
String idText = id == View.NO_ID ? "" : " with id '"
+ mActivity.getResources().getResourceEntryName(id) + "'";
throw new IllegalStateException("Could not find a method " +
handlerName + "(View) in the activity "
+ activity.getClass() + " for onClick handler"
+ " on view " + view.getClass() + idText, e);
}
}
@Override
public void onClick(View v) {
try {
mHandler.invoke(mActivity, v);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not execute non "
+ "public method of the activity", e);
} catch (InvocationTargetException e) {
throw new IllegalStateException("Could not execute "
+ "method of the activity", e);
}
}
static void set(Activity activity, View view, String handlerName){
view.setOnClickListener(new ViewOnClickHandler(activity, view, handlerName));
}
}
If you put this code in a package of your choice and import the class into your activity, the code from your sample can shrink down to:
ViewOnClickHandler.set(this, demoButton, "TheButtonHandler");
Upvotes: 0
Reputation: 6246
Method 1
public class YourActivity extends Activity implements View.OnClickListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//....
myButton1.setOnClickListener(this);
myButton2.setOnClickListener(this);
myButton3.setOnClickListener(this);
myButton4.setOnClickListener(this);
myButton1.setTag(0);
myButton2.setTag(1);
myButton3.setTag(2);
myButton4.setTag(3);
}
@Override
public void onClick(View v) {
//Do your stuff
switch ((int) v.getTag()) {
case 0:
//First button pressed;
break;
case 1:
//Second button pressed;
break;
case 2:
//Third button pressed;
break;
case 3:
//Fourth button pressed;
break;
default:
//Unknown value, handle an error
break;
}
}
}
Method 2
public class YourActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//....
myButton1.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View arg0) {
// ... button handler code
}
});
myButton2.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View arg0) {
// ... button handler code
}
});
myButton3.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View arg0) {
// ... button handler code
}
});
myButton4.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View arg0) {
// ... button handler code
}
});
}
}
Upvotes: 2
Reputation: 152867
The equivalent is setOnClickListener()
and View.OnClickListener
.
If you examine the platform source, you'll see that methods defined with onClick
attribute are transformed to a an OnClickListener
that invokes the named method via Java reflection.
I've seen examples of using setOnClickListener, but the handler code was always embedded inline ... which is where I don't want it because that would put the button handler code up where the buttons are initialized
You can have your OnClickListener
s e.g. as member variables like this:
private OnClickListener mClickListener = new OnClickListener() { ... };
//
view.setOnClickListener(mClickListener);
to have the initialization and click handling in separate places.
Upvotes: 2
Reputation: 4338
Well you don't have to include them inline if that is what you are requesting. You can create your own class such as:
MyButtonClickListener implements Button.OnClickListener
{
...
}
and this can be defined elsewhere. Then you can reference it in the initialization code similarly but not taking up as much space for readability as such.
demoButton.setOnClickListener(new MyButtonClickListener());
if that is indeed your question.
Upvotes: 1