ExpandableListView - 将选定的子项保持为"已按下"状态

Sco*_*ott 16 android android-widget

我在左侧导航中使用ExpandableListView作为平板电脑屏幕.

当用户在我的可扩展列表中按下组的子项时,我希望将该子项保持在按下状态,以便用户知道正在显示右手内容的子项.

对于ListView,我能够在代码中使用此行完成此效果:

getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
Run Code Online (Sandbox Code Playgroud)

然后应用此选择器:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true" android:drawable="@drawable/menu_item_pressed" />
<item android:state_pressed="false" android:state_focused="false" android:drawable="@drawable/menu_item_normal" />
<item android:state_pressed="true" android:drawable="@drawable/menu_item_pressed" />
<item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/menu_item_pressed" />
Run Code Online (Sandbox Code Playgroud)

按下listView项后,listView项上的"state_activiated"为true.

我希望这个技术对我的expandableListView有用,但事实并非如此.我用了:

getExpandableListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
Run Code Online (Sandbox Code Playgroud)

然后使用上面相同的选择器,但它不起作用.我还尝试过其他状态,例如state_selected和state_checked,这些状态也不起作用.

上面的选择器正确应用按下和未按下状态.看起来使用ExpandableListView,按下一个孩子后状态不会被"激活".

任何帮助表示赞赏.谢谢!

Him*_*ani 33

在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>
Run Code Online (Sandbox Code Playgroud)

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

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

第1组 [指数= 0]

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

第2组 [指数= 4]

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

第3组 [指数= 8]

  • 儿童项目1
  • 儿童项目2
  • 子项目3 [索引= 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;
}
Run Code Online (Sandbox Code Playgroud)


Sco*_*ott 8

我最终解决了这个问题,而没有在子视图上使用选择器.expandableListView的适配器为每个组和子项获取数据.我为子数据添加了一个"selected"布尔值.该片段负责将每个子节点的选定布尔值正确设置为true或false.然后,在适配器的"getChildView"方法中,如果子节点的"selected"布尔值为true,我将视图的背景资源设置为"按下"背景.否则我将其设置为"未按下"背景.除了在子视图上使用textView的选择器以在按下时更改文本颜色以实现所需效果时,执行此操作.

下面是我的Fragment维护孩子的"选定"布尔值所做的事情:

  • 将您的组/子数据保存为片段中的类变量
  • onChildClick - 遍历子数据,设置所有"selected"= false.然后将当前组/子项的子项设置为true.通过调用setEmptyView刷新expandableListView,重置侦听器,并设置列表适配器.
  • onGroupClick - 循环子数据,设置所有"selected"= false.然后将当前组/子项的子项设置为true.
  • 在您的片段中显示列表的位置 - 填充适配器数据,设置列表适配器,在适配器上调用notifyDataSetChanged.通过调用setEmptyView刷新expandableListView,重置侦听器,并设置列表适配器.

除了上面我还维护一个currentGroupPosition和currentChildPosition作为类变量.使用setRetainInstance = true可以使其在屏幕旋转等方面正常工作.


hot*_*309 5

我认为没有任何内置方法可以使用内置Android功能进行尝试.为了进行一些测试,我开始使用Android API示例(C:\<android-sdk-directory>\samples\android-15\ApiDemos\src\com\example\android\apis\view\ExpandableList3.java)中的代码.

我用过ExpandableListView.CHOICE_MODE_SINGLE.选择模式适用于View检查或选择的任何内容.(该ExpandableListView源代码表示,它决定了有多少项目可以选择一次,但是ListView,它似乎适用于什么检查.)另外请注意,医生说你不能得到有效的结果getCheckedItemPosition对于ListView在单一选择模式.这似乎是真的.

我的测试表明,ExpandableListActivity它不会自动选中或选中点击/触摸的项目,也不会自动将焦点放在被点击的孩子身上.ExpandableListActivity单击其中一个子项后,只有自身和持有子项的组才会自动聚焦.

这是我的一些代码(大部分来自Android示例):

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    final String NAME = "NAME";
    final String IS_EVEN = "IS_EVEN";

    List<Map<String, String>> groupData = new ArrayList<Map<String, String>>();
    List<List<Map<String, String>>> childData = new ArrayList<List<Map<String, String>>>();

    for (int i = 0; i < 12; i++) {

        Map<String, String> curGroupMap = new HashMap<String, String>();
        groupData.add(curGroupMap);

        curGroupMap.put(NAME, "Group " + i);
        curGroupMap.put(IS_EVEN, (i % 2 == 0) ? "This group is even" : "This group is odd");

        List<Map<String, String>> children = new ArrayList<Map<String, String>>();

        for (int j = 0; j < 12; j++) {

            Map<String, String> curChildMap = new HashMap<String, String>();
            children.add(curChildMap);

            curChildMap.put(NAME, "Child " + j);
            curChildMap.put(IS_EVEN, (j % 2 == 0) ? "This child is even" : "This child is odd");
        }

        childData.add(children);
    }

    SimpleExpandableListAdapter adapter = new SimpleExpandableListAdapter(

        this,
        groupData,
        android.R.layout.simple_expandable_list_item_1,
        new String[] {NAME, IS_EVEN},
        new int[] {android.R.id.text1, android.R.id.text2},
        childData,
        R.layout.child, 
        new String[] {NAME, IS_EVEN},
        new int[] {android.R.id.text1, android.R.id.text2}
        );

    ExpandableListView expListView = (ExpandableListView)findViewById(android.R.id.list);

    setListAdapter(adapter);
    expListView.setChoiceMode(ExpandableListView.CHOICE_MODE_SINGLE);
    expListView.setOnChildClickListener(new OnChildClickListener() {

        @Override
        public boolean onChildClick(ExpandableListView expListView, View viewClicked, int groupPosition, int childPosition, long childRowId) {

            viewClicked.setSelected(true); // the only way to force a selection of the clicked item      
Run Code Online (Sandbox Code Playgroud)

请注意最后一行,它强制单击的子项具有选定状态.然后,您可以使用selectorDrawable状态列表的XML 在选中项时突出显示所选项.(这不完全有效 - 更多内容如下.)

onChildClick在我的内部ExpandableListActivity,我做了一些测试,发现了以下内容:

groupPosition; // index of group within the ExpandableListViewActivity           
childRowId; // for my particular ExpandableListView, this was the index of the child in the group
childPosition; // for my particularExpandableListView, this was also the index of the child in the group

expListView.getCheckedItemPosition(); // null - from ListView class
expListView.getSelectedView(); // null - from AbsListView class
expListView.getSelectedItemId(); // a long, based on the packed position - from AdapterView class
expListView.getSelectedId(); // -1 - from ExpandableListView class, calls getSelectedPosition()
expListView.getSelectedPosition(); // -1 - from ExpandableListView class, calls getSelectedItemPosition()
expListView.getSelectedItemPosition(); // -1 - from AdapterView class
expListView.getFocusedChild(); // null - from ViewGroup class
expListView.getItemIdAtPosition(1); // a long (View ID) - from AdapterView class
viewClicked.isFocused()); // false
viewClicked.isPressed()); // false
viewClicked.isSelected()); // true only if we explicitly set it to true
expListView.isFocused()); // true
expListView.isPressed()); // false
expListView.isSelected()); // false
expListView.getCheckedItemPosition())); // -1 - from ListView
expListView.getSelectedId())); // -1 - from ExpandableListView  

/* expListView.getChildAt(childPosition) is not helpful, because it looks at the rendered 
   LinearLayout with a bunch of TextViews inside it to get the index and find the child,
   and you won't generally know where to look for the child you want */
Run Code Online (Sandbox Code Playgroud)

我也尝试创建一个新的OnItemClickListener并实现它的onItemClick方法.虽然文档表明onItemClickListener它将以某种身份在ExpandableListViews上运行,但我从未见过它.

我试图改变所选子项的背景颜色并保持突出显示的第一件事并不顺利.我在XML文件中设置了一个Drawablefor .它有点工作,但提出了几个问题.android:state_window_focused="true"selector

我尝试的第二件事是onChildClick通过调用明确选择按下的项目viewClicked.setSelected(true);.这里的问题较少:

1)如果我滚动直到突出显示的项目不在视图中并返回到它,突出显示已消失,2)如果我旋转手机会发生同样的情况,3)突出显示的项目的状态不再被选中因为它在显示屏上不再可见.

Android ExpandableListView显然不像手风琴式左导航菜单那样工作,尽管这似乎是一个相当明显的用途.如果你想以这种方式使用它,我认为你将不得不进行大量的定制并深入研究如何View绘制.

祝好运.

  • 更换灯泡需要多少Android开发团队工程师?没有,因为他们决定不支持更换灯泡,所以你必须自己改变它. (2认同)