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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10318642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:17:06  来源:igfitidea点击:

Highlight for selected item in expandable list

androidandroid-layoutandroid-widget

提问by Barak

I have a layout where I have an expandable list in a fragment on the left and a details fragment on the right. This all works fine.

我有一个布局,其中左侧的片段中有一个可扩展的列表,右侧的片段中有一个详细信息。这一切正常。

Now I would like to indicate what item on the left is having it's details shown on the right and here I'm having a problem.

现在我想指出左边的哪个项目在右边显示了它的详细信息,在这里我遇到了问题。

In a normal list view I have achieved this by setting the choice mode for the list view to single and then using a state drawable based on the "activated" state. When I click the item, the background is set to my selected color and stays that way until I select another item on the list.

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

I tried to apply this to my expandable listview and it was/is a dismal failure. There were no errors, but the selected item did not maintain it's color state. I'm not sure if I'm not setting the choice mode properly for it (I've tried it in the layout file as well as programatically, it doesn't seem to make a difference), or pointing it to the wrong thing (not sure how that could be, but...)

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

Any help/pointers appreciated (even if it's in a completely different direction).

感谢任何帮助/指针(即使它的方向完全不同)。

Most current failure:

目前最失败的:

expandable listview code

可扩展的列表视图代码

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

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>

回答by silvermouse

Do the following on ExpandableListView:

在 ExpandableListView 上执行以下操作:

Step 1.Set choice mode to single (Can be done in xml as android:choiceMode = "singleChoice")

步骤 1.将选择模式设置为单一(可以在 xml 中完成,如android:choiceMode = "singleChoice"

Step 2.Use a selector xml as background (android:listSelector = "@drawable/selector_list_item")

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

Step 3.Call expandableListView.setItemChecked(index,true)in onChildClick() callback.

步骤3.呼叫expandableListView.setItemChecked(指数,真正的)在onChildClick()回调。

indexis a 0 based index of the child item calculated as follows

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

Group 1[index = 0]

第 1 组[索引 = 0]

  • Child item 1
  • Child item 2
  • Child item 3 [index = 3]
  • 子项 1
  • 子项 2
  • 子项 3 [索引 = 3]

Group 2[index = 4]

第 2 组[索引 = 4]

  • Child item 1
  • Child item 2
  • Child item 3 [index = 7]
  • 子项 1
  • 子项 2
  • 子项 3 [索引 = 7]

Group 3[index = 8]

第 3 组[索引 = 8]

  • Child item 1
  • Child item 2
  • Child item 3 [index = 11]
  • 子项 1
  • 子项 2
  • 子项 3 [索引 = 11]

If we have list headers as well, they would also account for index values.

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

Here is a working example:

这是一个工作示例:

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

回答by Prakash Gavade

After spending 3-4 hours it is made it its so simple no need to create extra XML files just check if the group item is expanded if yes then select color and in else statement make them as they are ....

花费 3-4 小时后,它变得如此简单,无需创建额外的 XML 文件,只需检查组项目是否展开(如果是),然后选择颜色,然后在 else 语句中按原样制作它们......

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

回答by Barak

I finally figured out how to make this work (for me). It seems a bit of the hack, but it's the only thing I've managed to get working for this.

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

Basically I create a two dimensional array to hold the selected state of the children, initialize it in the adapter constructor, then I reference that in my getChildViewmethod (in case the currently selected child scrolls out of view) and my onChildClickmethod (to change the current selection and turn off the old one).

基本上,我创建了一个二维数组来保存子项的选定状态,在适配器构造函数中对其进行初始化,然后在我的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

Constructorinitialize the array

构造函数初始化数组

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

    }

getChildViewneeded for when the child scrolls out of view

当孩子滚出视图时需要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; 
    } 

onChildClickchange selected item

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

回答by Driss Bounouar

I was having the same problem I fixed this by adding

我遇到了同样的问题,我通过添加解决了这个问题

v.setSelected(true);

here's a sample of my code :

这是我的代码示例:

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

                        }

my item xml

我的项目 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>

attribute android:drawSelectorOnTop="true"in the ExpandableListView element in the xml file (not the item child or group ) like this :

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

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

回答by Rusfearuth

The next solution help you make different list selector for group and child.

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

First of all, you need disable list selector for ExpendableListView:

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


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

After, you need copy an empty listSelector. You can do you like this

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


...
private Drawable empty;
...

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


Now, we need know when we will enable list selector or disable. You should add follow changes to your adapter for that:

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


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;
           }
       });
       ...
    }
...
}

That's all. I hope this solution keeps your time.

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

回答by user2779311

In case you need only the child item color to be changed than in the onchildclickmethod set the background color to the View v.

如果您只需要更改子项颜色而不是在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);
}

to do so set isChildSelectableto true in the adapter.

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

回答by Jorge Leandro Garcia

You can save the current view and change the background color of view within your click listeners:

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

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

回答by Ilya Shirokov

This simple solution has helped me when I was faced with the same question as the author

当我面临与作者相同的问题时,这个简单的解决方案对我有所帮助

I have a layout where I have an expandable list in a fragment on the left and a details fragment on the right. This all works fine. Now I would like to indicate what item on the left is having it's details shown on the right and here I'm having a problem.

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

To indicate what item in expandable list is selected go to ExpandableListView properties (in layout) and chose color for listSelector.

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

回答by NewUser

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

回答by NewUser

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