How to display menu item with icon and text in AppCompatActivity
Asked Answered
T

9

47

I tried different combinations in xml file:

<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=".MainActivity">
    <item
        android:id="@+id/action_create_alarm"
        android:icon="@drawable/ic_action_accept"
        android:orderInCategory="100"
        android:title="@string/menu_create_alarm"
        app:showAsAction="ifRoom|withText" />
</menu>

or

<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=".MainActivity">
    <item
        android:id="@+id/action_create_alarm"
        android:icon="@drawable/ic_action_accept"
        android:orderInCategory="100"
        android:title="@string/menu_create_alarm"
        app:showAsAction="always|withText" />
</menu>

or

<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=".MainActivity">
    <item
        android:id="@+id/action_create_alarm"
        android:icon="@drawable/ic_action_accept"
        android:orderInCategory="100"
        android:title="@string/menu_create_alarm"
        app:showAsAction="withText" />
</menu>

or

<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=".MainActivity">
    <item
        android:id="@+id/action_create_alarm"
        android:icon="@drawable/ic_action_accept"
        android:orderInCategory="100"
        android:title="@string/menu_create_alarm"
        android:showAsAction="always|withText" />
</menu>

I tried to set it programmaticly

@Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
        MenuItem item = menu.add(R.string.menu_create_alarm);
        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT|MenuItem.SHOW_AS_ACTION_IF_ROOM);
        item.setIcon(R.drawable.ic_action_accept);
        item.setOnMenuItemClickListener(
            new OnMenuItemClickListener(){

                @Override
                public boolean onMenuItemClick(MenuItem item){
                    saveAlarm();
                    return true;
                }
            }
        );


//      inflater.inflate(R.menu.menu_create_alarm, menu);
        super.onCreateOptionsMenu(menu, inflater);

    }

or

<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=".MainActivity">
    <item
        android:id="@+id/action_create_alarm"
        android:icon="@drawable/ic_action_accept"
        android:orderInCategory="100"
        android:title="@string/menu_create_alarm"
        android:showAsAction="always|withText"
        app:showAsAction="always|withText" />
</menu>

However, Only Icon appears. And there is planty of room, cause I did not set toolbar title. Removing menues and replasing them with button inside toolbar is not sutable.
How to display text?

Totemism answered 6/10, 2015 at 11:48 Comment(7)
#14932716Jessabell
@Jessabell yo make link to answers, with solution already listed and not workingTotemism
Icon + text or only text??Heavenward
@Heavenward icon+ text.Totemism
do you have one menu item? or severallAlasteir
@Alasteir only one, which is listed in examples aboveTotemism
May be this could help clear the picture https://mcmap.net/q/263337/-android-4-0-text-on-the-action-bar-never-showsLynellelynett
K
12

You can use following code for establishing your purpose. No need to make it programmatic. You can trick in menu.xml file.

menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

<item
    android:id="@+id/overflowMenu"
    android:icon="@drawable/ic_more_vert_white_24dp"
    android:title=""
    app:showAsAction="always">

    <menu>
        <item
            android:id="@+id/menuWithIconText"
            android:icon="@drawable/chosen_icon"
            android:title="@string/menu_item_title"
            />
    </menu>
</item>

In above code, we've used menu inside of item. In inside menu, we've defined our overflow menu which we want with icon. Just remember to use app:showAsAction="always" in outside item tag.

Kakapo answered 1/3, 2020 at 12:15 Comment(2)
I don't have such a drawable in my project and when i add it it says that it's not found.Harrell
@Harrell drawable is folder where you save icons. Basically in drawable folder you keep all your assets. Please check your assets folder and select it in android:icon attribute.Kakapo
M
32
@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
//        getMenuInflater().inflate(R.menu.menu_patient_home_screen, menu);


        menu.add(0, 1, 1, menuIconWithText(getResources().getDrawable(R.mipmap.user_2), getResources().getString(R.string.action_profile)));
        menu.add(0, 2, 2, menuIconWithText(getResources().getDrawable(R.mipmap.add_user), getResources().getString(R.string.action_add_user)));
        menu.add(0, 3, 3, menuIconWithText(getResources().getDrawable(R.mipmap.switch_profile), getResources().getString(R.string.action_switch_profile)));
        menu.add(0, 4, 4, menuIconWithText(getResources().getDrawable(R.mipmap.logout), getResources().getString(R.string.action_sign_out)));
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        switch (item.getItemId()) {
            case 1:
                Toast.makeText(PatientHomeScreen.this, "Profile is Clicked", Toast.LENGTH_SHORT).show();
                return true;
            case 2:
                Toast.makeText(PatientHomeScreen.this, "Add New User is Clicked", Toast.LENGTH_SHORT).show();
                return true;
            case 3:
                Toast.makeText(PatientHomeScreen.this, "Switch Profile is Clicked", Toast.LENGTH_SHORT).show();
                return true;
            case 4:
                Toast.makeText(PatientHomeScreen.this, "Sign Out is Clicked", Toast.LENGTH_SHORT).show();
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private CharSequence menuIconWithText(Drawable r, String title) {

        r.setBounds(0, 0, r.getIntrinsicWidth(), r.getIntrinsicHeight());
        SpannableString sb = new SpannableString("    " + title);
        ImageSpan imageSpan = new ImageSpan(r, ImageSpan.ALIGN_BOTTOM);
        sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        return sb;
    }

Screen shot of emulator

Hope this will help you

Modulus answered 10/1, 2017 at 13:4 Comment(2)
Above solution works good, If you are working in Fragment you need to change only one thing, change onCreateOptionsMenu(Menu menu) with onCreateOptionsMenu(Menu menu, MenuInflater inflater). and add setHasOptionsMenu(true) in onCreate(Bundle savedInstanceState) or View onCreateView(LayoutInflater inflater....)Villalba
How can I do this with XML only?Legation
F
26

You need to add tools:context="your class" to menu tag

menu.xml

<?xml version="1.0" encoding="utf-8"?>
<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=".activities.BaseActivity">


   <item
       android:id="@+id/action_notification1"
       android:icon="@drawable/three"
       android:title="action_notification"
       app:showAsAction="always">
       <menu>
           <item
               android:id="@+id/profile"
               android:icon="@drawable/profile"
               android:orderInCategory="100"
               android:title="PROFILE" />

           <item
               android:id="@+id/c"
               android:icon="@drawable/correct_tick"
               android:orderInCategory="100"
               android:title="COMPLETED TRIPS" />

           <item
               android:id="@+id/app"
               android:icon="@drawable/report_issue"
               android:orderInCategory="100"
               android:title="REPORT ISSUES" />
           <item
               android:id="@+id/r"
               android:icon="@drawable/correct_tick"
               android:orderInCategory="100"
               android:title="REACHED CENTER" />


           <item
               android:id="@+id/pdf"
               android:icon="@drawable/pdf_image"
               android:orderInCategory="100"
               android:title="BAG INFO" />
           <item
               android:id="@+id/l"
               android:icon="@drawable/logout"
               android:orderInCategory="100"
               android:title="LOGOUT" />
       </menu>
   </item>


</menu>

Override onCreateOptionsMenu() Method

@Override 
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu); 
    menu.getItem(0).getSubMenu().getItem(3).setVisible(false);
    menu.getItem(0).getSubMenu().getItem(4).setVisible(true);
    return super.onCreateOptionsMenu(menu);
} 

You should write tool:context to menu tag then run you will get icons before your text.

Farmer answered 23/3, 2016 at 10:28 Comment(0)
A
26

Adding to the answer from dev_ry, there is a much smoother way without using reflection by just casting and suppressing the restricted API warning:

import android.support.v7.view.menu.MenuBuilder;

@SuppressLint("RestrictedApi")
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    if (menu instanceof MenuBuilder) {
        ((MenuBuilder) menu).setOptionalIconsVisible(true);
    }
    getMenuInflater().inflate(R.menu.menu, menu);
    return super.onCreateOptionsMenu(menu);
}
Anton answered 14/4, 2017 at 12:15 Comment(2)
Simple but powerful solution.Indoor
saved my day bro :-)Backbencher
C
13
protected boolean onPrepareOptionsPanel(View view, Menu menu) {
    if (menu != null) {
        if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
            try {
                Method m = menu.getClass().getDeclaredMethod(
                        "setOptionalIconsVisible", Boolean.TYPE);
                m.setAccessible(true);
                m.invoke(menu, true);
            } catch (Exception e) {
                Log.e(getClass().getSimpleName(),
                        "onMenuOpened...unable to set icons for overflow menu",
                        e);
            }
        }
    }
    return super.onPrepareOptionsPanel(view, menu);
}
Carlina answered 19/2, 2016 at 7:2 Comment(4)
When my class extended Activity, this worked form me: https://mcmap.net/q/261603/-how-to-show-icons-in-overflow-menu-in-actionbar. But when i changed my class to extend AppCompatActivity, previous solution stoped working and this answer saved my day =)Chemism
Thanks a lot for this. Any change we need to make in proguard?Diocesan
@Diocesan I have not tested it for proguard but dont think that progurad need some changes because of this.Carlina
Tried everything else to get both the icon and text to display in the drop-down menu. This worked which also gave an error which was resolved by adding @SuppressLint("RestrictedApi") before the method as per #41151495Brenna
K
12

You can use following code for establishing your purpose. No need to make it programmatic. You can trick in menu.xml file.

menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

<item
    android:id="@+id/overflowMenu"
    android:icon="@drawable/ic_more_vert_white_24dp"
    android:title=""
    app:showAsAction="always">

    <menu>
        <item
            android:id="@+id/menuWithIconText"
            android:icon="@drawable/chosen_icon"
            android:title="@string/menu_item_title"
            />
    </menu>
</item>

In above code, we've used menu inside of item. In inside menu, we've defined our overflow menu which we want with icon. Just remember to use app:showAsAction="always" in outside item tag.

Kakapo answered 1/3, 2020 at 12:15 Comment(2)
I don't have such a drawable in my project and when i add it it says that it's not found.Harrell
@Harrell drawable is folder where you save icons. Basically in drawable folder you keep all your assets. Please check your assets folder and select it in android:icon attribute.Kakapo
C
10

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=".MainActivity">
    <item
        android:id="@+id/action_create_alarm"
        android:icon="@drawable/ic_action_accept"
        android:orderInCategory="100"
        android:title="@string/menu_create_alarm"
        android:showAsAction="always|withText"
        app:showAsAction="always|withText" />
</menu>

java:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    new MenuInflater(this).inflate(R.menu.menu_frg_safetybox, menu);
    super.onCreateOptionsMenu(menu, inflater);
}
Caber answered 6/10, 2015 at 12:24 Comment(5)
there is still no text, only iconTotemism
Android decides for itself at the end of the day if it can fit or not.Caber
how to call, new inflator in fragment? If i do @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){ // inflater.inflate(R.menu.menu_create_level, menu); new MenuInflater(getActivity()).inflate(R.menu.menu_create_level, menu); super.onCreateOptionsMenu(menu, inflater); }, I still have only iconTotemism
As i said. if the OS decides that the text and icon are to large for the device, it will only put the icon. You would have to try a larger device.Caber
but how is this diff from mine lol.. life on stackoverflow :)Alasteir
O
6

'always|withText' will work if there is sufficient room, otherwise it will place only the icon.You an see that by rotating phone to landscape mode..

       <item
        android:id="@+id/action_create_alarm"
        android:icon="@drawable/ic_launcher"
        android:title="Save"
        app:showAsAction="always|withText"
        />
Oxazine answered 6/10, 2015 at 12:42 Comment(1)
that is correct. If I turn the device into landscape mode the text show up. Nevertheless I want to text is being displaying always. Although my Title in toolbar is very short ("Activity") text doesn't appear.Klepht
A
3

try these two together

app:showAsAction="always|withText"
android:showAsAction="always|withText"
Alasteir answered 6/10, 2015 at 12:20 Comment(4)
there is still no text, only iconTotemism
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.Lennie
where is the link Sir @LennieAlasteir
This is the correct answer I don't know why it doesn't have more upvotesAntipodal
R
2

MyActivity.java:

@Override
    public boolean onCreateOptionsMenu(Menu menu) 
    {
        getMenuInflater().inflate(R.menu.my_menu, menu);
        View view = menu.findItem(R.id.whats_this).getActionView();
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // do something
            }
        });
        return super.onCreateOptionsMenu(menu);
    }

my_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<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=".MyActivity">

    <item
        android:id="@+id/item"
        app:actionLayout="@layout/my_layout"
        android:orderInCategory="100"
        android:title="@string/whats_this"
        app:showAsAction="always" />
</menu>

my_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="30dp"
        android:paddingLeft="5dp"
        android:gravity="center_vertical"
        android:textStyle="bold"
        android:textColor="@color/white"
        android:text="@string/whats_this"/>

    <ImageView
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:src="@mipmap/question"/>

</LinearLayout>
Rauscher answered 20/1, 2020 at 13:13 Comment(1)
This is not useful at all, the question is how to display an icon next to the item when the menu unfoldsWeintraub

© 2022 - 2024 — McMap. All rights reserved.