Reputation: 1300
I'm filling a listview, here is the code :
ArrayAdapter<CharSequence> listAdapter1;
ListView toc;
toc=(ListView)findViewById(R.id.listView1);
listAdapter1=ArrayAdapter.createFromResource(Glossary.this,R.array.arabicalphabet,R.layout.glossarysimplerow);
toc.setAdapter(listAdapter1);
I'm setting a list selector in the xml file, when clicking on any item in the list its color will change to blue to show that it is selected. The problem is, when I scroll the listview the selection will change, for example if I have a list filled from A to Z, If I select the letter "B" and I scroll many times, I get the letter "M" selected... Any help please
Upvotes: 3
Views: 2423
Reputation: 7761
In Android the children of AdapterView
like ListView
have caching enabled, so when user scrolls, the items off the screen are off the memory, getView()
is called for the items that are to be shown on the view after scrolling.
The View
that is passed in the getView()
method is reused and has properties of the previously visible view
s in the ListView
. This improves the performance of the ListView
but makes it necessary to check for all the possible conditions and reset all the properties of the view received in the getView()
.
Now the generic ArrayAdapter
that you used has no implementation of changing colors on click and it doesn't have any way to keep a record of the view already clicked. So on scrolling the results are unexpected.
You may implement your own Adapter
class as shown below and it will solve your issue:
public class MyAdapter extends ArrayAdapter<String> {
Context context;
List<String> lstStrings;
List<Boolean> isClicked;
public MyAdapter (Context context, int resource, List<String> lstStrings) {
super(context, resource, lstStrings);
this.context = context;
lstStrings = lstStrings;
isClicked = new ArrayList<>(Arrays.asList(new Boolean[lstStrings.length]));
Collections.fill(isClicked, new Boolean(false));
}
@Override
public int getCount() {
return lstStrings.size();
}
@Override
public String getItem(int position) {
return lstStrings.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = LayoutInflater.from( context).inflate(R.layout.list_item, null);
TextView txtTheText = (TextView) convertView.findViewById(R.id.txtTheText);
txtTheText .setText(lstStrings.get(position));
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
isClicked.set(!isClicked.get(position));
}
});
if (isClicked.get(position))
convertView.setBackgroundColor(Color.argb(255, 255, 0, 0));
else
convertView.setBackgroundColor(Color.argb(255, 0, 0, 255));
return convertView;
}
}
Upvotes: 2
Reputation: 14021
I have a resolution. When you click one item, record its position
. Then override onConfigurationChanged(Configuration newConfig)
, and call ListView.setSelection(position)
.
Upvotes: 0
Reputation: 2495
yah, I encounted this problem a week ago, the reason is "when you scroll listview, the first display item has position 0", so your change view will affect on the new item.
My solution is:
1). Using ScrollView
with a LinearLayout
inside it instead of using ListView
2). Add array TextView[]
to LinearLayout
.
code:
Layout:
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp">
<LinearLayout
android:id="@+id/ll_inflater"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
</ScrollView>
Java:
int prePos = -1;
int sdk = android.os.Build.VERSION.SDK_INT;
LinearLayout ll_inflater = (LinearLayout)findViewById(R.id.ll_inflater);
TextView[] tv_Subs = new TextView[array.size()];//arrary is arrayData
for(int i = 0; i < array.size(); i++){
tv_Subs[i] = new TextView(getApplication());
tv_Subs[i].setLines(3);
tv_Subs[i].setTextColor(getResources().getColor(R.color.sub_color));
tv_Subs[i].setGravity(Gravity.CENTER);
if(sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
//set default background color
} else {
//set default background color
}
tv_Subs[i].setText(array.get(i));
ll_inflater.addView(tv_Subs[i], i, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
final int finalI = i;
tv_Subs[i].setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
if(prePos !=-1){
//change background of preposition tv_Subs[prePost] to default color
}
//change background color here
prePos = finalI;
}
});
}
Upvotes: 1