Как добавить разделители между определенными пунктами меню?
Фон
У меня есть пункт меню на панели действий (фактически на панели инструментов), который при нажатии показывает список элементов на выбор, похожих на радиокнопки:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:icon="@drawable/..."
android:title="@string/..."
app:showAsAction="always">
<menu>
<group
android:id="@+id/..."
android:checkableBehavior="single">
<item .../>
<item .../>
<item .../>
</group>
</menu>
</item>
</menu>
Мне нужно поставить элемент под этим списком элементов, который будет иметь разделитель между ним и списком. Как показано в руководстве по дизайну материала (взято из здесь):
![введите описание изображения здесь]()
ИЗМЕНИТЬ: вот эскиз того, что я хочу сделать:
![введите описание изображения здесь]()
Проблема
Я не могу найти способ сделать это.
Что я пробовал
Единственными возможными решениями, которые я нашел, являются:
-
измените тему активности ( здесь), но это также повлияет на другое меню элементы деятельности
-
чтобы поместить разделитель между пунктами меню, когда они появляются на панели действий, но здесь они не отображаются на самой панели инструментов. Они отображаются во всплывающем меню выбранного элемента.
-
Я пытался помещать поддельные элементы между списком и дополнительным элементом, а также пытался поместить группу, пустую группу и даже попробовать различные атрибуты.
К сожалению, ничего не получилось.
Вопрос
Как добавить разделитель между определенными элементами всплывающего меню действия?
Возможно, мне нужно создать настраиваемое всплывающее меню при нажатии на элемент действия (например здесь)? Если да, то каким образом я могу разместить разделитель между определенными элементами?
Может быть, использовать Spinner в качестве элемента действия?
Ответы
Ответ 1
Хорошо, я нашел хорошее обходное решение, но я не уверен, что стиль должен быть таким. Это то, что мне не хватает:
- фон элементов находится поверх фона всплывающего окна, и я не уверен, правильно ли это это сделать.
- Я использовал белый фон библиотеки поддержки для всплывающего окна счетчика. Я думаю, что должен быть лучший способ сделать его белым.
- Мне нужно знать, каков правильный стиль разделителя. пока я использовал простой
- Стиль элемента панели действий отсутствует. Я просто использовал простой ImageView, и я думаю, что он должен быть другим.
- По какой-то причине на некоторых версиях Android (возможно, Lollipop и ниже) фон элементов выглядит черным, а не белым.
- У счетчика иногда могут возникать проблемы с setOnItemSelectedListener, не знаю, когда.
MainActivity
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
final MenuItem item = menu.findItem(R.id.action_settings);
final Spinner spinner = ((Spinner) MenuItemCompat.getActionView(item));
SimpleImageArrayAdapter adapter = new SimpleImageArrayAdapter(this);
spinner.setAdapter(adapter);
return true;
}
public class SimpleImageArrayAdapter extends ArrayAdapter<String> {
private final String[] items = {"item 1", "item 2", "item 3", "extra item"};
public SimpleImageArrayAdapter(Context context) {
super(context, 0);
}
@Override
public int getCount() {
return items.length;
}
@Override
public String getItem(final int position) {
return items[position];
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
View rootView = convertView == null ? LayoutInflater.from(getContext()).inflate(R.layout.spinner_item, parent, false) : convertView;
TextView tv = (TextView) rootView.findViewById(android.R.id.text1);
tv.setTextColor(0xff000000);
tv.setText(items[position]);
boolean isLastItem = position == getCount() - 1;
rootView.findViewById(R.id.action_divider).setVisibility(isLastItem ? View.VISIBLE : View.GONE);
rootView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
return rootView;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//this is the view that shown for the spinner when it closed
ImageView iv = new ImageView(getContext());
iv.setImageResource(android.R.drawable.ic_menu_add);
int viewSize = getDimensionFromAttribute(MainActivity.this, android.support.v7.appcompat.R.attr.actionBarSize);
iv.setLayoutParams(new ViewGroup.LayoutParams(viewSize, viewSize));
iv.setScaleType(ScaleType.CENTER_INSIDE);
iv.setBackgroundResource(getResIdFromAttribute(MainActivity.this, R.attr.selectableItemBackground));
return iv;
}
}
public static int getResIdFromAttribute(final Activity activity, final int attr) {
if (attr == 0)
return 0;
final TypedValue typedValue = new TypedValue();
activity.getTheme().resolveAttribute(attr, typedValue, true);
return typedValue.resourceId;
}
public static int getDimensionFromAttribute(final Context context, final int attr) {
final TypedValue typedValue = new TypedValue();
if (context.getTheme().resolveAttribute(attr, typedValue, true))
return TypedValue.complexToDimensionPixelSize(typedValue.data, context.getResources().getDisplayMetrics());
return 0;
}
Рез/меню/menu_main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.user.myapplication.MainActivity">
<item
android:id="@+id/action_settings"
android:actionLayout="@layout/spinner"
android:title=""
app:actionLayout="@layout/spinner"
app:showAsAction="always"
/>
</menu>
Рез/макет/spinner_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/action_divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/divider"/>
<TextView
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:minHeight="?attr/listPreferredItemHeightSmall"
android:paddingEnd="?attr/listPreferredItemPaddingRight"
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
android:paddingRight="?attr/listPreferredItemPaddingRight"
android:paddingStart="?attr/listPreferredItemPaddingLeft"
android:textAppearance="?attr/textAppearanceListItemSmall"/>
</LinearLayout>
Рез/макет/spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<Spinner
android:id="@+id/spinner"
style="@style/SpinnerWithoutArrow"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
RES/значение/styles.xml
<style name="SpinnerWithoutArrow" parent="@style/Widget.AppCompat.Spinner">
<item name="android:background">@null</item>
<item name="android:popupBackground">@drawable/abc_popup_background_mtrl_mult</item>
</style>
Рез/вытяжка/divider.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:height="1dp"/>
<solid android:color="#FFff0000" />
</shape>
Ответ 2
Вы должны использовать макет действия
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".LandingActivity">
<item
android:id="@+id/action_cart"
android:title="cart"
android:actionLayout="@layout/cart_update_count"
android:icon="@drawable/shape_notification"
app:showAsAction="always"/>
</menu>
а затем макет действия может иметь текстовое представление с разделителем.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/divider"/>
<TextView
android:id="@android:id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:textAppearance="?attr/textAppearanceListItemSmall"/>
</LinearLayout>
то вы можете добавить прослушиватель кликов в код
Ответ 3
Это можно сделать, используя всплывающее окно и список. В вашем представлении списка вы можете иметь разные типы просмотров, такие как пункт меню и разделитель.
Я перечисляю код для части окна всплывающего окна:
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.option_menu, null);
ListView listView = (ListView) view.findViewById(R.id.listView);
listView.setDivider(null);
mAdapter = new OptionListAdapter(context, options);
listView.setAdapter(mAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//TODO: The code when item is clicked.
}
});
mPopupWindow = new PopupWindow(context, null, R.attr.popupMenuStyle);
mPopupWindow.setFocusable(true); // otherwise on android 4.1.x the onItemClickListener won't work.
mPopupWindow.setContentView(view);
mPopupWindow.setOutsideTouchable(true);
int height = 0;
int width = 0;
float density = context.getResources().getDisplayMetrics().density;
int minWidth = Math.round(196 * density); // min width 196dip, from abc_popup_menu_item_layout.xml
int cellHeight = context.getResources().getDimensionPixelOffset(R.dimen.option_height);
int dividerHeight = context.getResources().getDimensionPixelOffset(R.dimen.divider_height);
final int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
for (int i = 0; i < mAdapter.getCount(); i++) {
Object item = mAdapter.getItem(i);
if (item != null) {
View childView = mAdapter.getView(i, null, listView);
childView.measure(widthMeasureSpec, heightMeasureSpec);
height += cellHeight;
width = Math.max(width, childView.getMeasuredWidth());
} else {
height += dividerHeight; // divider
}
}
width = Math.max(minWidth, width);
Drawable background = mPopupWindow.getBackground(); // 9-pitch images
if (background != null) {
Rect padding = new Rect();
background.getPadding(padding);
height += padding.top + padding.bottom;
width += padding.left + padding.right;
}
mPopupWindow.setWidth(width);
mPopupWindow.setHeight(height);
mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
Затем вы можете использовать следующий метод для отображения всплывающего окна:
PopupWindowCompat.showAsDropDown(mPopupWindow, parent, x, y, gravity);
В адаптере для просмотра списка вы можете переопределить getViewTypeCount() и getItemViewType() для поддержки как макета меню, так и разделителя, также вы можете добавить любой тип вида, который вам нужен.
Вот снимок в моем приложении:
![введите описание изображения здесь]()
Ответ 4
Супер простое решение, разработанное для меня:
Определить выделение для фона:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/white"/>
<stroke
android:width="3dp"
android:color="@color/colorPrimary"/>
</shape>
, тогда в стилях используйте фон:
<style name="bluetooth_popup" parent="@android:style/Widget.DeviceDefault.Light.PopupMenu">
<item name="android:textColor">@color/colorPrimary</item>
<item name="android:textStyle">bold</item>
<item name="android:textAllCaps">true</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:itemBackground">@drawable/bluetooth_popup_buttons</item>
Ответ 5
Я сделал это следующим образом:
Сводный снимок экрана:
![введите описание изображения здесь]()
style.xml:
<style name="popup" parent="Widget.AppCompat.ListView.DropDown">
<item name="android:divider">@color/colorPrimary</item>
<item name="android:dividerHeight">1dp</item>
<item name="android:textColor">@color/colorPrimary</item>
<item name="android:itemBackground">@android:color/white</item>
</style>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!--- Customize popmenu -->
<item name="android:dropDownListViewStyle">@style/popup</item>
</style>
Java-код:
private void showPopup(View v) {
Context wrapper = new ContextThemeWrapper(this, R.style.popup);
PopupMenu mypopupmenu = new PopupMenu(wrapper, v);
MenuInflater inflater = mypopupmenu.getMenuInflater();
inflater.inflate(R.menu.menu_patient_language, mypopupmenu.getMenu());
mypopupmenu.show();
mypopupmenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
txtPreferredLanguage.setText(item.getTitle().toString());
switch (item.getItemId()) {
case R.id.menuEnglish:
// Your code goes here
break;
case R.id.menuFrench:
// Your code goes here
break;
}
return false;
}
});
}
Надеюсь, это поможет вам.
Ответ 6
теперь:
group1[ item0 item1 item2 ] group1[item3];
измените на:
group1[ item0 item1] group1[item2 item3]
группа имеет divider
;
ему нравится, что группа может добавить divder
между item
;
Если divider
недоступно, попробуйте background
;
i никогда пользователь menu
;
его догадка,