superior studio emergente create configuracion bar agregar activity android android-actionbar submenu android-toolbar divider

emergente - android studio menu superior



¿Cómo agregar divisores entre elementos de menú específicos? (6)

Fondo

Tengo un elemento de menú en la barra de acción (barra de herramientas en realidad) que cuando se hace clic, muestra una lista de elementos para elegir, similar a los botones de opción:

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

Necesito colocar un elemento debajo de esta lista de elementos, que tendrá un separador entre él y la lista. Similar a lo que muestran las pautas de diseño de material (tomadas de here ):

EDITAR: aquí hay un bosquejo de lo que quiero hacer:

El problema

No puedo encontrar la manera de hacerlo.

Lo que he intentado

Las únicas soluciones posibles que he encontrado son:

  1. cambie el tema de la actividad ( here ), pero esto también afectará a otros elementos del menú de la actividad

  2. métodos para colocar un separador entre los elementos del menú cuando aparecen en la barra de acción, pero aquí no aparecen en la barra de herramientas. Aparecen en un menú emergente de un elemento seleccionado.

  3. Intenté colocar elementos falsos entre la lista y el elemento adicional, y también intenté colocar un grupo, un grupo vacío e incluso probé varios atributos.

Lamentablemente nada funcionó.

La pregunta

¿Cómo puedo agregar un divisor entre elementos específicos del menú emergente de un elemento de acción?

¿Quizás necesito crear un menú emergente personalizado al hacer clic en el elemento de acción (como here )? Si es así, ¿cómo coloco un separador entre elementos específicos allí? Tal vez use un Spinner como un elemento de acción?


Debes usar diseño de acción

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

y luego el diseño de acción puede tener la vista de texto con divisor.

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

A continuación, puede agregar la escucha de clic en el código


Esto se puede hacer usando la ventana emergente y la vista de lista. En su vista de lista, puede tener diferentes tipos de vista, como elemento de menú y divisor.

Enumero el código para la parte de la ventana emergente:

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

Luego puedes usar el siguiente método para mostrar la ventana emergente:

PopupWindowCompat.showAsDropDown(mPopupWindow, parent, x, y, gravity);

En el adaptador para la vista de lista, puede anular getViewTypeCount () y getItemViewType () para admitir tanto el diseño de elementos de menú como el diseño de divisor, también puede agregar cualquier tipo de vista que necesite.

Aquí hay una instantánea en mi aplicación:


Lo hice de esta manera:

Captura de pantalla de referencia:

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>

Código de 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; } }); }

Espero que esto te ayudará.


OK, he encontrado una buena solución, pero no estoy seguro de que el estilo deba ser así. Eso es lo que me falta:

  1. El fondo de los elementos está sobre el fondo de la ventana emergente de la ruleta, y no estoy seguro de si esa es la forma correcta de ponerlo.
  2. Utilicé el fondo blanco de la biblioteca de soporte para la ventana emergente de la ruleta. Creo que debería haber una mejor manera de hacerlo blanco.
  3. Necesito saber cuál es el estilo correcto del divisor. Por ahora he usado uno simple.
  4. Falta el estilo del elemento de la barra de acción. Acabo de usar un sencillo ImageView, y creo que debería ser diferente.
  5. Por alguna razón, en algunas versiones de Android (tal vez Lollipop y abajo) el fondo de los elementos se ve negro en lugar de blanco.
  6. El hilandero a veces puede tener problemas con setOnItemSelectedListener, sin saber cuándo.

Actividad principal

@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''s shown for the spinner when it''s 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; }

res / menu / 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>

res / layout / 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>

res / layout / 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 / values ​​/ 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>

res / drawable / 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>


Solución super simple que funcionó para mí:

Definir un dibujo para el fondo:

<?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>

luego en Estilos usa el fondo:

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


ahora :

group1[ item0 item1 item2 ] group1[item3];

cambiar a :

group1[ item0 item1] group1[item2 item3]

grupo tiene un divider ; le gusta que el grupo puede agregar un divder entre item ;

si el divider no está disponible, intente con el background ; Yo nunca menu usuario; es mi conjetura