i have a ListView (lvProperties) whose adapter is a custom ListAdapter (not an ArrayAdapter). This adapter gets is data from an Instance variable of custom type Section (containing a few Strings, Integers, ArrayLists and methods).
I need this list to ALWAYS display a selection (there must be always a selected element, even on activity launch).
When using a simple ArrayAdapter in the past something like this would be enough:
lvProperties.requestFocus();
lvProperties.setSelection(0);
However, in this case it does not work at all. I have been looking around SO and the web and used:
lvProperties.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lvProperties.setFocusable(true);
lvProperties.setFocusableInTouchMode(true);
lvProperties.requestFocus();
lvProperties.setSelection(0);
And still nothing.
My ListAdapter:
lvProperties.setAdapter(new ListAdapter() {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v=convertView;
if(v==null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v=vi.inflate(R.layout.detail_row1, null);
}
TextView name=(TextView)v.findViewById(R.id.propName);
TextView value=(TextView)v.findViewById(R.id.propValue);
if(name!=null) {
name.setText(section.propNames.get(position));
}
if(value!=null) {
value.setText(section.propValues.get(position));
}
return v;
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {}
@Override
public void registerDataSetObserver(DataSetObserver observer) {}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
return 0;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public int getCount() {
return section.propNames.size();
}
@Override
public boolean isEnabled(int position) {
return true;
}
@Override
public boolean areAllItemsEnabled() {
return true;
}
});
My unimplemented OnItemSelectedListener:
lvProperties.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
// TODO Auto-generated method stub
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
And my detail_row1.xml (I will be implementing to layouts for the rows next, but this is how it's right now:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:layout_height="wrap_content"
android:padding="6dip"
>
<TextView
android:id="@+id/propName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#000000"
android:gravity="center_vertical|left"
android:paddingTop="10sp"
android:paddingBottom="10sp"
android:paddingLeft="4sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:id="@+id/propValue"
android:textColor="#000000"
android:textSize="16sp"
android:textStyle="bold"
android:paddingTop="10sp"
android:paddingBottom="10sp"
android:paddingRight="4sp"
android:gravity="center_vertical|right"
/>
</LinearLayout><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:layout_height="wrap_content"
android:padding="6dip"
>
<TextView
android:id="@+id/propName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#000000"
android:gravity="center_vertical|left"
android:paddingTop="10sp"
android:paddingBottom="10sp"
android:paddingLeft="4sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:id="@+id/propValue"
android:textColor="#000000"
android:textSize="16sp"
android:textStyle="bold"
android:paddingTop="10sp"
android:paddingBottom="10sp"
android:paddingRight="4sp"
android:gravity="center_vertical|right"
/>
</LinearLayout>
any help / pointer to guide on how to accomplish this? I don't want to use a drawable, just the default selector for the Theme I'm using.
Again, there must always be one selected entry in the list.
I realize that by design this is not the intended behavior for lists BUT this is one of those cases where one size doesn't fit all
For all others interested, I just replicated what I needed with having to mess with ChoiceMode, requestFocus, setSelection, etc etc etc, works fine in API 8 upwards
when app launches I want the first row to be highlighted already:
selectedItem.setValue(0) // an inner class i have, could be a simple integer as well
my Inner Class ArrayDapter (I need it to see the parent selectedItem all the time):
note: i will be changed the hard coded color next, i just solved the problem i had:
public class DetailsAdapter extends ArrayAdapter<Section> {
public Section section;
public View v;
public Context c;
public DetailsAdapter(Context context, int textViewResourceId,
Section s) {
super(context, textViewResourceId);
this.section=s;
this.c=context;
}
@Override
public int getCount() {
return section.propNames.size();
}
@Override
public View getView(int pos, View convertView, ViewGroup parent){
this.v = convertView;
LayoutInflater vi = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(v==null) {
v=vi.inflate(R.layout.detail_row1, null);
}
**LinearLayout llc=(LinearLayout) v.findViewById(R.id.detail_container);**
TextView name=(TextView)v.findViewById(R.id.propName);
TextView value=(TextView)v.findViewById(R.id.propValue);
if(pos==selectedItem.value) {
llc.setBackgroundColor(Color.LTGRAY);
} else
{ llc.setBackgroundColor(Color.WHITE);}
Log.e("Pos",""+pos);
if(llc!=null) {
}
if(name!=null) {
name.setText(section.namesAsArray()[pos]);
}
if(value!=null) {
value.setText(section.valuesAsArray()[pos]);
}
return v;
}
}
The trick so I could avoid android:state_xxxxxxx in my XML file was to wrap my custom row with a nested LinearLayout filling the outer one.
the layout for the row:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:layout_height="wrap_content"
android:id="@+id/detail_linearLayout"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="0"
android:id="@+id/detail_container"
android:padding="6dip"
>
<TextView
android:id="@+id/propName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#000000"
android:gravity="center_vertical|left"
android:paddingTop="10sp"
android:paddingBottom="10sp"
android:paddingLeft="4sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:id="@+id/propValue"
android:textColor="#000000"
android:textSize="16sp"
android:textStyle="bold"
android:paddingTop="10sp"
android:paddingBottom="10sp"
android:paddingRight="4sp"
android:gravity="center_vertical|right"
/>
</LinearLayout>
</LinearLayout>
finally, on I set my OnItemClickListener:
lvProperties.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
**selectedItem.value=arg2;
lvProperties.invalidateViews();**
.
.
.
}});
done and done!