17

Here is what I am trying to implement: when people click on the menu on top right corner of a toolbar, an options menu appears on bottom of the screen. See picture below:

enter image description here

I am not sure what method should I call for the item at the bottom. Can somebody give me some hint on how to implement this?

I implement successfully the icon in the top right menu bar with the code below. But I don't know how to show the options at the bottom of the screen, with width match_parent, and height wrap_content

onClick on the right top corner

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.edit_profile_image_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        switch (id) {
            case R.id.more:
                //How to show the 2 option in the bottom of screen here


                return true;
        }

        return super.onOptionsItemSelected(item);
    }

Update

After implement the code of Nikesh, the popup shown like this:

enter image description here

The Vee
  • 11,420
  • 5
  • 27
  • 60
ken
  • 2,426
  • 5
  • 43
  • 98
  • You can use move able button and pop up a menu from it. –  Jun 21 '17 at 12:52
  • a pop up menu start from bottom??can u explain more?? – ken Jun 21 '17 at 12:53
  • 2
    What you need is `BottomSheet`. Read this tutorial: https://code.tutsplus.com/articles/how-to-use-bottom-sheets-with-the-design-support-library--cms-26031 – aborocz Jun 21 '17 at 12:59
  • You can also get the look you want by using [BottomSheetDialogFragment](https://developer.android.com/reference/android/support/design/widget/BottomSheetDialogFragment) – Burak Cakir Nov 26 '18 at 10:41

7 Answers7

6

UPDATED ANSWER

You can now use Material Design BottomAppBar

  • A bottom app bar displays navigation and key actions at the bottom of mobile screens

SAMPLE CODE

Add below dependencies in your build.gradle

implementation 'com.google.android.material:material:1.0.0'

Now create 3 menu file in res/menu directory

enter image description here

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

    <item
        android:id="@+id/app_bar_search"
        android:icon="@drawable/ic_search"
        android:title="Search"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/app_bar_fav"
        android:icon="@drawable/ic_favorite"
        android:title="Favorite"
        app:showAsAction="ifRoom"/>
    <item
        android:icon="@drawable/ic_favorite"
        android:title="Favorite"
        app:showAsAction=""/>
</menu>

nav_drawer_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/navItemOne"
        android:title="Nav Item 1"
        app:showAsAction="never"/>

    <item
        android:id="@+id/navItemTwo"
        android:title="Nav Item 2"
        app:showAsAction="never"/>

    <item
        android:id="@+id/navItemThree"
        android:title="Nav Item 3"
        app:showAsAction="never"/>
</menu>

toolbar_menu.xml

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

    <item
        android:id="@+id/app_bar_fav"
        android:icon="@drawable/ic_favorite"
        android:title="Favorite"
        app:showAsAction="ifRoom"/>
    <item
        android:id="@+id/app_bar_search"
        android:icon="@drawable/ic_search"
        android:title="Search"
        app:showAsAction="ifRoom"/>
    <item
        android:id="@+id/app_bar_settings"
        android:title="Settings"
        app:showAsAction="never"/>

    <item
        android:title="Menu Item 1"
        app:showAsAction="never"/>

    <item
        android:title="Menu Item 2"
        app:showAsAction="never"/>
    <item
        android:title="Menu Item 3"
        app:showAsAction="never"/>

</menu>

Now Create a class name BottomNavigationDrawerFragment to open navigation drawer from bottom

import android.content.Context
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.android.synthetic.main.bottom_nav_layout.*

class BottomNavigationDrawerFragment : BottomSheetDialogFragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.bottom_nav_layout, container, false)
    }
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        navigation_view.setNavigationItemSelectedListener { menuItem ->
            // Bottom Navigation Drawer menu item clicks
            when (menuItem!!.itemId) {
                R.id.navItemOne -> context!!.toast(" Nav item one is Clicked ")
                R.id.navItemTwo -> context!!.toast(" Nav item Two is Clicked ")
                R.id.navItemThree -> context!!.toast(" Nav item Three is Clicked ")
            }
            // Add code here to update the UI based on the item selected
            // For example, swap UI fragments here
            true
        }
    }

    // This is an extension method for easy Toast call
    fun Context.toast(message: CharSequence) {
        val toast = Toast.makeText(this, message, Toast.LENGTH_SHORT)
        toast.setGravity(Gravity.BOTTOM, 0, 600)
        toast.show()
    }
}

Code of MainActivity

import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //  attach menu to your BottomAppBar
        bottomBar.replaceMenu(R.menu.bottom_menu)

        // handle click event of navigationIcon
        bottomBar.setNavigationOnClickListener {
            toast("Navigation Icon Clicked")
            val bottomNavDrawerFragment = BottomNavigationDrawerFragment()
            bottomNavDrawerFragment.show(supportFragmentManager, bottomNavDrawerFragment.tag)
        }

        // handle click event of FloatingActionButton
        fab.setOnClickListener {
            toast("Fab Icon Clicked")

        }

        //handle click event of menu of BottomAppBar
        bottomBar.setOnMenuItemClickListener { menuItem ->

            when (menuItem!!.itemId) {
                R.id.app_bar_search -> toast("Search menu of bottomBar is clicked!")
            }

            true
        }
    }

    // Overriding Actionbar menu
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        val inflater = menuInflater
        inflater.inflate(R.menu.toolbar_menu, menu)
        return true
    }


    //handle click event of menu of Actionbar
    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
        when (item!!.itemId) {
            R.id.app_bar_fav -> toast("Fav menu item of toolbar is clicked!")
            R.id.app_bar_search -> toast("Search menu item of toolbar is clicked!")
            R.id.app_bar_settings -> toast("Settings item  of toolbar is clicked!")
            else -> toast("Menu item  of toolbar  is clicked!")
        }

        return true
    }

    // method to display toast
    private fun toast(message: String) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
    }
}

layout.activity_main

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    android:fitsSystemWindows="true">

    <com.google.android.material.bottomappbar.BottomAppBar
        android:id="@+id/bottomBar"
        style="@style/Widget.MaterialComponents.BottomAppBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        app:fabCradleMargin="10dp"
        app:fabCradleVerticalOffset="4dp"
        android:backgroundTint="@color/colorPrimary"
        app:fabAlignmentMode="center"
        app:navigationIcon="@drawable/ic_drawer"/>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_anchor="@id/bottomBar"
        app:srcCompat="@drawable/ic_apps" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

bottom_nav_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">


    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:menu="@menu/nav_drawer_menu"/>

</androidx.constraintlayout.widget.ConstraintLayout>

SAMPLE CODE for JAVA Lover

BottomNavigationDrawerFragment

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.navigation.NavigationView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import neel.com.bottomappbar.R;

public class BottomNavigationDrawerFragment extends BottomSheetDialogFragment {

    private Context mContext;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext=context;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View rootView= inflater.inflate(R.layout.bottom_nav_layout, container, false);

        NavigationView navigationView=rootView.findViewById(R.id.navigation_view);

        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {

                switch (menuItem.getItemId()){
                    case R.id.navItemOne:
                        Toast.makeText(mContext, "Nav item One is Clicked ", Toast.LENGTH_SHORT).show();
                        return true;
                    case R.id.navItemTwo:
                        Toast.makeText(mContext, "Nav item Two is Clicked ", Toast.LENGTH_SHORT).show();
                        return true;
                    case R.id.navItemThree:
                        Toast.makeText(mContext, "Nav item Three is Clicked ", Toast.LENGTH_SHORT).show();
                        return true;
                }
                return false;
            }
        });

        return rootView;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }
}

MainActivity

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.google.android.material.bottomappbar.BottomAppBar;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import neel.com.bottomappbar.R;

public class MainActivity extends AppCompatActivity {

    BottomAppBar bottomAppBar;
    FloatingActionButton floatingActionButton;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bottomAppBar = findViewById(R.id.bottomBar);

        //  attach menu to your BottomAppBar
        bottomAppBar.replaceMenu(R.menu.bottom_menu);

        // handle click event of navigationIcon of bottomAppBar
        bottomAppBar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                BottomNavigationDrawerFragment bottomNavigationDrawerFragment = new BottomNavigationDrawerFragment();
                bottomNavigationDrawerFragment.show(getSupportFragmentManager(), bottomNavigationDrawerFragment.getTag());
            }
        });

        //handle click event of menu of BottomAppBar
        bottomAppBar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.app_bar_search:
                        Toast.makeText(MainActivity.this, "Search menu of bottomBar is clicked!", Toast.LENGTH_SHORT).show();
                        return true;
                    case R.id.app_bar_fav:
                        Toast.makeText(MainActivity.this, "Favorite menu of bottomBar is clicked!", Toast.LENGTH_SHORT).show();
                        return true;

                }
                return false;
            }
        });

        floatingActionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this, "Fab Is clicked ", Toast.LENGTH_SHORT).show();
            }
        });
    }

    // Overriding Actionbar menu
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.toolbar_menu, menu);
        return true;
    }

    //handle click event of menu of Actionbar
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.app_bar_fav:
                Toast.makeText(MainActivity.this, "Fav menu item of toolbar is clicked!", Toast.LENGTH_SHORT).show();
                return true;
            case R.id.app_bar_search:
                Toast.makeText(MainActivity.this, "Search menu item of toolbar is clicked!", Toast.LENGTH_SHORT).show();
                return true;
            case R.id.app_bar_settings:
                Toast.makeText(MainActivity.this, "app_bar_settings", Toast.LENGTH_SHORT).show();
                return true;

        }
        return false;
    }
}

for more information please check below articles

OUTPUT

https://www.youtube.com/watch?v=k145bGLrleo

OLD ANSWER

try this attach this PopupMenu in your bottom view click event something like button click event

step 1 create a view at bootom of your layout like this

<View
android:layout_gravity="center"
android:id="@+id/myView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

step 2 create a new_menu.xml file like this

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
    android:id="@+id/temp"
    android:title="@string/str_menu_account_logout"
    android:icon="@drawable/next"
    app:showAsAction="ifRoom"></item>

</menu>

now add this code to create option menu in your java file

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.new_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if (item.getItemId() == R.id.temp) {
        PopupMenu popupMenu = new PopupMenu(this, findViewById(R.id.myView),Gravity.CENTER);
        popupMenu.inflate(R.menu.home_menu);
        popupMenu.show();
        return true;
    }

    return false;

}
AskNilesh
  • 67,701
  • 16
  • 123
  • 163
  • the menu.xml file is the place to put "select from album" and "save to album" inside?? – ken Jun 21 '17 at 13:23
  • you have to perform click event of select from album" or save to album" to show pop up menu – AskNilesh Jun 21 '17 at 13:29
  • no,I want when people click on the icon on the top right corner,then I show the menu with "select from album" and "save to phone" in the bottom – ken Jun 21 '17 at 13:35
  • than place to put "select from album" and "save to album" inside menu – AskNilesh Jun 21 '17 at 13:40
  • I tried,but when I click on the icon on top right corner,the menu not shown at the bottom – ken Jun 21 '17 at 13:47
  • @ken check my update ans and ask me in case of any query – AskNilesh Jun 21 '17 at 14:03
  • I tried it,it show the popup menu.but it the position is not at the bottom..I update the question now,please check ya – ken Jun 21 '17 at 14:11
0

I will suggest to use the Material design App Bar(Bottom), with few modifications you can get the result.

Try this https://material.io/design/components/app-bars-bottom.html

hope this will help.

Minion
  • 964
  • 14
  • 16
0

Simple. Make a dialog with its own contents which will makeup the bottom menu. When user clicks there above then the dialog should show but its position would be below i.e. anchored with the bottom. You can find many codes regarding how to position dialog at the bottom of the scree anchored!! SO not adding any.Hope it helps.!

Debasish Ghosh
  • 1,867
  • 20
  • 29
0

Answer by @Nilesh is very elaborate and bit complicated.

Simple Solution

  1. Create FrameLayout and arrange your buttons inside frame layout depending on your requirements. Set id -- I use id = "menu"

  2. Set visibility to gone android:visibility = "gone"

  3. On menubutton click

    findViewById(R.id.menu).setVisibility(View.VISIBLE);

  4. Now to make menu disappear when you click outside the menu, add an empty view or layout behind the menu. set ontouch listner. Set visibility GONE when the background view is touched.

Mayank Kumar Chaudhari
  • 16,027
  • 10
  • 55
  • 122
0

there is no need to reinvent the wheel; use a BottomNavigationView, which is being provided by:

dependencies {
    api "com.google.android.material:material:1.0.0"
}

it can be added into the layout alike this (set gone by default):

 <android.support.design.widget.BottomNavigationView
     android:id="@+id/navigation"
     android:layout_width="match_parent"
     android:layout_height="56dp"
     android:layout_gravity="start"
     android:visiblity="gone"
     app:menu="@menu/bottom" />

the menu/bottom.xml:

<menu
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@+id/action_search"
        android:title="@string/menu_search"
        android:icon="@drawable/ic_search" />

    <item android:id="@+id/action_settings"
        android:title="@string/menu_settings"
        android:icon="@drawable/ic_add" />

</menu>

then hook into the onMenuOpened() event:

@Override
public boolean onMenuOpened(int featureId, Menu menu) {
    this.mBottomNavigationView.setVisibility(View.VISIBLE);
    return super.onMenuOpened(featureId, menu);
}

and also implement method onOptionsItemSelected():

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.action_search:
            ...
            this.hideBottomNavigation();
            return true;

        case R.id.action_settings:
            ...
            this.hideBottomNavigation();
            return true;

        default:
            this.hideBottomNavigation();
            return super.onOptionsItemSelected(item);
    }
}

private void hideBottomNavigation() {
    this.mBottomNavigationView.setVisibility(View.GONE);
}

BottomSheetDialogFragment would indeed be the other option available, while it does not support inflating a menu, but a fragment ...nevertheless it would merely be the same approach.

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
0

You can now use Material Design BottomAppBar

1st add this in build.gradle where all are being implemented

implementation 'com.google.android.material:material:1.0.0'

create menu anyname.xml

2nd add coordinator layout and inside it bottomAppBaradd menu and navigation as given here

3rd Add code by initialising

private var mBottomAppBar: BottomAppBar ?= null

Then add them into the method

//bottom bar
        mBottomAppBar = findViewById(R.id.bar)
        mBottomAppBar?.setOnMenuItemClickListener{
            when(it.itemId){
                R.id.itemConfig->showConfigBottomSheetDialogFragment()

            }
            true
        }
        mBottomAppBar?.setNavigationOnClickListener{
                startContentHighlightActivity()
        }

    }

The navigation will directly work and the menu will work according to the items you will add.

-1
   //This is click event of button 
@Override
public void onClick(View view) {

    switch (view.getId()){
        case R.id.buttonSort:
            PopupMenu popupMenu = new PopupMenu(this, findViewById(R.id.myView),Gravity.CENTER);
            popupMenu.inflate(R.menu.bottom_menu);
            popupMenu.show();
            break;
}

This is my home_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/bottom_menu_price"
    android:title="Price low to high"
    android:icon="@drawable/ic_price_low"

    />
<item
    android:id="@+id/bottom_menu_price_high"
    android:title="Price high to low"
    android:icon="@drawable/ic_price_high"

    />
<item
    android:id="@+id/bottom_menu_date"
    android:title="New Added"
    android:icon="@drawable/ic_date_sort"

    />
<item
    android:id="@+id/bottom_menu_rate"
    android:title="Best Rated"
    android:icon="@drawable/ic_rate_sort"

    />

Nikos Hidalgo
  • 3,666
  • 9
  • 25
  • 39
Tousif Akram
  • 129
  • 6
  • While this block of code might answer the question, it would be much better if you can include some explanation as to what it's doing and why it will solve the problem. It's a good idea to read [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer) to learn about what makes a useful answer here. – DaveyDaveDave Nov 20 '18 at 11:57