Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Popup Menu in custom ListView

What I want to achieve:

I have a custom ListView adapter. To each Listitem I want to add a popup menu, pretty similar to the ListView in the current Google Play application.

Screenshot of Google Play items

This is what I tried: Most of my code comes from this Android sample 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>

Logcat output:

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)
...

The error is thrown at popup.show() in my CustomFragment.

This error is clearly driving me crazy and ANY help to solve this issue is highly appreciated!

like image 325
Al0x Avatar asked Jan 05 '15 15:01

Al0x


2 Answers

I finally found the solution to my problem, eventhough I have no explanation why this solution works.

With the following import I always had the error:

import android.support.v7.widget.PopupMenu;

It works fine with the following import:

import android.widget.PopupMenu;

I tested the code provided by Ric (Thanks for the great help!) and my own. Both are working now. Maybe someone has an explanation why the import matters in this case.

like image 157
Al0x Avatar answered Sep 22 '22 05:09

Al0x


First create a button in your custom-item-listview.xml and then add the code below:

Button:

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

class:

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: This works well for me:

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;

}
like image 30
Rick Avatar answered Sep 22 '22 05:09

Rick