如何使自定义的ListView定制listSelector [英] How to make custom listSelector on custom listView

查看:161
本文介绍了如何使自定义的ListView定制listSelector的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想弄清楚如何设置自定义listSelector我的ListView。在code是更多或更少的复制和放大器;从为他人工作计算器粘贴的解决方案,但它不为我工作

当我打开CAB模式,那么我可以选择和取消的项目,我看到在导航栏CAB所选项目的数量,但我​​没有看到列表中的任何指示。我想看看被选中的项目。任何想法,为什么它不工作?

布局/ category_list.xml:

 <?XML版本=1.0编码=UTF-8&GT?;
<的LinearLayout
    的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    的xmlns:工具=htt​​p://schemas.android.com/tool​​s
        机器人:ID =@ + ID / categories_layout
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    机器人:方向=垂直>
    < ListView控件
            机器人:ID =@ + ID / category_browser
            机器人:layout_width =match_parent
            机器人:layout_height =0dip
            机器人:layout_weight =1
            机器人:dividerHeight =1DP
                    机器人:listSelector =@绘制/ list_selector
                    机器人:drawSelectorOnTop =真
            工具:列表项=@布局/ category_list_item>
    < /&的ListView GT;
    <包括布局=@布局/广告/>
< / LinearLayout中>

布局/ category_list_item.xml:

 <?XML版本=1.0编码=UTF-8&GT?;
< com.fletech.smartbaby.api.CheckableLinearLayout
        的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
        的xmlns:工具=htt​​p://schemas.android.com/tool​​s
        机器人:ID =@ + ID / category_browser_list_item
        机器人:layout_width =match_parent
        机器人:layout_height =WRAP_CONTENT
        机器人:layout_gravity =补
        机器人:可点击=真
        机器人:重力=补
        机器人:方向=横向>
        < ImageView的
                机器人:ID =@ + ID / category_item_icon
                机器人:layout_width =90dp
                机器人:layout_height =90dp
                机器人:layout_gravity =补
                机器人:layout_weight =0
                        机器人:背景=#FFFFFF
                机器人:SRC =@绘制/ ic_launcher/>
        <的TextView
                机器人:ID =@ + ID / category_browser_list_title
                机器人:layout_width =WRAP_CONTENT
                机器人:layout_height =match_parent
                机器人:layout_weight =1
                机器人:重力=center_vertical |启动
                机器人:paddingLeft =10dp
                机器人:paddingRight =10dp
                        工具:文本=类别名称
                机器人:文字颜色=#000000
                机器人:TEXTSIZE =24sp/>        <包括布局=@布局/ category_features
            机器人:layout_centerInParent =真
            机器人:layout_alignParentRight =真
            机器人:layout_alignParentEnd =真
            />        <包括布局=@布局/ category_status
            机器人:layout_centerInParent =真
            机器人:layout_alignParentRight =真
            机器人:layout_alignParentEnd =真
            />
< /com.fletech.smartbaby.api.CheckableLinearLayout>

绘制/ list_selector.xml:

 <选择的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android>
    <项目>
        <形状机器人:形状=矩形>
            [固体机器人:颜色=#40777777/>
        < /形状>
    < /项目>
    <项目的android:state_long_ pressable =真正的>
        <形状机器人:形状=矩形>
            [固体机器人:颜色=#400000ff/>
        < /形状>
    < /项目>
    <项目的android:state_checkable =真正的>
        <形状机器人:形状=矩形>
            [固体机器人:颜色=#400000ff/>
        < /形状>
    < /项目>
    <项目的android:state_checked =真正的>
        <形状机器人:形状=矩形>
            [固体机器人:颜色=#800000ff/>
        < /形状>
    < /项目>
< /选择>

和CheckableLinearLayout.java:

 包com.fletech.smartbaby.api;进口android.annotation.TargetApi;
进口android.content.Context;
进口android.graphics.drawable.Drawable;
进口android.os.Build;
进口android.os.Parcel;
进口android.os.Parcelable;
//进口android.support.v7.widget.LinearLayoutCompat; //我需要这个?我看不出有什么区别
进口android.util.AttributeSet;
进口android.util.Log;
进口android.widget.Checkable;
进口android.widget.LinearLayout;公共类CheckableLinearLayout扩展的LinearLayout实现可勾选{
    私有静态最后弦乐TAG = CheckableLinearLayout.class.getSimpleName();
    私有静态最终诠释[] = CHECKED_STATE_SET {android.R.attr.state_checked};    私人布尔mChecked;    公共CheckableLinearLayout(上下文的背景下){
        超级(上下文);
    }    公共CheckableLinearLayout(上下文的背景下,ATTRS的AttributeSet){
        超(背景下,ATTRS);
    }    @TargetApi(Build.VERSION_ codeS.HONEYCOMB)
    公共CheckableLinearLayout(上下文的背景下,ATTRS的AttributeSet,诠释defStyle){
        超(背景下,ATTRS,defStyle);
    }    @覆盖
    公共无效setChecked(布尔选中){
        Log.v(TAG,setChecked:+查);
        如果(mChecked!=选中){
            mChecked =检查;
            refreshDrawableState();
        }
    }    @覆盖
    公共布尔器isChecked(){
        返回mChecked;
    }    @覆盖
    公共无效切换(){
        Log.v(TAG,切换:+ mChecked + - >中+(mChecked)!);
        setChecked(!mChecked);
    }    @覆盖
    //不知道,如果需要的话,因为它似乎没有这个工作,以及
    公共布尔performClick(){
        Log.v(TAGperformClick);
        切换();
        返回super.performClick();
    }    @覆盖
    //这可能是不必要
    保护无效drawableStateChanged(){
        Log.v(TAGdrawableStateChanged);
        super.drawableStateChanged();
        最终可绘制可绘制=的getBackground();
        如果(绘!= NULL)
        {
            最终诠释[] = myDrawableState getDrawableState();
            drawable.setState(myDrawableState);
            无效();
        }
    }    @覆盖
    保护INT [] onCreateDrawableState(INT extraSpace){
        Log.v(TAG,onCreateDrawableState:+ extraSpace);
        最终诠释[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        如果(器isChecked()){
            mergeDrawableStates(drawableState,CHECKED_STATE_SET);
        }        返回drawableState;
    }    @覆盖
    保护Parcelable的onSaveInstanceState(){
        SavedState结果=新SavedState(super.onSaveInstanceState());
        result.checked = mChecked;
        返回结果;
    }    @覆盖
    保护无效onRestoreInstanceState(Parcelable状态){
        如果(!(州的instanceof SavedState)){
            super.onRestoreInstanceState(州);
            返回;
        }        SavedState SS =(SavedState)状态;
        super.onRestoreInstanceState(ss.getSuperState());        setChecked(ss.checked);
    }    保护静态类SavedState扩展BaseSavedState {
        保护布尔检查;        保护SavedState(Parcelable超级大国){
            超(超状态);
        }        @覆盖
        公共无效writeToParcel(包裹出来,诠释标志){
            super.writeToParcel(出,旗);
            out.writeInt(选中1:0);
        }        公共静态最终Parcelable.Creator< SavedState> CREATOR =新Parcelable.Creator< SavedState>(){
            公共SavedState createFromParcel(包裹中){
                返回新SavedState(中);
            }            公共SavedState [] newArray(INT大小){
                返回新SavedState【尺寸】;
            }
        };        私人SavedState(包裹中){
            超级(在);
            检查= in.readInt()== 1;
        }
    }
}


解决方案

我花了我一个多星期,找出为什么这个东西适合所有人不为我工作。答案很简单。我希望这会帮助别人。

的解决方案是改变在选择的XML中的项目的顺序。没有任何国家的项目必须是最后一个:

 <选择的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android>
    <项目的android:state_long_ pressable =真正的>
        <形状机器人:形状=矩形>
            [固体机器人:颜色=#400000ff/>
        < /形状>
    < /项目>
    <项目的android:state_checkable =真正的>
        <形状机器人:形状=矩形>
            [固体机器人:颜色=#400000ff/>
        < /形状>
    < /项目>
    <项目的android:state_checked =真正的>
        <形状机器人:形状=矩形>
            [固体机器人:颜色=#800000ff/>
        < /形状>
    < /项目>    !< - 没有任何国家的项目必须是最后一个: - >
    <项目>
        <形状机器人:形状=矩形>
            [固体机器人:颜色=#40777777/>
        < /形状>
    < /项目>
< /选择>

的原因是,它似乎是分析器查找在相匹配的XML文件的第一个项目。这意味着,如果你有不同数目的状态的项目,那么你应该总是有那些有在XML的顶部定义更多的状态。例如:

 <选择的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android>
    <项目的android:state_checkable =真正的机器人:state_long_ pressable =真正的>
        <形状机器人:形状=矩形>
            [固体机器人:颜色=#FFFF00/>
        < /形状>
    < /项目>
    <项目的android:state_long_ pressable =真正的>
        <形状机器人:形状=矩形>
            [固体机器人:颜色=#FF0000/>
        < /形状>
    < /项目>
    <项目的android:state_checkable =真正的>
        <形状机器人:形状=矩形>
            [固体机器人:颜色=#00FF00/>
        < /形状>
    < /项目>
    <项目>
        <形状机器人:形状=矩形>
            [固体机器人:颜色=#40777777/>
        < /形状>
    < /项目>
< /选择>

这样,也只有这样,你会看到项目不同的颜色是:
- 既可选中和long_ pressable
- 可检查的,但不是long_ pressable
- long_ pressable但可勾选
- 一切

I'm trying to figure out how to set up a custom listSelector to my listView. The code is more-or-less copy&paste from solutions that worked for others in stackoverflow, but it doesn't work for me.

When I turn on the CAB mode, then I can select and deselect the items, and I see the number of selected items in the CAB navbar, but I don't see any indication in the list. I would like to see which items are selected. Any idea why it doesn't work?

layout/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>

layout/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>

drawable/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>

and 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;
        }
    }
}

解决方案

I took me more than a week to find out why this thing that works for everyone doesn't work for me. The answer is simple. I hope it'll help others.

The solution was to change the order of the items in the selector xml. The item without any states has to be the last one:

<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>

The reason is that it seems that the parser looks for the 1st item in the xml file that matches. It means that if you have items with different number of states, then you should always have those that have more states defined in the top of the xml. For example:

<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>

This way, and only this way, you'll see a different color on items that are: - both checkable and long_pressable - checkable, but not long_pressable - long_pressable but not checkable - everything else

这篇关于如何使自定义的ListView定制listSelector的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆