Android: долго нажимать на дочерние представления ExpandableListView? - PullRequest
46 голосов
/ 01 марта 2010

ExpandableListView имеет метод setOnChildClickListener, но в нем отсутствует setOnChild Long ClickListener метод.

Когда я добавил setOnLongClickListener() в дочернее представление в getChildView(), весь подсписок стал полностью неактивным (несмотря на то, что parentView.setOnChildClickListener() присутствует и работает раньше).

Как я могу включить длинные клики на дочерних представлениях?

Ответы [ 5 ]

85 голосов
/ 30 ноября 2011

Мне удалось заставить длинные клики работать с дочерним элементом 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;
    }
});

Потребовалось много времени, чтобы выяснить, что аргумент id в onItemLongClick был аргументом packedPosition, необходимым для getPackedPosition* методов, что, конечно, не ясно из документации.

Примечание: Чтобы это решение работало, необходимо переопределить методы getGroupId и getChildId() в адаптере

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

   @Override
   public long getChildId(int groupPosition, int childPosition) {
      return childPosition;
   }
40 голосов
/ 01 марта 2010

Я нашел ответ в блоге Стива Оливера здесь: 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”);
  }
}

Во-вторых, создайте контекстное меню:

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

Вот и все. Теперь пользователи могут долго нажимать на элемент в расширяемом списке и получать контекстное меню, если это дочерний элемент.

32 голосов
/ 08 мая 2013

Я знаю, что в этом ответе может не быть необходимости, но у меня похожая ситуация, и ни один из них не решил мою проблему. Поэтому я публикую свою на тот случай, если кому-то это может понадобиться. Надеюсь, все, что вы, ребята, не возражаете.

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

Редактировать Это решение для Listview было давно. Я настоятельно рекомендую перейти на RecyclerView сейчас.

12 голосов
/ 31 августа 2013

Я искал этот ответ, но не здесь дал правильные результаты.

Отмеченный ответ от tomash предполагает совершенно другой способ. Ответ от Николай частично правильный, но использование 'id' неверно.

Правильно, работает, ответ: преобразовать position параметр в packedPosition и ТО! используя это новое значение packedPosition для получения групповых и дочерних идентификаторов. Проверьте код ниже

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

EDIT : теперь я вижу, что autobot имеет почти правильное решение, за исключением тестирования getPackedPositionType на id, а не на packetPosition

1 голос
/ 23 мая 2012

Я справляюсь с твоей проблемой. просто установите элемент тега ur и используйте его следующим образом:

adapter = new ExpandableListAdapter() {


        private String[] groups = { "Biceps", "Deltoids", "Hamstrings", "Lower Back","Quadriceps","Triceps","Wrist" };
        private String[][] children = {
                { "Konsantra Dumbell curl", "Hammer curl", "Barbell Biceps Curl", "Prone Curl" },
                { "Arnold Press", "Lateral Raise", "Dumbell Upright row", "Bar Military Press" },
                { "Dead Lift", "Hack Squat","Zercher Squat","Seated Leg Flexion" },
                { "Back Raise", "Superman" },
                { "Back Squat", "Bulgarian Split Squat","Dumbell Lunge" },
                { "Bench Dip", "French Press","Triceps Extension" },
                { "Dumbell Wrist Curl "," Reverse Writst Curl"}
        };
        public void unregisterDataSetObserver(DataSetObserver observer) {
            // TODO Auto-generated method stub

        }

        public void registerDataSetObserver(DataSetObserver observer) {
            // TODO Auto-generated method stub

        }

        public void onGroupExpanded(int groupPosition) {
            // TODO Auto-generated method stub

        }

        public void onGroupCollapsed(int groupPosition) {
            // TODO Auto-generated method stub

        }

        public boolean isEmpty() {
            // TODO Auto-generated method stub
            return false;
        }

        public boolean isChildSelectable(int groupPosition, int childPosition) {
            // TODO Auto-generated method stub
            return true;
        }

        public boolean hasStableIds() {
            // TODO Auto-generated method stub
            return true;
        }

        public View getGroupView(int groupPosition, boolean isExpanded,
                View convertView, ViewGroup parent) {
             TextView textView = getGenericView();
                textView.setText(getGroup(groupPosition).toString());
                textView.setTag((Object)getGroup(groupPosition).toString()+"G");
                return textView;
        }

        public long getGroupId(int groupPosition) {
            // TODO Auto-generated method stub
            return groupPosition;
        }

        public int getGroupCount() {
            // TODO Auto-generated method stub
            return groups.length;
        }

        public Object getGroup(int groupPosition) {
            // TODO Auto-generated method stub
            return groups[groupPosition];
        }

        public long getCombinedGroupId(long groupId) {
            // TODO Auto-generated method stub
            return 0;
        }

        public long getCombinedChildId(long groupId, long childId) {
            // TODO Auto-generated method stub
            return 0;
        }

        public int getChildrenCount(int groupPosition) {
            // TODO Auto-generated method stub
            return children[groupPosition].length;
        }

        public View getChildView(int groupPosition, int childPosition,
                boolean isLastChild, View convertView, ViewGroup parent) {
             TextView textView = getGenericView();
                textView.setText(getChild(groupPosition, childPosition).toString());
                textView.setTag((Object)getChild(groupPosition, childPosition).toString()+"C");
                return textView;
        }

        public long getChildId(int groupPosition, int childPosition) {
            // TODO Auto-generated method stub
            return childPosition;
        }

        public Object getChild(int groupPosition, int childPosition) {
            // TODO Auto-generated method stub
            return children[groupPosition][childPosition];
        }

        public boolean areAllItemsEnabled() {
            // TODO Auto-generated method stub
            return false;
        }

        public TextView getGenericView() {
            // Layout parameters for the ExpandableListView
            AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                    ViewGroup.LayoutParams.FILL_PARENT, 64);

            TextView textView = new TextView(expandXml.this);
            textView.setLayoutParams(lp);
            // Center the text vertically
            textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
            // Set the text starting position
            textView.setPadding(36, 0, 0, 0);

            return textView;
        }

    };

А затем setOnItemLongClickListener для расширяемого ListView.

listView.setOnItemLongClickListener(new OnItemLongClickListener() {

        public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
                int arg2, long arg3) {
            // TODO Auto-generated method stub
            String s=null;

                int childPosition =ExpandableListView.getPackedPositionChild(arg3);
                if(arg1.getTag()!=null){
                Object o= arg1.getTag();

                 s = o.toString();
                }
                Toast.makeText(expandXml.this ,s , Toast.LENGTH_SHORT).show();

            return false;
        }
    });

Вот и мы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...