So I have a custom ListView object. The list items have two textviews stacked on top of each other, plus a horizontal progress bar that I want to remain hidden until I actually do something. To the far right is a checkbox that I only want to display when the user needs to download updates to their database(s). When I disable the checkbox by setting the visibility to Visibility.GONE, I am able to click on the list items. When the checkbox is visible, I am unable to click on anything in the list except the checkboxes. I've done some searching but haven't found anything relevant to my current situation. I found this question but I'm using an overridden ArrayAdapter since I'm using ArrayLists to contain the list of databases internally. Do I just need to get the LinearLayout view and add an onClickListener like Tom did? I'm not sure.
Here's the listview row layout XML:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:padding="6dip"> <LinearLayout android:orientation="vertical" android:layout_width="0dip" android:layout_weight="1" android:layout_height="fill_parent"> <TextView android:id="@+id/UpdateNameText" android:layout_width="wrap_content" android:layout_height="0dip" android:layout_weight="1" android:textSize="18sp" android:gravity="center_vertical" /> <TextView android:layout_width="fill_parent" android:layout_height="0dip" android:layout_weight="1" android:id="@+id/UpdateStatusText" android:singleLine="true" android:ellipsize="marquee" /> <ProgressBar android:id="@+id/UpdateProgress" android:layout_width="fill_parent" android:layout_height="wrap_content" android:indeterminateOnly="false" android:progressDrawable="@android:drawable/progress_horizontal" android:indeterminateDrawable="@android:drawable/progress_indeterminate_horizontal" android:minHeight="10dip" android:maxHeight="10dip" /> </LinearLayout> <CheckBox android:text="" android:id="@+id/UpdateCheckBox" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
And here's the class that extends the ListActivity. Obviously it's still in development so forgive the things that are missing or might be left laying around:
public class UpdateActivity extends ListActivity { AccountManager lookupDb; boolean allSelected; UpdateListAdapter list; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); lookupDb = new AccountManager(this); lookupDb.loadUpdates(); setContentView(R.layout.update); allSelected = false; list = new UpdateListAdapter(this, R.layout.update_row, lookupDb.getUpdateItems()); setListAdapter(list); Button btnEnterRegCode = (Button)findViewById(R.id.btnUpdateRegister); btnEnterRegCode.setVisibility(View.GONE); Button btnSelectAll = (Button)findViewById(R.id.btnSelectAll); btnSelectAll.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { allSelected = !allSelected; for(int i=0; i < lookupDb.getUpdateItems().size(); i++) { lookupDb.getUpdateItem(i).setSelected(!lookupDb.getUpdateItem(i).isSelected()); } list.notifyDataSetChanged(); // loop through each UpdateItem and set the selected attribute to the inverse } // end onClick }); // end setOnClickListener Button btnUpdate = (Button)findViewById(R.id.btnUpdate); btnUpdate.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { } // end onClick }); // end setOnClickListener lookupDb.close(); } // end onCreate @Override protected void onDestroy() { super.onDestroy(); for (UpdateItem item : lookupDb.getUpdateItems()) { item.getDatabase().close(); } } @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); UpdateItem item = lookupDb.getUpdateItem(position); if (item != null) { item.setSelected(!item.isSelected()); list.notifyDataSetChanged(); } } private class UpdateListAdapter extends ArrayAdapter<UpdateItem> { private List<UpdateItem> items; public UpdateListAdapter(Context context, int textViewResourceId, List<UpdateItem> items) { super(context, textViewResourceId, items); this.items = items; } @Override public View getView(int position, View convertView, ViewGroup parent) { View row = null; if (convertView == null) { LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); row = li.inflate(R.layout.update_row, null); } else { row = convertView; } UpdateItem item = items.get(position); if (item != null) { TextView upper = (TextView)row.findViewById(R.id.UpdateNameText); TextView lower = (TextView)row.findViewById(R.id.UpdateStatusText); CheckBox cb = (CheckBox)row.findViewById(R.id.UpdateCheckBox); upper.setText(item.getName()); lower.setText(item.getStatusText()); if (item.getStatusCode() == UpdateItem.UP_TO_DATE) { cb.setVisibility(View.GONE); } else { cb.setVisibility(View.VISIBLE); cb.setChecked(item.isSelected()); } ProgressBar pb = (ProgressBar)row.findViewById(R.id.UpdateProgress); pb.setVisibility(View.GONE); } return row; } } // end inner class UpdateListAdapter }
edit: I'm still having this problem. I'm cheating and adding onClick handlers to the textviews but it seems extremely stupid that my onListItemClick() function is not being called at all when I am not clicking on my checkbox.
The issue is that Android doesn't allow you to select list items that have elements on them that are focusable. I modified the checkbox on the list item to have an attribute like so:
android:focusable="false"
Now my list items that contain checkboxes (works for buttons too) are "selectable" in the traditional sense (they light up, you can click anywhere in the list item and the "onListItemClick" handler will fire, etc).
EDIT: As an update, a commenter mentioned "Just a note, after changing the visibility of the button I had to programmatically disable the focus again."
In case you have ImageButton inside the list item you should set the descendantFocusability
value to 'blocksDescendants' in the root list item element.
android:descendantFocusability="blocksDescendants"
And the focusableInTouchMode
flag to true
in the ImageButton
view.
android:focusableInTouchMode="true"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With