I have a super TestUI application. It has a gridview with buttons in them.
I want word of the button click to be passed back to the main Activity, so that it can update its state.
Sadly the buttons steal the clicks. So the typical:
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(TestUI.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
Does not get called.
Instead in the adapter definition:
public View getView(int position, View convertView, ViewGroup parent) {
Button gridItem;
if (convertView == null) { // if it's not recycled, initialize some attributes
gridItem = new Button(mContext);
} else {
gridItem = (Button) convertView;
}
gridItem.setText("button " + String.valueOf(position));
gridItem.setClickable(true);
gridItem.setFocusable(false);
gridItem.setOnClickListener(new MyOnClickListener(position, mContext));
return gridItem;
Which is backed with a class MyOnClickListener that implements the OnClickListener interface. However if I do it this way I still need a call back to the main activity, somehow it needs to know that something was done as it controls the program state.
So what is the best way to update the "roo开发者_StackOverflow中文版t" class/activities' state from a button click?
I know this a basic OO question but I mostly write in ASM and C so I frankly just don't know.
Why do you need to have 2 onClickListeners. From the onItemClickListener
you have to the main activity can't you do all the work you need to do? Is a necessary for the adapter to do the MyOnClickListener
work?
You can set the gridItem.setOnClickListener from the main activity. No need to create a new ListenerObject every time.
You just need a xml to inflate to getView containing a Button
<Button android:text="Handle me"
android:id="@+id/btnHandleMe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="buttonHandler"
android:clickable="true">
and create this function to your activity.
public void buttonHandler(View v) {
// Do your stuff here that new MyOnClickListener(position, mContext) whould do.
}
You can get the position of the row/column that this button is populated in the list/grid by adding a tag to the adapter.
In getView add
gridItem.setTag(position)
and to retreive it from buttonHandler
if(v.getTag instance of Integer)
int position = (Integer)v.getTag();
So now you handle all clicks from the activity and by default the activity is notified.
As you said, your getView method is inside the adapter class. But the adapter gets a copy of the "context", which your getView method has access to. Context is a super-class of all Activities and Services. Through this object you can do many of the basic operations of an Activity. From your example, I understand that you would like to show a toast. This can be done using
public View getView(int position, View convertView, ViewGroup parent) {
//usual getView stuff goes first
gridItem.setOnClickListener(new OnClickListener(){
public onClick(View v){
Toast.makeText(mContext, "" + position, Toast.LENGTH_SHORT).show();
}
}
}
So in short, your MyOnClickListener class needs to used the mContext variable for interacting with the root activity.
Edit I realized that I made a mistake in the above answer. I looked at the sample on http://developer.android.com/resources/tutorials/views/hello-gridview.html and realized that you aren't restricted to using Context. You could use something like
public class MyActivity extends Activity {
public int a = 0;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));
}
}
public class ImageAdapter extends BaseAdapter {
private MyActivity myAct;
public ImageAdapter(MyActivity c) {
myAct= c;
}
public View getView(int position, View convertView, ViewGroup parent) {
//usual getView stuff goes first
gridItem.setOnClickListener(new OnClickListener(){
public onClick(View v){
myAct.a = position;
}
}
}
}
Hopefully that is what you wanted to do.
精彩评论