Reputation: 17475
I have a GridView
showing some TextView
s, the views are drawn so that ONE is marked as selected. The problem is that when the user interaction changes the selected item in my logic I want to update the views involved, namely the view showing previous selected item and the view showing the current selected item. (Of course in my real problem the child views in the grid are more complex as well as the update process which could involve some calculations, loading of resources, accessing databases, etc.)
Till now I'm using BaseAdapter.notifyDataSetChanged
or GridView.invalidateViews
and both do the work but also updates ALL the visible child views of the GridView
but what I want is to update just TWO views among them.
How can I do that? How to get just the two views for the updating process?
Note: I'm facing this problem with ListView
s also but I think maybe it will have the same solution.
Example code:
public class MainActivity extends Activity {
private int selectedPos = 36;
private class MyAdapter extends BaseAdapter {
@Override
public int getCount() {
return 100;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv;
if(convertView==null) {
tv = new TextView(MainActivity.this);
} else {
tv = (TextView) convertView;
}
Log.d("Updating -----", String.valueOf(position));
if(position==selectedPos)
tv.setText("Item ".toUpperCase() + String.valueOf(position));
else
tv.setText("Item " + String.valueOf(position));
return tv;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final GridView gv = (GridView) findViewById(R.id.gridView1);
gv.setAdapter(new MyAdapter());
gv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectedPos = position;
//gv.invalidateViews();
((MyAdapter)gv.getAdapter()).notifyDataSetChanged();
}
});
}
}
What I'm looking for is something like (some kind of pseudo code):
updateThisViewAsNotSelected(selectedPos);
gv.redrawThisView(selectedPos);
selectedPos = position;
updateThisViewAsSelected(selectedPos);
gv.redrawThisView(selectedPos);
Upvotes: 0
Views: 3640
Reputation: 1052
You need to traverse through the visible children of the list or grid view to achieve to that. For example, if you'd like to achieve that with a grid view:
for(int k = gridView.getFirstVisiblePosition(); k <= gridView.getLastVisiblePosition(); k++) {
View view = gridView.getChildAt(k);
// you can update the view here
}
If you'd like to get a child from a specific position:
int firstVisiblePosition = gridView.getFirstVisiblePosition();
for (int k = 0; k < gridView.getChildCount(); k++ ) {
int current = firstVisiblePosition + k;
if (current == updateThisPosition) {
View child = gridView.getChildAt(i);
// Update the view
TextView anything = (TextView) child.findViewById(R.id.anything_text);
anything.setText("updated!");
}
}
Upvotes: 1
Reputation: 2308
Recreating views all the time:
What exactly is the problem of updating the views when getView
is called? If you do nothing but change the text of a TextView
I can see no problem.
If you are planning to do something more you need to change your view on Adapter
s. See below.
Long running operations and adapters
You should never do any long running operations in the adapter itself. And not in getView at all.
You should begin thinking about Adapter
s as... well adapters. They adapt the data you have to the current UI context.
So it's not the job of the adapter to fetch data from the database or anything like that. The adapter should be fed data and simply adapt it into views.
For feeding the adapter with data consider using AsyncTask
. It performs operations away from the UI threat and and can update the adapter when it is done.
You can for example let the Adapter have a List of objects that represent each view. Then to update the adapter you just need to provide it a new list of changed objects and notify it that the data has changed.
Upvotes: 1