Java 自定义 ListView 中的弹出菜单

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27782846/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 05:02:01  来源:igfitidea点击:

Popup Menu in custom ListView

javaandroidlistviewandroid-adapterruntimeexception

提问by Al0x

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.

我有一个自定义 ListView 适配器。我想为每个 Listitem 添加一个弹出菜单,与当前 Google Play 应用程序中的 ListView 非常相似。

Screenshot of Google Play items

Google Play 商品的屏幕截图

This is what I tried: Most of my code comes from this Android sample samples\android-19\ui\ActionBarCompat-ListPopupMenu

这是我试过的:我的大部分代码来自这个 Android 示例samples\android-19\ui\ActionBarCompat-ListPopupMenu

CustomFragmentPageAdapter.java:

CustomFragmentPageAdapter.java

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

CustomFragment.java

自定义片段.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:

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:

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

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

该错误是在我的 CustomFragment 中的 popup.show() 处引发的。

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

这个错误显然让我发疯了,非常感谢任何解决这个问题的帮助!

采纳答案by Al0x

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.

我测试了 Ric 提供的代码(感谢您的大力帮助!)和我自己的。两人现在都在工作。也许有人解释了为什么在这种情况下导入很重要。

回答by Rick

First create a buttonin your custom-item-listview.xmland then add the code below:

首先button在您的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"
... />

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

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:

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;

}

回答by Philippe

I've just had the same issue when I modified the theme parent style: from

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

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

to

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

Maybe your app uses the Theme.Base style, which does not define the required 6th parameter used by PopupMenu. From SO question How to use ActionBarActivity with Theme.Material, Theme.AppCompat extends Theme.Base.AppCompat

也许您的应用程序使用 Theme.Base 样式,它没有定义 PopupMenu 使用的必需的第 6 个参数。从 SO 问题How to use ActionBarActivity with Theme.Material, Theme.AppCompat extends Theme.Base.AppCompat

回答by mlopezv86

I fixed a similar error just by passing as parameter a static activity. For example:

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

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

Also, you problem might be this one: Issue 152141

此外,您的问题可能是这个:问题 152141

Hopefully it will help you, respecting the android.support.v7.widget.PopupMenuimport.

希望它会帮助你,尊重android.support.v7.widget.PopupMenu进口。

Regards.

问候。

回答by Uzair

use thisas(activity context)notapplication context or context

使用这个作为(活动上下文)应用程序上下文或上下文

     PopupMenu popup = new PopupMenu(this, v);

回答by Karthick

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

Note:
Don't forgot to import this....

注意:
不要忘记导入这个....

import android.support.v7.widget.PopupMenu;
import android.view.MenuItem;

回答by Josi

Rick's code of lines works perfect as long as you import the following:

只要您导入以下内容,Rick 的代码行就可以完美运行:

import android.widget.PopupMenu;

Not the one below:

不是下面那个:

import android.support.v7.widget.PopupMenu;