46 votes

Android: clic long sur les vues enfant d'un ExpandableListView?

ExpandableListView a une méthode setOnChildClickListener, mais elle manque de la méthode setOnChild * Long * ClickListener .

Lorsque j'ai ajouté la méthode setOnLongClickListener () à la vue enfant dans getChildView (), la sous-liste entière est devenue complètement impossible à cliquer (malgré la présence de parentView.setOnChildClickListener () auparavant).

Comment puis-je activer les longs clics sur les vues enfants?

85voto

Nicholas Harlen Points 481

J'ai réussi à obtenir de longs clics de travail sur un élément enfant ExpandableListView, en utilisant les éléments suivants:

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

Il a fallu du temps pour comprendre que l'argument id dans onItemLongClick était l'argument wrappéPosition requis par les méthodes getPackedPosition *, ce qui n'est certainement pas clair dans la documentation.

40voto

tomash Points 4364

J'ai trouvé une réponse sur Steve Oliver blog ici: http://steveoliverc.wordpress.com/2009/10/16/context-menus-for-expandable-lists/

Vous devez utiliser onCreateContextMenu() au lieu de rechercher l' setOnChildLongClickListener(). Voici Steve info:

Une liste extensible prend en charge les menus contextuels dans à peu près de la même façon qu'une liste standard n': ajouter un écouteur pour le menu contextuel (lorsque l'utilisateur a longtemps appuyé sur un élément de liste). Contrairement à une norme d'affichage de liste, toutefois, vous voulez probablement savoir si l'utilisateur a sélectionné un groupe (extensible élément) ou un enfant (sous-élément) de l'élément de liste.

En outre, vous ne pourriez pas vouloir faire quelque chose si l'utilisateur tente d'afficher un menu contextuel sur un élément du groupe. Il pourrait y avoir des cas où vous voulez faire quelque chose pour tous les enfants de moins de un groupe, mais dans mon Librarium application, je voulais ignorer les éléments de groupe et de présenter le menu contextuel que pour les enfants.

Tout d'abord, vous devez savoir lorsque le menu contextuel va être créé afin que vous puissiez déterminer si l'utilisateur a appuyé sur un groupe ou un enfant. Si ils ont fait pression sur un groupe, puis annuler le menu contextuel. Cela nous donne également une chance d'obtenir le texte de l'enfant, de sorte que nous pouvons le mettre dans l'en-tête du menu de contexte.

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

Deuxièmement, créer le Menu Contextuel:

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

C'est tout. Désormais, les utilisateurs peuvent à long appuyez sur un élément dans une liste extensible, et obtenir le menu contextuel si c'est un enfant de l'élément.

32voto

autobot_101 Points 415

Je sais que cette réponse n'est peut-être pas nécessaire, mais j'ai une situation similaire et aucune de ces réponses ne résout mon problème. Je poste donc le mien au cas où quelqu'un en aurait besoin. J'espère que ça ne vous dérange pas.

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

13voto

menion.asamm Points 325

J'étais à la recherche pour cette réponse, mais non, ici, a donné des résultats corrects.

Marqué réponse de tomash suggèrent une façon totalement différente. Réponse de Nicolas est en partie exact, mais à l'aide de " id " est incorrect.

Correct, le travail, la réponse est: convertir position paramètre packedPosition PUIS de! l'utilisation de ce nouveau packedPosition de la valeur à obtenir du groupe et de l'enfant de son identification. Code de vérification ci-dessous

    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: je vois maintenant que autobot a presque bonne solution, à l'exception de test getPackedPositionType sur id et pas sur packetPosition

1voto

Acablack Points 34

Je gère votre problème. Il suffit de définir une balise ur item et de l’utiliser comme ceci:

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

    };
 

Et ensuite setOnItemLongClickListener pour Expandable 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;
        }
    });
 

Et c'est parti.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X