Tôi sẽ bắt đầu bằng cách nói rằng tôi đã đọc chi tiết hầu hết mọi câu hỏi trên SO mà tôi có thể tìm thấy liên quan đến các mục danh sách có thể chọn tùy chỉnh và bộ chọn. Nhiều người trong số họ có các sự cố tương tự nhưng không có câu trả lời nào giải quyết được sự cố của tôi.Mục danh sách tùy chỉnh không phản hồi trạng thái được chọn trong bộ chọn
Tại thời điểm trong ứng dụng của tôi, tôi trình bày hoạt động danh sách tùy chỉnh. Khi được tạo, nó sẽ truy lục một tập dữ liệu tĩnh từ mục đích gọi nó và chuyển dữ liệu đó tới bộ điều hợp mảng tùy chỉnh của nó. Mỗi mục danh sách là một RelativeLayout đơn giản thực hiện giao diện Checkable. Theo mặc định, nếu bạn nhấp vào một trong các mục, một hoạt động mới sẽ được hiển thị, hiển thị thông tin chi tiết về số liên lạc đã chọn. Tuy nhiên, nếu một mục trong danh sách được nhấn lâu, một ActionMode được bắt đầu. Nhấp vào một mục trong danh sách tại thời điểm này không hiển thị hoạt động chi tiết, nó chỉ đặt mục để kiểm tra. Sau đó, nếu người dùng chọn một trong các mục chế độ hành động, nó sẽ thực hiện hành động trên (các) mục được chọn.
Điều quan trọng cần hiểu là trong cả hai chế độ lựa chọn, việc nhấp vào một mục danh sách sẽ đặt nó thành kiểm tra.
Tất cả những gì tôi mô tả ở trên đều hoạt động hoàn hảo. My chỉ vấn đề phải làm với hình nền của các mục danh sách không được đánh dấu khi chúng được thiết lập để kiểm tra, thậm chí bằng cách sử dụng bộ chọn mặc định.
Những gì tôi muốn làm, có hai bộ chọn: một cho mỗi chế độ lựa chọn. Trong phần đầu tiên, nền không thay đổi khi một mục được chọn, và trong phần thứ hai thì nó sẽ xuất hiện. Tôi đã thử triển khai các bộ chọn tùy chỉnh, nhưng ngay cả trong những trạng thái được chọn sẽ bị bỏ qua! Các phần khác của bộ chọn hoạt động tốt, nhưng không hoạt động.
Việc triển khai CheckableListItem của tôi kết hợp ý tưởng từ nhiều ví dụ khác nhau, vì vậy nếu tôi làm điều gì đó sai hoặc nếu có cách nào tốt hơn thì hãy cho tôi biết!
Note: Một điểm thú vị là nếu tôi đặt nền của danh sách các mục trong results_list_item.xml để chọn tôi, thay vì tài sản listSelector của ListView, các nền làm thay đổi khi một mục được kiểm tra . Tuy nhiên, việc này làm cho quá trình chuyển đổi báo chí dài trong bộ chọn của tôi không hoạt động.
ResultsActivity.java:
public class ResultsActivity extends ListActivity implements OnItemLongClickListener {
private ListView listView; // Reference to the list belonging to this activity
private ActionMode mActionMode; // Reference to the action mode that can be started
private boolean selectionMode; // Detail mode or check mode
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_results);
// When the home icon is pressed, go back
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
// Get a reference to the list
listView = getListView();
// Initially in detail mode
selectionMode = true;
// Get the contacts from the intent data and pass them to the contact adapter
@SuppressWarnings("unchecked")
ArrayList<Contact> results = ((ArrayList<Contact>)getIntent().getSerializableExtra("results"));
Contact[] contacts = new Contact[results.size()];
ContactArrayAdapter adapter = new ContactArrayAdapter(this, results.toArray(contacts));
setListAdapter(adapter);
// We will decide what happens when an item is long-clicked
listView.setOnItemLongClickListener(this);
}
/**
* If we are in detail mode, when an item in the list is clicked
* create an instance of the detail activity and pass it the
* chosen contact
*/
public void onListItemClick(ListView l, View v, int position, long id) {
if (selectionMode) {
Intent displayContact = new Intent(this, ContactActivity.class);
displayContact.putExtra("contact", (Contact)l.getAdapter().getItem(position));
startActivity(displayContact);
}
}
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
/**
* If the home button is pressed, go back to the
* search activity
*/
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent intent = new Intent(this, SearchActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* When an item is long-pressed, switch selection modes
* and start the action mode
*/
public boolean onItemLongClick(AdapterView<?> adapter, View view, int position, long i) {
if (mActionMode != null)
return false;
if (selectionMode) {
toggleSelectionMode();
listView.startActionMode(new ListActionMode(this, getListView()));
return true;
}
return false;
}
/**
* Clear the list's checked items and switch selection modes
*/
public void toggleSelectionMode() {
listView.clearChoices();
((ContactArrayAdapter)listView.getAdapter()).notifyDataSetChanged();
if (selectionMode) {
selectionMode = false;
} else {
selectionMode = true;
}
}
}
activity_results.xml:
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="multipleChoice"
android:listSelector="@drawable/list_selector" />
list_selector.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true" android:drawable="@drawable/blue_transition" />
<item android:state_checked="true" android:drawable="@drawable/blue" />
</selector>
TwoLineArrayAdapter:
public abstract class TwoLineArrayAdapter extends ArrayAdapter<Contact> {
private int mListItemLayoutResId;
public TwoLineArrayAdapter(Context context, Contact[] results) {
this(context, R.layout.results_list_item, results);
}
public TwoLineArrayAdapter(Context context, int listItemLayoutResourceId, Contact[] results) {
super(context, listItemLayoutResourceId, results);
mListItemLayoutResId = listItemLayoutResourceId;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View listItemView = convertView;
if (convertView == null) {
listItemView = inflater.inflate(mListItemLayoutResId, parent, false);
}
// Get the text views within the layout
TextView lineOneView = (TextView)listItemView.findViewById(R.id.results_list_item_textview1);
TextView lineTwoView = (TextView)listItemView.findViewById(R.id.results_list_item_textview2);
Contact c = (Contact)getItem(position);
lineOneView.setText(lineOneText(c));
lineTwoView.setText(lineTwoText(c));
return listItemView;
}
public abstract String lineOneText(Contact c);
public abstract String lineTwoText(Contact c);
}
ContactArrayAdapter:
public class ContactArrayAdapter extends TwoLineArrayAdapter {
public ContactArrayAdapter(Context context, Contact[] contacts) {
super(context, contacts);
}
public String lineOneText(Contact c) {
return (c.getLastName() + ", " + c.getFirstName());
}
public String lineTwoText(Contact c) {
return c.getDepartment();
}
}
CheckableListItem.java:
public class CheckableListItem extends RelativeLayout implements Checkable {
private boolean isChecked;
private List<Checkable> checkableViews;
public CheckableListItem(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
initialise(attrs);
}
public CheckableListItem(Context context, AttributeSet attrs) {
super(context, attrs);
initialise(attrs);
}
public CheckableListItem(Context context, int checkableId) {
super(context);
initialise(null);
}
private void initialise(AttributeSet attrs) {
this.isChecked = false;
this.checkableViews = new ArrayList<Checkable>(5);
}
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean check) {
isChecked = check;
for (Checkable c : checkableViews) {
c.setChecked(check);
}
refreshDrawableState();
}
public void toggle() {
isChecked = !isChecked;
for (Checkable c : checkableViews) {
c.toggle();
}
}
private static final int[] CheckedStateSet = {
android.R.attr.state_checked
};
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CheckedStateSet);
}
return drawableState;
}
protected void onFinishInflate() {
super.onFinishInflate();
final int childCount = this.getChildCount();
for (int i = 0; i < childCount; i++) {
findCheckableChildren(this.getChildAt(i));
}
}
private void findCheckableChildren(View v) {
if (v instanceof Checkable) {
this.checkableViews.add((Checkable) v);
}
if (v instanceof ViewGroup) {
final ViewGroup vg = (ViewGroup) v;
final int childCount = vg.getChildCount();
for (int i = 0; i < childCount; i++) {
findCheckableChildren(vg.getChildAt(i));
}
}
}
}
results_list_item.xml:
<com.test.mycompany.Widgets.CheckableListItem
android:id="@+id/results_list_item"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="5dp"
android:paddingBottom="5dp" >
<TextView android:id="@+id/results_list_item_textview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:textSize="20sp"
android:textColor="#000000"
android:focusable="false" />
<TextView android:id="@+id/results_list_item_textview2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@id/results_list_item_textview1"
android:textSize="16sp"
android:textColor="@android:color/darker_gray"
android:focusable="false" />
</com.test.mycompany.Widgets.CheckableListItem>
Bạn đang kiểm tra và bỏ chọn các mục của mình ở đâu? Bạn cũng có thể thử làm việc với android: state_activited. – DroidBender
Tôi không tự làm. Họ đang nhận được kiểm tra, mặc dù. Khi tôi đặt các câu lệnh tường trình trong phương thức setChecked của các mục, tôi thấy rằng nó đang được gọi. – Groppe
Hãy thử 'android: longClickable = true' trên' CheckableListItem' khi u đặt bg trực tiếp .. (như được chỉ định trong Ghi chú của bạn) – Ronnie