[英]How to make custom listSelector on custom listView
我試圖弄清楚如何為我的listView設置自定義listSelector。 該代碼或多或少是從在Stackoverflow中對其他人有用的解決方案中復制並粘貼的,但對我而言不起作用。
當我打開CAB模式時,可以選擇和取消選擇項目,並且可以在CAB導航欄中看到所選項目的數量,但是在列表中沒有看到任何指示。 我想看看選擇了哪些項目。 知道為什么它不起作用嗎?
布局/ category_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/categories_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/category_browser"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:dividerHeight="1dp"
android:listSelector="@drawable/list_selector"
android:drawSelectorOnTop="true"
tools:listitem="@layout/category_list_item" >
</ListView>
<include layout="@layout/ad"/>
</LinearLayout>
布局/ category_list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<com.fletech.smartbaby.api.CheckableLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/category_browser_list_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="fill"
android:clickable="true"
android:gravity="fill"
android:orientation="horizontal">
<ImageView
android:id="@+id/category_item_icon"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_gravity="fill"
android:layout_weight="0"
android:background="#ffffff"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/category_browser_list_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical|start"
android:paddingLeft="10dp"
android:paddingRight="10dp"
tools:text="Category name"
android:textColor="#000000"
android:textSize="24sp" />
<include layout="@layout/category_features"
android:layout_centerInParent="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
/>
<include layout="@layout/category_status"
android:layout_centerInParent="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
/>
</com.fletech.smartbaby.api.CheckableLinearLayout>
繪制/ list_selector.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#40777777"/>
</shape>
</item>
<item android:state_long_pressable="true">
<shape android:shape="rectangle">
<solid android:color="#400000ff"/>
</shape>
</item>
<item android:state_checkable="true">
<shape android:shape="rectangle">
<solid android:color="#400000ff"/>
</shape>
</item>
<item android:state_checked="true">
<shape android:shape="rectangle">
<solid android:color="#800000ff"/>
</shape>
</item>
</selector>
和CheckableLinearLayout.java:
package com.fletech.smartbaby.api;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
//import android.support.v7.widget.LinearLayoutCompat; // do I need this? I can't see any difference
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Checkable;
import android.widget.LinearLayout;
public class CheckableLinearLayout extends LinearLayout implements Checkable {
private static final String TAG = CheckableLinearLayout.class.getSimpleName();
private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};
private boolean mChecked;
public CheckableLinearLayout(Context context) {
super(context);
}
public CheckableLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public CheckableLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setChecked(boolean checked) {
Log.v(TAG, "setChecked: " + checked);
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
}
}
@Override
public boolean isChecked() {
return mChecked;
}
@Override
public void toggle() {
Log.v(TAG, "toggle: " + mChecked + " -> " + (!mChecked));
setChecked(!mChecked);
}
@Override
// not sure if needed, as it seems to work without this as well
public boolean performClick() {
Log.v(TAG, "performClick");
toggle();
return super.performClick();
}
@Override
// this might be unnecessary
protected void drawableStateChanged() {
Log.v(TAG, "drawableStateChanged");
super.drawableStateChanged();
final Drawable drawable=getBackground();
if(drawable!=null)
{
final int[] myDrawableState=getDrawableState();
drawable.setState(myDrawableState);
invalidate();
}
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
Log.v(TAG, "onCreateDrawableState: " + extraSpace);
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
@Override
protected Parcelable onSaveInstanceState() {
SavedState result = new SavedState(super.onSaveInstanceState());
result.checked = mChecked;
return result;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setChecked(ss.checked);
}
protected static class SavedState extends BaseSavedState {
protected boolean checked;
protected SavedState(Parcelable superState) {
super(superState);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(checked ? 1 : 0);
}
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
private SavedState(Parcel in) {
super(in);
checked = in.readInt() == 1;
}
}
}
我花了一個多星期的時間來找出為什么這個對所有人都有效的東西對我不起作用。 答案很簡單。 希望對別人有幫助。
解決方案是更改選擇器xml中項目的順序。 沒有任何狀態的項目必須是最后一個:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_long_pressable="true">
<shape android:shape="rectangle">
<solid android:color="#400000ff"/>
</shape>
</item>
<item android:state_checkable="true">
<shape android:shape="rectangle">
<solid android:color="#400000ff"/>
</shape>
</item>
<item android:state_checked="true">
<shape android:shape="rectangle">
<solid android:color="#800000ff"/>
</shape>
</item>
<!-- the item without any states has to be the last: -->
<item>
<shape android:shape="rectangle">
<solid android:color="#40777777"/>
</shape>
</item>
</selector>
原因是解析器似乎在xml文件中尋找匹配的第一項。 這意味着,如果您擁有狀態數不同的項目,那么應該始終在xml頂部定義具有更多狀態的項目。 例如:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checkable="true" android:state_long_pressable="true">
<shape android:shape="rectangle">
<solid android:color="#ffff00"/>
</shape>
</item>
<item android:state_long_pressable="true">
<shape android:shape="rectangle">
<solid android:color="#ff0000"/>
</shape>
</item>
<item android:state_checkable="true">
<shape android:shape="rectangle">
<solid android:color="#00ff00"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#40777777"/>
</shape>
</item>
</selector>
這樣,只有這樣,您將在以下項目上看到不同的顏色:-可檢查和long_pressable-可檢查,但不可long_pressable-long_pressable但不可檢查-其他
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.