The solution I’m going to detail makes use of the ActionLayout
of MenuItem
, which is available both from the Android 11+, as in previous versions, but with the use of v7 support library AppCompat
. Soon the solution can be applied to all devices.
Configuration of Activity
on Androidmanifest
<activity
android:name=".app.activity.MenuActivity"
android:label="Exemplo Menu"
android:uiOptions="splitActionBarWhenNarrow"
/>
As you mentioned, we need to define the android:uiOptions="splitActionBarWhenNarrow"
so that the SplitActionBar
appear.
Menu (menu_activity.xml
)
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/ed_save1"
android:title="@string/action_save"
android:icon="@drawable/ic_save_dark"
android:actionLayout="@layout/menu_item_layout"
app:actionLayout="@layout/menu_item_layout"
android:showAsAction="withText|ifRoom"
app:showAsAction="withText|ifRoom" />
<item
android:id="@+id/ed_save2"
android:title="@string/action_save"
android:icon="@drawable/ic_save_dark"
android:actionLayout="@layout/menu_item_layout"
app:actionLayout="@layout/menu_item_layout"
android:showAsAction="withText|ifRoom"
app:showAsAction="withText|ifRoom" />
<item
android:id="@+id/ed_save3"
android:title="@string/action_save"
android:icon="@drawable/ic_save_dark"
android:actionLayout="@layout/menu_item_layout"
app:actionLayout="@layout/menu_item_layout"
android:showAsAction="withText|ifRoom"
app:showAsAction="withText|ifRoom" />
<item
android:id="@+id/ed_save4"
android:title="@string/action_save"
android:icon="@drawable/ic_save_dark"
android:actionLayout="@layout/menu_item_layout"
app:actionLayout="@layout/menu_item_layout"
android:showAsAction="withText|ifRoom"
app:showAsAction="withText|ifRoom" />
</menu>
In it we see some repeated attributes, with the schema app
and the schema android
. I do this because the attributes with schema app
are for the AppCompat
and the ones with schema android
to the ActionBar
native. If you do not use AppCompat
can remove smoothly.
Definition of menu_item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:focusable="true"
android:paddingTop="4dip"
android:paddingBottom="4dip"
android:paddingLeft="8dip"
android:paddingRight="8dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="6pt"
android:textColor="@color/white"
style="?attr/actionButtonStyle" />
Common layout, only one TextView
, where we will configure the icon and the text. If you want you can customize as needed.
Menuactivity
/**
* Created by wakim on 28/09/14.
*/
public class MenuActivity extends ActionBarActivity implements View.OnClickListener {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_activity, menu);
for(int i = 0, c = menu.size(); i < c; ++i) {
MenuItem item = menu.getItem(i);
// A linha abaixo é para quem usa o AppCompat.
//TextView actionLayout = (TextView) MenuItemCompat.getActionView(item);
// Recuperando a View que representa o Menu
TextView actionLayout = (TextView) item.getActionView();
// Atribuo o text baseado no title do Menu
actionLayout.setText(item.getTitle());
// Atribuo o drawable de acordo com o ícone.
// Estou usando o drawableTop, mas poderá usar qualquer um dos:
// drawableLeft, drawableTop, drawableRight, drawableBottom
actionLayout.setCompoundDrawablesWithIntrinsicBounds(null, item.getIcon(), null, null);
// Somos obrigados a configurar manualmente o OnClickListener
// Ja que estamos configurando uma View Customizada para o Menu
actionLayout.setOnClickListener(this);
}
return super.onCreateOptionsMenu(menu);
}
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.ed_save1:
// Tratamento para click no item ed_save1
break;
case R.id.ed_save2:
// Tratamento para click no item ed_save2
break;
case R.id.ed_save3:
// Tratamento para click no item ed_save3
break;
case R.id.ed_save4:
// Tratamento para click no item ed_save4
break;
}
}
}
My Activity
inherits from ActionBarActivity
because I’m using the AppCompat
, that forces me to inherit it it to gain access to ActionBar
. If you are using only the ActionBar
native, you can inherit from Activity
no problem.
Upshot
Edit
In the case of the menu built on ActionMode
, it is necessary to adapt the solution to store the state of the ActionMode
and use it to retrieve the Menu
created and respectively the MenuItem
clicked. Thus calling the method onActionItemClicked
, maintaining the same logic.
Menuactivity
/**
* Created by wakim on 28/09/14.
*/
public class MenuActivity extends ActionBarActivity implements View.OnClickListener, ActionMode.Callback {
ActionMode mActionMode;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startActionMode(this);
// Se estiver usando a biblioteca AppCompat, para iniciar o ActionMode
// é preciso chamar o método abaixo, em vez do método acima.
//startSupportActionMode(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// O menu será criado no ActionMode...
return super.onCreateOptionsMenu(menu);
}
/***
Método que configura o ActionLayout do menu,
com os atributos do próprio MenuItem
*/
void configureActionLayout(Menu menu) {
for(int i = 0, c = menu.size(); i < c; ++i) {
MenuItem item = menu.getItem(i);
TextView actionLayout = (TextView) MenuItemCompat.getActionView(item);
//TextView actionLayout = (TextView) item.getActionView();
actionLayout.setText(item.getTitle());
actionLayout.setCompoundDrawablesWithIntrinsicBounds(null, item.getIcon(), null, null);
actionLayout.setOnClickListener(this);
}
}
@Override
public void onClick(View v) {
// Tenta fazer o tratamento caso seja um MenuItem de um menu criado no ActionMode
if(handleActionModeIfPossible(v.getId())) {
return;
}
// Tratamento padrão, caso não seja um MenuItem do ActionMode
switch (v.getId()) {
case R.id.ed_save1:
// Tratamento para click no menu
Log.i("tag", "ed_save1");
break;
case R.id.ed_save2:
// Tratamento para click no menu
Log.i("tag", "ed_save2");
break;
case R.id.ed_save3:
// Tratamento para click no menu
Log.i("tag", "ed_save3");
break;
case R.id.ed_save4:
// Tratamento para click no menu
Log.i("tag", "ed_save4");
break;
}
}
boolean handleActionModeIfPossible(int menuId) {
// Se nao temos um ActionMode no momento podemos parar
if(mActionMode == null) {
return false;
}
// Recupero o possível MenuItem do Menu atual do ActionMode
MenuItem menuItem = mActionMode.getMenu().findItem(menuId);
// Se nao existe um MenuItem com id "menuId", não podemos continuar.
if(menuItem == null) {
return false;
}
onActionItemClicked(mActionMode, menuItem);
return true;
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.am_menu_activity, menu);
configureActionLayout(menu);
mActionMode = mode;
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
mActionMode = mode;
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
mActionMode = mode;
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
}
You’re using the library
AppCompat
to theActionBar
?– Wakim
I don’t even know what this library does
– Pedro Rangel
android:uiOptions="splitActionBarWhenNarrow" serves to make the actionbar appear at the bottom so that even if you have space to appear icon + text does not appear, only the icon...
– Pedro Rangel
to this aew library and support ne... now I remembered I think
– Pedro Rangel
Yeah, but how are you using the
ActionBar
native, it is not necessary to use it.– Wakim
hum. strange q all the examples I saw on the net to make appear use android:uiOptions="splitActionBarWhenNarrow" and in all cases only appear the icons... I wanted to know a way to force appear
– Pedro Rangel
I’ve been there. What I did to solve this was to create an Actionbar custon and use setCustomView to override the default Actionbar.
– Savrige
@Borachio but will get 2 actionbar? an overlay is the default that does not appear or will replace the default?
– Pedro Rangel
@Borachio anyway if you wish to expose how to do this custom actiobar thank you very much.
– Pedro Rangel
I think something parallel to what @Borachio quoted, would be to use a
actionLayout
to the menu icon. Instead of setting only oneDrawable
, with theactionLayout
you can set an xml layout for each item (can be the same by configuring in the menu creation), including anyView
.– Wakim
I’ll see how you do it. vlw for the tip
– Pedro Rangel