突出显示可展开列表中的选定项目

时间:2012-04-25 15:18:19

标签: android android-layout android-widget

我有一个布局,我在左边的片段中有一个可扩展列表,右边有一个细节片段。一切正常。

现在我想说明左边的项目是否显示右侧的详细信息,此处我遇到了问题。

在普通列表视图中,我通过将列表视图的选择模式设置为单个,然后使用基于“激活”状态的可绘制状态来实现此目的。当我单击该项目时,背景将设置为我选择的颜色并保持这种状态,直到我在列表中选择另一个项目。

我尝试将此应用于我的可扩展列表视图,这是一个令人沮丧的失败。没有错误,但所选项目没有保持其颜色状态。我不确定我是否正在为它设置正确的选择模式(我已经在布局文件中尝试了它以及编程方式,它似乎没有什么区别),或者指向错误的东西(不知道那是怎么回事,但是......)

任何帮助/指针都会受到赞赏(即使它处于完全不同的方向)。

目前大多数失败:

可扩展列表视图代码

private void fillData(String group, String child) {
    ExpandableListView lv;
    mGroupsCursor = mDbHelper.fetchGroup(group);
    getActivity().startManagingCursor(mGroupsCursor);
    mGroupsCursor.moveToFirst();
    lv = (ExpandableListView) getActivity().findViewById(R.id.explist);
    lv.setChoiceMode(ExpandableListView.CHOICE_MODE_SINGLE);        

    mAdapter = new MyExpandableListAdapter(mGroupsCursor, getActivity(),
            R.layout.explistlayout,
            R.layout.explistlayout,
            new String[] { "_id" },
            new int[] { android.R.id.text1 },
            new String[] { child },
            new int[] { android.R.id.text1 });
    lv.setAdapter(mAdapter);
    registerForContextMenu(lv);

    lv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { 
        @Override 
        public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id)  
        { 
            mRowId  = id;
            EventDisplayFragment eventdisplay = new EventDisplayFragment();
            getFragmentManager().beginTransaction().replace(R.id.rightpane, eventdisplay).commit();
            return true; 
        } 
        }); 
}

public class MyExpandableListAdapter extends SimpleCursorTreeAdapter {

    public MyExpandableListAdapter(Cursor cursor, Context context,
            int groupLayout, int childLayout, String[] groupFrom,
            int[] groupTo, String[] childrenFrom, int[] childrenTo) {
        super(context, cursor, groupLayout, groupFrom, groupTo,
                childLayout, childrenFrom, childrenTo);
    }
    @Override
    protected Cursor getChildrenCursor(Cursor groupCursor) {
        Cursor childCursor = mDbHelper.fetchChildren(mGroup, groupCursor
                .getString(groupCursor
                        .getColumnIndex(AttendanceDB.EVENT_ROWID)));
        getActivity().startManagingCursor(childCursor);
        childCursor.moveToFirst();
        return childCursor;
    }
}

item_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item 
     android:state_pressed="true" 
     android:drawable="@color/green" />
    <item 
     android:state_selected="true" 
     android:drawable="@color/blue" />
    <item 
     android:state_focused="true" 
     android:drawable="@color/violet" />
    <item 
     android:state_activated="true" 
     android:drawable="@color/blue" />
</selector>

11 个答案:

答案 0 :(得分:31)

在ExpandableListView上执行以下操作:

步骤1。将选择模式设置为单一(可以在xml中完成 android:choiceMode =“singleChoice”

第2步。使用选择器xml作为背景( android:listSelector =“@ drawable / selector_list_item”

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
   android:exitFadeDuration="@android:integer/config_mediumAnimTime">

   <item android:drawable="@android:color/holo_blue_bright" android:state_pressed="true"/>
   <item android:drawable="@android:color/holo_blue_light" android:state_selected="true"/>
   <item android:drawable="@android:color/holo_blue_dark" android:state_activated="true"/>

</selector>

第3步。在onChildClick()回调中调用 expandableListView.setItemChecked(index,true)

index 是子项的0基索引,计算如下

第1组 [index = 0]

  • 儿童项目1
  • 子项目2
  • 子项目3 [index = 3]

第2组 [index = 4]

  • 儿童项目1
  • 子项目2
  • 子项目3 [index = 7]

第3组 [index = 8]

  • 儿童项目1
  • 子项目2
  • 子项目3 [index = 11]

如果我们也有列表标题,他们也会考虑索引值。

这是一个有效的例子:

@Override
public boolean onChildClick(ExpandableListView parent, View v,
        int groupPosition, int childPosition, long id) {
    ...

    int index = parent.getFlatListPosition(ExpandableListView.getPackedPositionForChild(groupPosition, childPosition));
    parent.setItemChecked(index, true);


    return true;
}

答案 1 :(得分:14)

花了3-4个小时之后,它变得如此简单,不需要创建额外的XML文件,只需检查是否扩展了组项目,如果是,则选择颜色,而在else语句中将它们设为原样.... / p>

@Override
//in this method you must set the text to see the parent/group on the list
public View getGroupView(final int i, boolean b, View view, ViewGroup viewGroup) {

    if (view == null) {
        view = inflater.inflate(R.layout.list_item_parent, viewGroup,false);
    }

    if(b){
        view.setBackgroundResource(R.color.waterblue);
    }else{
        view.setBackgroundColor(color.transparent);
    }


    //return the entire view
    return view;
}

答案 2 :(得分:6)

我终于想出了如何使这项工作(对我而言)。这似乎有点像黑客,但这是我唯一能够为此工作的。

基本上我创建了一个二维数组来保存子节点的选定状态,在适配器构造函数中初始化它,然后在我的getChildView方法中引用它(如果当前选中的子节点滚出视图)和我的onChildClick方法(更改当前选择并关闭旧选项)。

private selectedStatus[][];  // array to hold selected state
private View oldView;        // view to hold so we can set background back to normal after selection of another view

构造函数 初始化数组

    public MyExpandableListAdapter(Cursor cursor, Context context,
            int groupLayout, int childLayout, String[] groupFrom,
            int[] groupTo, String[] childrenFrom, int[] childrenTo) {
        super(context, cursor, groupLayout, groupFrom, groupTo,
                childLayout, childrenFrom, childrenTo);
        selectedStatus = new boolean[cursor.getCount()][];
        for (int i = 0; i < cursor.getCount(); i++) {
            cursor.moveToPosition(i);
            Cursor childCheckCursor = mDbHelper.fetchChildren(mGroup,
                    cursor.getString(cursor
                            .getColumnIndex(AttendanceDB.EVENT_ROWID)));
            getActivity().startManagingCursor(childCheckCursor);
            selectedStatus[i] = new boolean[childCheckCursor.getCount()];
            for (int j = 0; j < childCheckCursor.getCount(); j++) {
                selectedStatus[i][j] = false;
            }
        }

    }
当孩子滚出视野时需要

getChildView

    @Override 
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { 
        final View v = super.getChildView(groupPosition, childPosition, isLastChild, convertView, parent); 
        if(selectedStatus[groupPosition][childPosition] == true){
            v.setBackgroundResource(R.color.blue);                          
        } else {
            v.setBackgroundResource(R.color.black);
        }
        return v; 
    } 

onChildClick 更改所选项目

    lv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
        @Override
        public boolean onChildClick(ExpandableListView parent, View v,
                int groupPosition, int childPosition, long id) {
            mRowId = id;
            EventDisplayFragment eventdisplay = new EventDisplayFragment();
            getFragmentManager().beginTransaction()
                    .replace(R.id.rightpane, eventdisplay).commit();
            if(oldView != null){
                oldView.setBackgroundResource(R.color.black);   // change the background of the old selected item back to default black                 }
            oldView = v;                                        // set oldView to current view so we have a reference to change back on  next selection
            for (int i = 0; i < selectedStatus.length; i++) {
                for (int j = 0; j < checkedStatus[i].length; j++) {
                    if(i == groupPosition && j == childPosition){  // set the current view to true and all others to false
                        selectedStatus[i][j] = true;
                    } else {
                        selectedStatus[i][j] = false;
                    }
                }
            }
            v.setBackgroundResource(R.color.blue);
            return true;
        }
    });

答案 3 :(得分:2)

我遇到了同样的问题,我通过添加

解决了这个问题
v.setSelected(true);

这是我的代码示例:

expandableListDetailsLevel.setChoiceMode(ExpandableListView.CHOICE_MODE_SINGLE);
        expandableListDetailsLevel
                .setOnGroupExpandListener(new OnGroupExpandListener() {

                    public void onGroupExpand(int groupPosition) {

                        if(groupPosition!=1){
                            expandableIsThere = false;
                        }

                        for (int i = 0; i < len; i++) {
                            if (i != groupPosition) {
                                expandableListDetailsLevel.collapseGroup(i);
                            }
                        }
                    }
                });

        expandableListDetailsLevel
                .setOnChildClickListener(new OnChildClickListener() {

                    @Override
                    public boolean onChildClick(ExpandableListView parent,
                            View v, int groupPosition, int childPosition,
                            long id) {


                        v.setSelected(true);

                        }

我的项目xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@drawable/selector" >


<TextView
    android:id="@+id/TVChild"
    android:layout_width="fill_parent"
    android:layout_height="match_parent"
    android:textColor="#000"
    android:textSize="12dp"/>

</LinearLayout>

xml文件中的ExpandableListView元素中的属性android:drawSelectorOnTop="true"(不是项子项或组),如下所示:

<ExpandableListView
                android:id="@+id/expandableViewDetailsBriefing"
                android:layout_width="fill_parent"
                android:layout_height="match_parent"
                android:background="#fff"
                android:drawSelectorOnTop="true"
                android:dividerHeight="1px"
                android:childDivider="@color/Gris"
                android:indicatorRight="690dp"
                android:textFilterEnabled="true" >
            </ExpandableListView>

答案 4 :(得分:2)

下一个解决方案可帮助您为组和子项创建不同的列表选择器。

首先,您需要为ExpendableListView禁用列表选择器:


...
   <ExpandableListView
            ...
            android:listSelector="@android:color/transparent"
            ...
            />
...

之后,您需要复制一个空的listSelector。你可以这样做


...
private Drawable empty;
...

// binding view here. Name of ExpandableListView will be elv
empty = elv.getSelector();


现在,我们需要知道何时启用列表选择器或禁用。您应该为您的适配器添加以下更改:


my adapter here {
...
    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View view, ViewGroup parent)
    {
       ...
       // after, we've got view of goup
       view.setOnTouchListener(new View.OnTouchListener()
       {
           @Override
           public boolean onTouch(View v, MotionEvent event)
           {
               elv.setSelector(empty);
               return false;
           }
       });
       ...
    }
...
    @Override
    public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, final ViewGroup parent)
    {
       ...
       // after, we've got view of child
       view.setOnTouchListener(new View.OnTouchListener()
       {
           @Override
           public boolean onTouch(View v, MotionEvent event)
           {
               elv.setSelector(R.drawable.my_custom_list_selector);
               return false;
           }
       });
       ...
    }
...
}

这就是全部。我希望这个解决方案可以节省您的时间。

答案 5 :(得分:2)

如果您只需要更改子项目颜色而不是onchildclick方法,请将背景颜色设置为View v。

@Override
            public boolean onChildClick(ExpandableListView parent, View v,
                    int groupPosition, int childPosition, long id) {
                // TODO Auto-generated method stub
                v.setBackgroundColor(Color.RED);
}

这样做可以在适配器中将isChildSelectable设置为true。

答案 6 :(得分:1)

您可以保存当前视图并更改点击侦听器中视图的背景颜色:

View currentView;
ExpandableListView elv;

elv.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
    @Override
    public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
        if(currentView != null) {
            currentView.setBackgroundColor(Color.parseColor("#FFFFFF"));
        }
        v.setBackgroundColor(Color.parseColor("#EEEEEE"));
        currentDrawerView = view;

        //do something

        return false;
    }
});
elv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
    @Override
    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
        if(currentView != null) {
            currentView.setBackgroundColor(Color.parseColor("#FFFFFF"));
        }
        v.setBackgroundColor(Color.parseColor("#EEEEEE"));
        currentDrawerView = view;

        //do something

        return false;
    }
});

答案 7 :(得分:1)

当我遇到与作者相同的问题时,这个简单的解决方案帮助了我

  

我有一个布局,我在一个片段中有一个可扩展列表   左边和右边的细节片段。一切正常。现在我   我想说明左边的哪个项目有详细信息   显示在右边,这里我遇到了问题。

要指示可扩展列表中的哪个项目被选中,请转到ExpandableListView属性(在布局中)并为listSelector选择颜色。

答案 8 :(得分:0)

expListView.setOnChildClickListener(new OnChildClickListener() {

            @Override
            public boolean onChildClick( ExpandableListView parent, View v,
                                         int groupPosition, int childPosition,
                                         long id) {



                for (int i = 1; i < expListView.getChildCount(); i++) {
                    View child = (View) expListView.getChildAt(i);
                    child.setBackgroundColor(Color.BLACK);
                }


                if(childPosition==0){
                    initWebView("URL");

                }
                if(childPosition==1) {
                    initWebView("URL");

                }
                if(childPosition==2) {

                    initWebView("URL");

                }
                if(childPosition==3) {
                    initWebView("URL");

                }
                if(childPosition==4) {
                    initWebView("URL");

                }
                if(childPosition==5) {
                    initWebView("URL");
                }

                v.setBackgroundColor(Color.GRAY);


                expListView.setVisibility(View.GONE);
                webView.setVisibility(View.VISIBLE);
                return false;
            }
        });
 }

答案 9 :(得分:0)

expListView.setOnChildClickListener(new OnChildClickListener() {

        @Override
        public boolean onChildClick( ExpandableListView parent, View v,
                                     int groupPosition, int childPosition,
                                     long id) {



            for (int i = 1; i < expListView.getChildCount(); i++) {
                View child = (View) expListView.getChildAt(i);
                child.setBackgroundColor(Color.BLACK);
            }


            if(childPosition==0){
                initWebView("URL");

            }
            if(childPosition==1) {
                initWebView("URL");

            }
            if(childPosition==2) {

                initWebView("URL");

            }
            if(childPosition==3) {
                initWebView("URL");

            }
            if(childPosition==4) {
                initWebView("URL");

            }
            if(childPosition==5) {
                initWebView("URL");
            }

            v.setBackgroundColor(Color.GRAY);


            expListView.setVisibility(View.GONE);
            webView.setVisibility(View.VISIBLE);
            return false;
        }
    });
}

答案 10 :(得分:-2)

只需使用以下

    <ExpandableListView
        android:id="@+id/expandable_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:childDivider="#474043"
         android:groupIndicator="@null"
         android:listSelector = "@drawable/item_selector"
        android:background="#555"
        android:drawSelectorOnTop="true"
        android:textFilterEnabled="true"
        />

和你的item_selector.xml如下

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@color/selection_color_for_ex_list" android:state_pressed="true"/>
    <item android:drawable="@color/selection_color_for_ex_list" android:state_selected="true"/>
    <item android:drawable="@color/selection_color_for_ex_list" android:state_focused="true"/>

</selector>