Вот что я имею в виду под странным:
- Для элементов обычно требуется 2 нажатия, чтобы правильно изменить цвет фона.
- При изменении списка Android кажется некорректно аннулировать представления списка, поскольку проверенные повторно используемые представления имеют проверенный фон для новых элементов (которые я подтвердил с помощью отладчика: не проверено).
- Несколько элементов могутвыглядят как выбранные, и на самом деле «правильно» снимите флажок, когда я нажимаю на них снова, за исключением того факта, что
ListView
сообщает только о самом последнем элементе, как проверено. - Первый раз, когда яотметьте элемент, я не могу снять его, щелкнув по нему.
- Все работает более или менее хорошо, если я изменяю режим выбора на
ListView.CHOICE_MODE_MULTIPLE
, за исключением, разумеется, того, что я не хочу множественноговыделение.
Я использую пользовательский адаптер и пользовательский макет.О, также, нацеливаясь на 4.0.3 пока.Вот код для списка:
ListView categoryList = (ListView) findViewById(R.id.categoryList);
categoryList.setAdapter(categoryAdapter);
categoryList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
categoryList.setItemsCanFocus(false);
categoryList.setOnItemClickListener(categoryAdapter);
Вот прослушиватель щелчков:
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ListView listView = (ListView) parent;
RemoteListItem remoteListItem = (RemoteListItem) view.getTag();
if (remoteListItem.isEnabled()) {
remoteListItem.action(view);
}
view.invalidate(); /added out of sheer desperation
}
Вот расширенная версия RelativeLayout, которую я использую:
package com.sastraxi.machineshop.ui;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Checkable;
import android.widget.RelativeLayout;
/**
* RelativeLayout that implements the Checkable interface.
* Set this view's tag as a Checkable, and this layout will delegate
* Checkable's interface methods to the tag object.
*/
public class CheckableRelativeLayout extends RelativeLayout implements Checkable {
@Override
public boolean isClickable() {
return false;
}
public CheckableRelativeLayout(Context context) {
super(context);
}
public CheckableRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CheckableRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Delegates to (Checkable) getTag().
*/
public boolean isChecked() {
try {
Checkable checkableTag = (Checkable) getTag();
return checkableTag.isChecked();
} catch (ClassCastException e) {
Log.w("CheckableRelativeLayout", "Tag is not an instance of Checkable; this object won't do anything useful.");
} catch (NullPointerException e) {
Log.w("CheckableRelativeLayout", "Tag is null; this object won't do anything useful.");
}
return false;
}
/**
* Delegates to (Checkable) getTag().
*/
public void setChecked(boolean checked) {
try {
Checkable checkableTag = (Checkable) getTag();
checkableTag.setChecked(checked);
invalidate();
} catch (ClassCastException e) {
Log.w("CheckableRelativeLayout", "Tag is not an instance of Checkable; this object won't do anything useful.");
} catch (NullPointerException e) {
Log.w("CheckableRelativeLayout", "Tag is null; this object won't do anything useful.");
}
}
/**
* Delegates to (Checkable) getTag().
*/
public void toggle() {
try {
Checkable checkableTag = (Checkable) getTag();
checkableTag.toggle();
invalidate();
} catch (ClassCastException e) {
Log.w("CheckableRelativeLayout", "Tag is not an instance of Checkable; this object won't do anything useful.");
} catch (NullPointerException e) {
Log.w("CheckableRelativeLayout", "Tag is null; this object won't do anything useful.");
}
}
private static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
};
/**
* Reflect the delegate Checkable's state in this View's state set.
*/
@Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
}
Вот тип элемента списка, к которому он относится:
public abstract class RemoteListItem implements Checkable {
private final String name;
private final String extra;
private boolean enabled = true;
private boolean selected = false;
public boolean isChecked() {
return selected;
}
public void toggle() {
selected = !selected;
}
public void setChecked(boolean checked) {
selected = checked;
}
public RemoteListItem(String name, String extra) {
this.name = name;
this.extra = extra;
}
public String getExtra() {
return extra;
}
public String getName() {
return name;
}
public abstract void action(View viewInList);
public boolean isEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
RemoteListAdapter.super.notifyDataSetChanged();
}
public boolean isSelectable() {
return true;
}
}
Вот макет, который расширяется для элементов:
<?xml version="1.0" encoding="utf-8"?>
<com.sastraxi.machineshop.ui.CheckableRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:padding="12dp"
android:gravity="center_vertical"
android:background="@drawable/listitem_background">
<TextView
android:id="@+id/key"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_alignParentLeft="true"
android:inputType="none"
/>
<TextView
android:id="@+id/value"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:gravity="right"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/faded_text_colour"
android:layout_alignParentRight="true"
android:inputType="none"
/>
<ProgressBar
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@android:style/Widget.ProgressBar.Small"
android:layout_marginTop="5dip"
android:layout_marginRight="2dip"
android:gravity="right"
android:visibility="gone"
android:layout_alignParentRight="true"/>
</com.sastraxi.machineshop.ui.CheckableRelativeLayout>
Кроме того, @ drawable / listitem_background - это список состояний, которыйоткуда проверяется цвет фона.Я чувствую себя настолько растерянным из-за того, что все работает не так, как я ожидаю.Кажется, я где-то пропускаю view.invalidate()
, но не могу понять, где.