Пользовательский макет Android MenuItem

У меня есть PopupMenu, которое появляется, когда я нажимаю кнопку действия на панели действий. Я хотел бы, чтобы MenuItem в моем PopupMenu имел собственный макет, подобный этому:

layout/menu_item_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/menuItemLayout"

    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/imageViewMenuItem"
        android:layout_width="20dip"
        android:layout_height="20dip"
        android:src="@drawable/abc_list_focused_holo" />

    <TextView
        android:id="@+id/textViewMenuItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextViewMenuItem" />

</LinearLayout>

Это xml PopUpMenu:

меню/pop_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:tools="http://schemas.android.com/tools"
       tools:context="apparound.actiobarpopupstylefacebook.Main" >

    <item
        android:id="@+id/popupItem"
        android:showAsAction="ifRoom"/>
</menu>

В моем коде активности следующий:

public void showPopup(int idR){
View menuItemView = findViewById(idR);
PopupMenu popup = new PopupMenu(this, menuItemView);
MenuInflater inflate = popup.getMenuInflater();
inflate.inflate(R.menu.pop_menu, popup.getMenu());
MenuItem menuItem= popup.getMenu().findItem(R.id.popupItem);
menuItem.setActionView(R.layout.menu_item_layout);
popup.show();
}

Но когда появляется всплывающее меню, элемент пуст. Я ошибался, используя метод setActionview()? Спасибо.


person bruno valenti    schedule 08.05.2014    source источник


Ответы (3)


Для пользовательских макетов вы не можете использовать меню, альтернативным вариантом является PopupWindow

PopupWindow popupwindow_obj = popupDisplay();
popupwindow_obj.showAsDropDown(clickbtn, -40, 18); // where u want show on view click event popupwindow.showAsDropDown(view, x, y);

public PopupWindow popupDisplay() 
{ 

    final PopupWindow popupWindow = new PopupWindow(this);

    // inflate your layout or dynamically add view
    LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

    View view = inflater.inflate(R.layout.mylayout, null);

    Button item = (Button) view.findViewById(R.id.button1);

    popupWindow.setFocusable(true);
    popupWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
    popupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
    popupWindow.setContentView(view);

    return popupWindow;
}

Создайте этот XML-файл в папке res/layout с именем my layout.xml.

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Window test" />
</LinearLayout>
person SuN    schedule 08.05.2014
comment
между 20+ вопросов и ответов, ваш ответ является лучшим. вы должны дать +500 или +1000 голосов. - person Adnan Abdollah Zaki; 19.04.2016
comment
Во всплывающем окне есть темная рамка - person Jemshit Iskenderov; 15.02.2017
comment
Исправлено с помощью popupWindow.setBackgroundDrawable(null); - person Jemshit Iskenderov; 15.02.2017
comment
Я вообще этого не понимаю. Тогда почему PopupMenu вообще существует? Если вы не можете использовать его для пользовательских макетов и можете использовать его только в основном макете, то почему бы просто не использовать ActionBar в основном макете? Я не вижу смысла во всплывающем меню. - person Donato; 27.05.2017
comment
в чем смысл кнопки item = (Button) view.findViewById(R.id.button1); Я не вижу, чтобы это где-то использовалось. - person Donato; 27.05.2017
comment
Как насчет нажатия на элементы? мы должны просто установить для них прослушиватели кликов, как простые кнопки, верно? Есть более простые способы? - person inverted_index; 08.10.2017
comment
Добрый день, сэр, просто спрашиваю, как я могу закрыть всплывающее окно, которое я делаю. Потому что на других устройствах, когда я нажимаю за пределы окна, само окно не закрывалось. Но хороший ответ, я голосую за :) - person Android Mediocre; 25.01.2018

Окончательный вариант PopupWindow popupWindow = new PopupWindow(); // увеличить макет или динамически добавить представление LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(R.layout.alert_reply_chat,null); popupWindow.setFocusable(true); popupWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT); всплывающее окно.setHeight(180); popupWindow.setBackgroundDrawable(null); popupWindow.setClippingEnabled (ложь); popupWindow.setTouchable (истина); popupWindow.setContentView(представление); вернуть всплывающее окно; //выше рабочий код, я проверил

person jaigish    schedule 01.03.2019

По умолчанию макет PopupMenu (и его элементов) нельзя настроить. В приведенном ниже решении я создал PopupMenu с горизонтальной компоновкой. В этом случае я использовал TextView как интерактивные элементы, но вы можете легко заменить их кнопками. Вы можете настроить пункты меню как хотите.

1 - Пользовательский класс PopupMenu:

public class PopupMenuCustomLayout {
    private PopupMenuCustomOnClickListener onClickListener;
    private Context context;
    private PopupWindow popupWindow;
    private int rLayoutId;
    private View popupView;

    public PopupMenuCustomLayout(Context context, int rLayoutId, PopupMenuCustomOnClickListener onClickListener) {
        this.context = context;
        this.onClickListener = onClickListener;
        this.rLayoutId = rLayoutId;
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
        popupView = inflater.inflate(rLayoutId, null);
        int width = LinearLayout.LayoutParams.WRAP_CONTENT;
        int height = LinearLayout.LayoutParams.WRAP_CONTENT;
        boolean focusable = true;
        popupWindow = new PopupWindow(popupView, width, height, focusable);
        popupWindow.setElevation(10);

        LinearLayout linearLayout = (LinearLayout) popupView;
        for (int i = 0; i < linearLayout.getChildCount(); i++) {
            View v = linearLayout.getChildAt(i);
            v.setOnClickListener( v1 -> { onClickListener.onClick( v1.getId()); popupWindow.dismiss(); });
        }
    }
    public void setAnimationStyle( int animationStyle) {
        popupWindow.setAnimationStyle(animationStyle);
    }
    public void show() {
        popupWindow.showAtLocation( popupView, Gravity.CENTER, 0, 0);
    }

    public void show( View anchorView, int gravity, int offsetX, int offsetY) {
        popupWindow.showAsDropDown( anchorView, 0, -2 * (anchorView.getHeight()));
    }

    public interface PopupMenuCustomOnClickListener {
        public void onClick(int menuItemId);
    }
}

2 - Ваш собственный макет, например. linearlayout с горизонтальной компоновкой. В этом случае я использую простой LinearLayout с элементами TextView. Вы можете использовать кнопки и т. д.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:orientation="horizontal">
    <TextView
        android:id="@+id/popup_menu_custom_item_a"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="A"
        android:textAppearance="?android:textAppearanceMedium" />
    <TextView
        android:id="@+id/popup_menu_custom_item_b"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:text="B"
        android:textAppearance="?android:textAppearanceMedium" />
    // ...
</LinearLayout>

3 - Использование Custom PopupMenu, как обычное PopupMenu.

PopupMenuCustomLayout popupMenu = new PopupMenuCustomLayout(
        MainActivity.mainActivity, R.layout.popup_menu_custom_layout,
        new PopupMenuCustomLayout.PopupMenuCustomOnClickListener() {
            @Override
            public void onClick(int itemId) {
                // log statement: "Clicked on: " + itemId
                switch (itemId) {
                    case R.id.popup_menu_custom_item_a:
                        // log statement: "Item A was clicked!"
                        break;
                }
            }
        });
// Method 1: popupMenu.show();
// Method 2: via an anchor view: 
popupMenu.show( anchorView, Gravity.CENTER, 0, 0);
person tm1701    schedule 15.12.2019