web-dev-qa-db-fra.com

Menu contextuel dans ListView personnalisé

Ce que je veux réaliser:

J'ai un adaptateur ListView personnalisé. À chaque liste, je souhaite ajouter un menu contextuel, assez similaire à ListView dans l'application Google Play actuelle.

Screenshot of Google Play items

Voici ce que j’ai essayé: La plupart de mon code provient de cet exemple Android samples\Android-19\ui\ActionBarCompat-ListPopupMenu

CustomFragmentPageAdapter.Java :

// create new fragment
mCustomFragment = CustomFragment.newInstance(position);

CustomFragment.Java

public class CustomFragment extends ListFragment implements View.OnClickListener{

...

@Override
public void onClick(final View v) {
    v.post(new Runnable() {
        @Override
        public void run() {
            showPopupMenu(v);
        }
    });
}

private void showPopupMenu(View view) {

    PopupMenu popup = new PopupMenu(getActivity(), view);

    popup.getMenuInflater().inflate(R.menu.popup_menu, popup.getMenu());

    popup.show();
}

CustomArrayAdapter :

public class CustomAdapter extends ArrayAdapter<WatchListPlayerItem> {
    ...    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final int pos = position;

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        final View rowView = inflater.inflate(R.layout.watch_list_row, parent, false);

        View popupButton = rowView.findViewById(R.id.imgPopUp);

        popupButton.setTag(getItem(position));

        popupButton.setOnClickListener(mFragment);

        return rowView;
    }
}

popup_menu.xml :

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item
        Android:id="@+id/install"
        Android:title="Install" />
    <item
        Android:id="@+id/addtowishlist"
        Android:title="Add to wishlist" />
</menu>

Sortie Logcat :

Java.lang.RuntimeException: Failed to resolve attribute at index 6
            at Android.content.res.TypedArray.getLayoutDimension(TypedArray.Java:603)
            at Android.view.ViewGroup$LayoutParams.setBaseAttributes(ViewGroup.Java:6423)
            at Android.view.ViewGroup$MarginLayoutParams.<init>(ViewGroup.Java:6591)
            at Android.widget.FrameLayout$LayoutParams.<init>(FrameLayout.Java:735)
...

L'erreur est renvoyée à popup.show () dans mon CustomFragment.

Cette erreur me rend clairement fou et TOUT aide pour résoudre ce problème est hautement appréciée!

9
Al0x

J'ai finalement trouvé la solution à mon problème, même si je n'ai aucune explication quant à son efficacité.

Avec l'importation suivante, j'ai toujours eu l'erreur:

import Android.support.v7.widget.PopupMenu;

Cela fonctionne bien avec l'importation suivante:

import Android.widget.PopupMenu;

J'ai testé le code fourni par Ric (Merci pour l'aide précieuse!) Et le mien. Les deux travaillent maintenant. Quelqu'un a peut-être une explication sur l'importance de l'importation dans ce cas.

36
Al0x

Commencez par créer une button dans votre custom-item-listview.xml puis ajoutez le code ci-dessous:

Button:

<Button
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="@string/button_text"
Android:id="@+id/button1"
... />

classe:

public class CustomAdapter extends ArrayAdapter<CustomItem> {

    private static Activity context = null;
    private final ArrayList<CustomItem> mItemsArrayList;
    private CustomFragment mFragment;


    public CustomAdapter(Activity context, ArrayList<CustomItem> itemsArrayList, CustomFragment fragment) {

        super(context, R.layout.watch_list_row, itemsArrayList);

        CustomAdapter.context = context;
        this.mItemsArrayList = itemsArrayList;
        this.mFragment = fragment;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final int pos = position;
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        final View rowView = inflater.inflate(R.layout.watch_list_row, parent, false);
    final Button popUp_btn = (Button)rowView.findViewById(R.id.button1);
    popUp_btn.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            final PopupMenu popup = new PopupMenu(context, popUp_btn);
            popup.getMenuInflater().inflate(R.menu.context_menu, popup.getMenu());
            popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                public boolean onMenuItemClick(MenuItem item) {
                    int i = item.getItemId();
                    if (i == R.id.item1) {
                        //do something
                        return true;
                    }
                    else if (i == R.id.item2){
                        //do something
                        return true;
                    }
                    else if (i == R.id.item3) {
                        //do something
                        return true;
                    }
                    else {
                        return onMenuItemClick(item);
                    }
                }
            });

            popup.show();

EDIT: Cela fonctionne bien pour moi:

TAB1

public  class TAB1 extends Fragment {
View view;

public TAB1() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.tab1, null);


            ListView list = (ListView) view.findViewById(Android.R.id.list);
            CustomList adapter = new CustomList(getActivity());
            adapter.addAll();
            list.setAdapter(adapter);


    return view;
}

CustomList:

public class CustomList extends ArrayAdapter<YourArrayAdapter> {

private static Activity context = null;

public CustomList(Activity context) {
    super(context, R.layout.custom_listview, web);
    CustomList.context = context;
}
@Override
public View getView(final int position, View view, ViewGroup parent) {
    LayoutInflater inflater = context.getLayoutInflater();
    final View rowView = inflater.inflate(R.layout.custom_listview, null, true);

    //your stuff here

    final Button popUp_btn = (Button)rowView.findViewById(R.id.button1);
    popUp_btn.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            final PopupMenu popup = new PopupMenu(context, popUp_btn);
            popup.getMenuInflater().inflate(R.menu.context_menu, popup.getMenu());
            popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                public boolean onMenuItemClick(MenuItem item) {
                    int i = item.getItemId();
                    if (i == R.id.item1) {
                        //do something
                        return true;
                    }
                    else if (i == R.id.item2){
                        //do something
                        return true;
                    }
                    else if (i == R.id.item3) {
                        //do something
                        return true;
                    }
                    else {
                        return onMenuItemClick(item);
                    }
                }
            });

            popup.show();

        }
    });

    return rowView;

}
5
Rick

utilisez this as (contexte d'activité) not contexte d'application ou contexte

     PopupMenu popup = new PopupMenu(this, v);
3
Uzair
    popup = (Button)findViewById(R.id.button);

    popup.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            PopupMenu popup = new PopupMenu(MainActivity.this,view);
            popup.getMenuInflater().inflate(R.menu.popup_menu,popup.getMenu());
            popup.show();
            popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    int id = item.getItemId();
                    if(id==R.id.install){
                        show_toast("Install Clicked");
                    }else{
                        show_toast("WishList Clicked");                            
                    }
                    return true;
                }
            });
        }
    });



    public void show_toast(String message){
        Toast.makeText(this,message,Toast.LENGTH_SHORT).show();
    }

Remarque:
N'oubliez pas d'importer ceci ....

import Android.support.v7.widget.PopupMenu;
import Android.view.MenuItem;
2
Karthick

Le code de lignes de Rick fonctionne parfaitement tant que vous importez les éléments suivants: 

import Android.widget.PopupMenu;

Pas celui ci-dessous: 

import Android.support.v7.widget.PopupMenu;
1
Josi

Je viens d'avoir le même problème lorsque j'ai modifié le style du thème parent: De

<style name="MainAppTheme" parent="@style/Theme.AppCompat.Light">

à

<style name="MainAppTheme" parent="@style/Theme.Base.AppCompat.Light">

Peut-être que votre application utilise le style Theme.Base, qui ne définit pas le sixième paramètre requis utilisé par PopupMenu. De SO question Comment utiliser ActionBarActivity avec Theme.Material , Theme.AppCompat étend Theme.Base.AppCompat

1
Philippe

J'ai corrigé une erreur similaire en passant simplement comme paramètre une activité statique. Par exemple:

static AppCompatActivity sActivity;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    sActivity = this;

yourLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        PopupMenu popup = new PopupMenu(sActivity, v);
        MenuInflater inflater = popup.getMenuInflater();
        inflater.inflate(R.menu.my_popup_menu, popup.getMenu());
        popup.show();
        }
   });
}

Votre problème pourrait aussi être celui-ci: Numéro 152141

J'espère que cela vous aidera, en respectant l'importation Android.support.v7.widget.PopupMenu.

Cordialement.

0
mlopezv86