问题
I have a custom ListView
. Each row contains a TextView
and ImageView
.
Look at screenshot:
On Item click I make that ImageView
visible. But the problem is that only ONE ImageView
should be visible at a time.
I think that the best approach is to set all other ImageViews
as INVISIBLE
on click. And after all images gone make a clicked one VISIBLE
.
But I don't know how to iterate properly that in Adapter
:
private class TimeZoneItemAdapter extends ArrayAdapter<String> {
private Activity myContext;
private ArrayList<String> datas;
public TimeZoneItemAdapter(Context context, int textViewResourceId, ArrayList<String> objects) {
super(context, textViewResourceId, objects);
myContext = (Activity) context;
datas = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = myContext.getLayoutInflater();
convertView = inflater.inflate(R.layout.listview_item, null);
viewHolder = new ViewHolder();
viewHolder.postNameView = (TextView) convertView.findViewById(R.id.listview_item);
viewHolder.postImageView = (ImageView) convertView.findViewById(R.id.image_mark);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.postNameView.setText(datas.get(position));
viewHolder.postNameView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//clear all image views during iteration
View view;
for (int i = 0; i < datas.size(); i++) {
//dont know which parameter need there for proper iteration
view = getView(i, ?????, null);
ImageView image = (ImageView) view.findViewById(R.id.image_mark);
image.setVisibility(View.INVISIBLE);
}
if (viewHolder.postImageView.getVisibility() != View.VISIBLE) {
selectedTimeZone = viewHolder.postNameView.getText().toString();
viewHolder.postImageView.setVisibility(View.VISIBLE);
} else {
viewHolder.postImageView.setVisibility(View.INVISIBLE);
}
}
});
return convertView;
}
class ViewHolder {
TextView postNameView;
ImageView postImageView;
}
}
Please help me or give some hints. I'm really confused with that already.
回答1:
There is one solution:
private static View lastClicked = null;
... ...
viewHolder.postNameView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
View parentRow = (View) v.getParent();
ViewHolder viewHolder = (ViewHolder)parentRow.getTag();
if(viewHolder.postImageView.getVisibility() != View.VISIBLE)
{
//clear last clicked image
if(lastClicked != null)
{
ViewHolder lastHolder = (ViewHolder)lastClicked.getTag();
lastHolder.postImageView.setVisibility(View.INVISIBLE);
}
selectedTimeZone = viewHolder.postNameView.getText().toString();
viewHolder.postImageView.setVisibility(View.VISIBLE);
lastClicked = parentRow;
}
else
{
viewHolder.postImageView.setVisibility(View.INVISIBLE);
lastClicked = null;
}
});
Hope this help!
回答2:
In the onClick you're iterating through the views and make sure that they all have the image hidden, and then after that setting the current one visible. You don't need to do that yourself, just tell the system to do it for you.
Note also that your current code will loop around all entries in the adapter and try and get a view for them... but not all of them will have one, the ones scrolled off the screen won't have a view.
The simplest way to do it is to remove everything from your onClick handler except the line where you set selectedTimeZone
, then call notifyDataSetChanged()
. This will make Android redraw all of the currently-onscreen views.
Then below your setText()
add:
if (datas.get(position).equals(selectedTimeZone)) {
viewHolder.postImageView.setVisibility(View.VISIBLE);
} else {
viewHolder.postImageView.setVisibility(View.INVISIBLE);
}
so when the system re-draws the views each view will be considered for having the image set to visible but only the current one will get it set.
回答3:
I wouldn't store any information on the views. I believe that the listview recycles its views so thing could get messy. Try to separate the data from the views.
I would try a different approach. Your datas
should be
ArrayList<MyData> datas;
public class MyData{
String place;
boolean: checked = false;
}
To populate the datas
ArrayList you can do this
for (String s : objects){
MyData d = new MyData();
d.place = s;
}
Then in your adapters getView
you should display/hide the imageView based on the value of checked
like this:
private class TimeZoneItemAdapter extends ArrayAdapter<MyData> {
private Activity myContext;
private ArrayList<MyData> datas;
public TimeZoneItemAdapter(Context context, int textViewResourceId, ArrayList<MyDatas> datas) {
super(context, textViewResourceId, datas);
this.datas = datas;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = myContext.getLayoutInflater();
convertView = inflater.inflate(R.layout.listview_item, null);
}
TextView postNameView = (TextView) convertView.findViewById(R.id.listview_item);
TextView postImageView = (ImageView) convertView.findViewById(R.id.image_mark);
postNameView.setText(this.datas.get(position).place);
if(this.datas.get(position).checked){
postImageView.setVisibility(View.VISIBLE);
}else{
postImageView.setVisibility(View.INVISIBLE);
}
return convertView;
}
}
When clicking on an item, you should iterate the datas
, uncheck everything and check the appropriate item. Then to update the listView you call
((TimeZoneItemAdapter)list.getAdapter()).notifyDataSetChanged();
and all the views will be updated automatically.
来源:https://stackoverflow.com/questions/29186821/iterate-through-listview-in-custom-adapter