自定义ListView中的弹出菜单

12
我想要实现的目标:
我有一个自定义的ListView适配器。我想要给每个Listitem添加一个弹出菜单,这个菜单非常类似于当前Google Play应用程序中的ListView。
这是我尝试过的内容: 我的大部分代码都来自于这个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();
}

自定义数组适配器:

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 输出:

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

在我的CustomFragment中,弹出窗口使用popup.show()时会引发错误。

这个错误明显让我疯狂,非常感谢任何帮助解决这个问题!


http://stackoverflow.com/questions/36712824/i-want-a-popup-menu-when-i-click-on-my-listview-item?noredirect=1#comment61012148_36712824 - shiv
8个回答

39

尽管我无法解释为什么这个解决方案有效,但我终于找到了解决我的问题的方法。

使用以下导入语句时,我总是会遇到错误:

import android.support.v7.widget.PopupMenu;

使用以下导入语句可以正常工作:

import android.widget.PopupMenu;

我测试了Ric提供的代码(非常感谢你的帮助!)和我的代码,两者现在都能正常工作。也许有人可以解释一下为什么在这种情况下导入很重要。


6

首先在您的custom-item-listview.xml中创建一个button,然后添加以下代码:

Button

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

类:

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

编辑: 这对我很有效:

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;

}

不幸的是,这给了我相同的错误,再次出现在popup.show();。 - Al0x
我已经尝试过使用context而不是getActivity()。我是否还有其他主要的编辑没有看到? - Al0x
测试了一下,又出现了同样的错误。请注意,适配器是在片段中使用,而不是活动。我知道可以使用片段中的getActivity()方法获取活动,但也许这就是主要问题所在? - Al0x
CustomFragment 应该扩展 Fragment,在其中创建 CustomAdapter。 - Rick
这个类继承了ListFragment,有什么显著的区别吗? - Al0x
显示剩余3条评论

3

使用作为(活动上下文),而不是应用程序上下文或上下文

     PopupMenu popup = new PopupMenu(this, v);

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

注意:
不要忘记导入这个……
import android.support.v7.widget.PopupMenu;
import android.view.MenuItem;

2
Rick的代码行只要导入以下内容就能完美运行:
import android.widget.PopupMenu;

非下面的那一个:
import android.support.v7.widget.PopupMenu;

1

我刚刚在修改主题父级样式时遇到了同样的问题:

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

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

也许你的应用程序使用了Theme.Base样式,而该样式没有定义PopupMenu所需的第6个参数。来自SO问题如何在Theme.Material中使用ActionBarActivity的答案表明,Theme.AppCompat扩展了Theme.Base.AppCompat。

我正在使用Theme.Holo.Light.DarkActionBar,我不认为这是我的问题所在。此外,我找到了另一种解决方案,请查看我发布的答案。 - Al0x

0

我通过将静态活动作为参数传递来修复了一个类似的错误。例如:

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

另外,你的问题可能是这个:问题152141

希望这可以帮到你,关于android.support.v7.widget.PopupMenu的导入,请注意。

祝好。


0

首先需要导入
import android.widget.PopupMenu;

并且你的代码应该长这样

holder.dayDate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                PopupMenu popupMenu = new PopupMenu(context, holder.dayDate);
                popupMenu.getMenu().add("Futa");
                popupMenu.getMenu().add("Acha");
                popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                    @Override
                    public boolean onMenuItemClick(MenuItem item) {
                        switch (item.getTitle().toString()) {
                            case "View" :
                                Toast.makeText(context, "Bidhaa imefutwa.", Toast.LENGTH_SHORT).show();
                                break;
                            case "Edit":
//                                popupMenu.dismiss();
                                break;
                        }
                        return false;
                    }
                });
                popupMenu.show();
            }
        });

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接