Android:长按ExpandableListView的子视图?

tom*_*ash 46 android

ExpandableListView有一个setOnChildClickListener方法,但缺少setOnChild Long ClickListener方法.

当我添加setOnLongClickListener()了子视图时getChildView(),整个子列表变得完全无法点击(尽管parentView.setOnChildClickListener()存在并且之前正在工作).

如何在子视图上启用长按?

Nic*_*len 85

我设法ExpandableListView使用以下内容长时间点击子项目:

getExpandableListView().setOnItemLongClickListener(new OnItemLongClickListener() {
    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        if (ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
            int groupPosition = ExpandableListView.getPackedPositionGroup(id);
            int childPosition = ExpandableListView.getPackedPositionChild(id);

            // You now have everything that you would as if this was an OnChildClickListener() 
            // Add your logic here.

            // Return true as we are handling the event.
            return true;
        }

        return false;
    }
});
Run Code Online (Sandbox Code Playgroud)

花了很长时间才发现onItemLongClick中的id参数是*方法packedPosition所需的参数getPackedPosition,当然不清楚文档.

注意:要使此解决方案起作用,您需要覆盖适配器中的getGroupIdgetChildId()方法

   @Override
   public long getGroupId(int groupPosition) {
      return groupPosition;
   }

   @Override
   public long getChildId(int groupPosition, int childPosition) {
      return childPosition;
   }
Run Code Online (Sandbox Code Playgroud)

  • 优雅,有效的解决方案.与OnChildClickListener不冲突. (3认同)
  • 我已经按照这个解决方案找到了问题.当我试图通过这些`childPosition`和`groupPosition`从列表适配器的数据源获取对象时,它会抛出outOfIndexException.我在这里找到了另一个答案:http://stackoverflow.com/questions/5806100/identifying-the-group-that-has-been-clicked-in-an-expandablelistview解释了为什么我不能在这种情况下使用id.最后,我用答案解决了我的问题(你可以在我的下面/上面的答案中找到). (3认同)

tom*_*ash 40

我在Steve Oliver的博客上找到了答案:http://steveoliverc.wordpress.com/2009/10/16/context-menus-for-expandable-lists/

你应该使用onCreateContextMenu()而不是寻找setOnChildLongClickListener().这是史蒂夫的信息:

可扩展列表支持上下文菜单,其方式与标准列表完全相同:为上下文菜单添加侦听器(当用户长按列表项时).但是,与标准列表视图不同,您可能想知道用户是选择了组(可扩展项)还是子项(子项)列表项.

此外,如果用户尝试在组项上显示上下文菜单,您可能不想做任何事情.在某些情况下,您可能希望对组内的所有子项执行某些操作,但在我的Librarium应用程序中,我想忽略组项并仅为子项显示上下文菜单.

首先,您需要知道何时创建上下文菜单,以便您可以识别用户是否按下了组或子项.如果他们按下组,则取消上下文菜单.这也让我们有机会获得子项的文本,以便我们可以将它放入上下文菜单的标题中.

public void onCreateContextMenu(ContextMenu menu, View v,
                                ContextMenuInfo menuInfo)             
{
  super.onCreateContextMenu(menu, v, menuInfo);

  ExpandableListView.ExpandableListContextMenuInfo info =
    (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;

  int type =
    ExpandableListView.getPackedPositionType(info.packedPosition);

  int group =
    ExpandableListView.getPackedPositionGroup(info.packedPosition);

  int child =
    ExpandableListView.getPackedPositionChild(info.packedPosition);

  // Only create a context menu for child items
  if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) 
  {
    // Array created earlier when we built the expandable list
    String page =mListStringArray[group][child];

    menu.setHeaderTitle(page);
    menu.add(0, MENU_READ, 0, “Read page”);
    menu.add(0, MENU_EDIT, 0, “Edit page”);
    menu.add(0, MENU_FAVORITE, 0, “Add page to favorites”);
    menu.add(0, MENU_EXPORT, 0, “Export page to file”);
    menu.add(0, MENU_DELETE, 1, “Delete page”);
  }
}
Run Code Online (Sandbox Code Playgroud)

其次,创建上下文菜单:

public boolean onContextItemSelected(MenuItem menuItem) 
{
  ExpandableListContextMenuInfo info = 
    (ExpandableListContextMenuInfo) menuItem.getMenuInfo();

  int groupPos = 0, childPos = 0;

  int type = ExpandableListView.getPackedPositionType(info.packedPosition);
  if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) 
  {
    groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition);
    childPos = ExpandableListView.getPackedPositionChild(info.packedPosition);
  }

  // Pull values from the array we built when we created the list
  String author = mListStringArray[groupPos][0];
  String page = mListStringArray[groupPos][childPos * 3 + 1];
  rowId = Integer.parseInt(mListStringArray[groupPos][childPos * 3 + 3]);

  switch (menuItem.getItemId()) 
  {
    case MENU_READ:
      readNote(rowId);
      return true;

    case MENU_EDIT:
      editNote(rowId);
      return true;

    // etc..

    default:
      return super.onContextItemSelected(menuItem);
  }
}
Run Code Online (Sandbox Code Playgroud)

而已.现在,用户可以长按可扩展列表中的项目,并获取上下文菜单(如果它是子项目).

  • 作为旁注,请不要忘记onCreate方法中的registerForContextMenu调用.如果你(像我一样)忘记了,那么什么都行不通. (12认同)

toa*_*ran 32

我知道这个答案可能没有必要,但我有类似的情况,这些答案没有解决我的问题.所以我发布我的,以防有人可能需要它.希望你们所有人都不介意.

@Override
                public boolean onItemLongClick(AdapterView<?> parent, View childView, int flatPos, long id) {
                     if (ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
                            final ExpandableListAdapter adapter = ((ExpandableListView) parent).getExpandableListAdapter();
                            long packedPos = ((ExpandableListView) parent).getExpandableListPosition(flatPos);
                            int groupPosition = ExpandableListView.getPackedPositionGroup(packedPos);
                            int childPosition = ExpandableListView.getPackedPositionChild(packedPos);

                        // do whatever you want with groupPos and childPos here - I used these to get my object from list adapter.
                    return false;
                }
Run Code Online (Sandbox Code Playgroud)

编辑 这个Listview的解决方案很久以前了.我强烈建议立即转到RecyclerView.

  • +1.这是正确的解决方案.您首先需要平面(原始)视图位置,而不仅仅是该位置的对象ID. (2认同)
  • 哇!!!!同意!无法从之前的示例中获取te childPosition.它始终是相同的,即零 - 但现在,当我实现这个代码,它似乎工作完美!我会投票. (2认同)
  • autobot_101:我的投票给你答案.这个答案应该得到最大的投票. (2认同)

Men*_*amm 13

我正在寻找这个答案,但是这里没有给出正确的结果.

来自tomash的明显答案表明完全不同的方式.Nicholas的答案部分正确,但使用'id'是不正确的.

正确,正常,回答是:将position参数转换为packedPosition然后!使用此新packedPosition值来获取组和子ID.检查下面的代码

    getExpandableListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            long packedPosition = getExpandableListView().getExpandableListPosition(position);
            if (ExpandableListView.getPackedPositionType(packedPosition) == 
                    ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
                // get item ID's
                int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition);
                int childPosition = ExpandableListView.getPackedPositionChild(packedPosition);

                // handle data 
                ...

                // return true as we are handling the event.
                return true;
            }
            return false;
        }
    });
Run Code Online (Sandbox Code Playgroud)

编辑:我现在看到autobot几乎是正确的解决方案,除了测试getPackedPositionType,id而不是测试packetPosition