Android DrawerLayout icon animation - java

I'm trying to animate the icons in my DrawerLayout using an AnimationDrawable. I created a new project selecting Navigation Drawer Activity as the main activity. I created an animation from a set of XML files and the animation runs in the previewer in Android Studio. I set the animation XML as the icon on the menu item and add a DrawerListener.onDrawerOpened(View V) that gets the menu item, gets its icon and calls start() as described here https://developer.android.com/guide/topics/graphics/drawable-animation. This seemed pretty straightforward to implement but also too simple which is why I wasn't too surprised when it didn't work. It just shows the first image in the series and never changes to the other images. If I run the app in the debugger I see that the icon is indeed an AnimationDrawable and that the icon's instance variables mAnimating and mRunning change from false to true when I call start() on it. Obviously there is something more I need to be doing but I don't know what. I did notice that the icon's mAnimationRunnable is set to null and I'm guessing this might have something to do with it.
Animation ld.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
<item android:drawable="#drawable/ic_untitled_1" android:duration="500" />
<item android:drawable="#drawable/ic_untitled_2" android:duration="500" />
<item android:drawable="#drawable/ic_untitled_3" android:duration="500" />
<item android:drawable="#drawable/ic_untitled_4" android:duration="500" />
<item android:drawable="#drawable/ic_untitled_5" android:duration="500" />
<item android:drawable="#drawable/ic_untitled_6" android:duration="500" />
<item android:drawable="#drawable/ic_untitled_7" android:duration="500" />
<item android:drawable="#drawable/ic_untitled_8" android:duration="500" />
</animation-list>
Drawer activity_main_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:icon="#drawable/ld"
android:title="#string/menu_home" />
<item
android:id="#+id/nav_settings"
android:icon="#drawable/ic_menu_gallery"
android:title="#string/menu_settings" />
<item
android:id="#+id/nav_timers"
android:icon="#drawable/ic_menu_slideshow"
android:title="#string/menu_timers" />
</group>
</menu>
Main layout activity_main.xml
<androidx.drawerlayout.widget.DrawerLayout 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"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
android:id="#+id/app_bar_main"
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
Main activity onCreate MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
com.company.databinding.ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.appBarMain.toolbar);
DrawerLayout drawer = binding.drawerLayout;
NavigationView navigationView = binding.navView;
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(R.id.nav_home, R.id.nav_settings, R.id.nav_timers).setOpenableLayout(drawer).build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
binding.drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
#Override
public void onDrawerSlide(#NonNull View drawerView, float slideOffset) {
}
#Override
public void onDrawerOpened(View drawerView) {
((AnimationDrawable)navigationView.getMenu().getItem(0).getIcon()).start();
}
#Override
public void onDrawerClosed(#NonNull View drawerView) {
((AnimationDrawable)navigationView.getMenu().getItem(0).getIcon()).stop();
}
#Override
public void onDrawerStateChanged(int newState) {
}
});
}

I haven't been able to make the AnimationDrawable start() as a menu icon but it does start if I display it in an ImageView in the navigation header. So I manually animated it myself. Here is my MenuIconAnimator class. I still use a DrawerListener and in onDrawerOpened(View drawerView) I create an instance of my animator class passing it the menu item and then I call start() on it. This swaps the menu icon based on the parameters setup in the animation XML. And then in onDrawerClosed(#NonNull View drawerView) I call the method stopThread() on the MenuIconAnimator and the thread stops.
Here are the relevant DrawerListener methods. menuIconAnimator is an instance variable on my activity class.
#Override
public void onDrawerOpened(View drawerView) {
menuIconAnimator = new MenuIconAnimator(navigationView.getMenu().getItem(0));
menuIconAnimator.start();
}
#Override
public void onDrawerClosed(#NonNull View drawerView) {
menuIconAnimator.stopThread();
}
Here is my MenuIconAnimator class.
package com.leridiandynamics.smartrecirculationcontrol2.ui;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.view.MenuItem;
public class MenuIconAnimator extends Thread{
Boolean running=true;
MenuItem menuItem;
public MenuIconAnimator(MenuItem menuItem){
this.menuItem = menuItem;
}
public void stopThread(){
running = false;
}
public void run() {
// Get the icon that is set on the menuItem. This is an AnimationDrawable.
// Hold onto it while we manually animate each frame by setting the frame
// drawable as the menuItem icon.
AnimationDrawable animationDrawable = ((AnimationDrawable)menuItem.getIcon());
Handler mainHandler = new Handler(Looper.getMainLooper());
while (running) {
try {
// loop through each frame setting it as the icon on the menu item and then sleep
// the thread for the duration of the frame.
for (int i=0; i<animationDrawable.getNumberOfFrames();i++){
Drawable drawable = animationDrawable.getFrame(i);
mainHandler.post(() -> menuItem.setIcon(drawable));
sleep(animationDrawable.getDuration(i));
if (!running) break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// restore the original animationDrawable on the menuItem so it is available the next time
// the MenuIconAnimator is called.
mainHandler.post(() -> menuItem.setIcon(animationDrawable));
}
}
UPDATE: It seems that if you have the animation running too quickly the menu is not very responsive to user input. Maybe that is why animation doesn't work on the menu items out of the box.
UPDATE 2: I have discovered that if the menu item's icon is changed while the user is tapping the menu item, the tap does not register. Finger touch, icon change, finger release...the menu item selection does not register.
UPDATE 3: This does not appear to be a viable solution to making AnimationDrawable work on a MenuItem. When the icon is changed the entire menu appears to redraw and any touch events are reset. I submitted an issue with Google regarding AnimationDrawable not animating on a MenuItem. https://issuetracker.google.com/issues/226640828 Will see if this gets addressed.

Related

Unable to navigate to desired fragment using navigation component

I am using navigation component in my app. I am trying to navigate to the Fragment on click of an action bar icon, but it is not working.
Below is my code:
action_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:title=""
android:id="#+id/cart_notif"
android:icon="#drawable/ic_order"
app:showAsAction="always"
android:actionLayout="#layout/notification_badge"/>
</menu>
nav_host.xml
<fragment
android:id="#+id/cartFragment"
android:name="BottomFragments.CartFragment"
android:label="Cart"
tools:layout="#layout/fragment_cart">
<action
android:id="#+id/action_cartFragment_to_cakeFragment"
app:destination="#id/cakeFragment"
app:enterAnim="#anim/nav_default_enter_anim"
app:popUpTo="#id/cakeFragment"
app:popUpToInclusive="true" />
</fragment>
MainActivity.java
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
if(item.getItemId() == R.id.cart_notif){
NavController navController = Navigation.findNavController(MainActivity.this,R.id.fragment);
navController.navigate(R.id.cartFragment);
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onSupportNavigateUp() {
navController.navigateUp();
return super.onSupportNavigateUp();
}
This approach is not working - how can I navigate?
here I can see you are using onOptionsItemSelected for navigating from one screen to another. Instead you should use onNavigationItemSelected method.
See this answer for more details.

Menu action items goes to overflow menu

You will have to forgive me, because I am still pretty new to android development. For my android app, I am staying to create a custom menu and place on the tool bar with the java code in a base activity that is extended by the other activities. But for some reason, the menu buttons are hiding in the overflow menu even though there is more than enough room for them to be showing. I feel like my code is correct, but I need to add a reference to something somewhere else that I am missing. Thanks in advance!
Current toolbar appearance
BaseActivity.java
public abstract class BaseActivity extends AppCompatActivity {
private Toolbar toolBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResource());
toolBar = (Toolbar) this.findViewById(R.id.toolbar);
if (toolBar != null) {
setSupportActionBar(toolBar);
if (getSupportActionBar() != null) {
setDisplayHomeEnabled(true);
}
}
}
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
protected abstract int getLayoutResource();
public void setDisplayHomeEnabled(boolean b) {
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(b);
}
}
#Override
public void setTitle(CharSequence title) {
toolBar.setTitle(title);
}
#Override
public void setTitle(int titleId) {
toolBar.setTitle(titleId);
}
public Toolbar getToolBar() {
return toolBar;
}
}
toolbar.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:minHeight="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:titleTextColor="#android:color/white"
android:background="?attr/colorPrimary">
</android.support.v7.widget.Toolbar>
</LinearLayout>
main_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/menu_settings"
android:title="Settings"
android:icon="#android:drawable/ic_menu_preferences"
android:showAsAction="always"/>
<item
android:id="#+id/menu_search"
android:title="Search"
android:showAsAction="always"
android:icon="#android:drawable/ic_menu_search"
android:actionViewClass="android.widget.SearchView"/>
</menu>
In your main_menu.xml file, add an 'app' tag for showAsAction as I have done below. It worked for me. See if that works for you too.
<?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/menu_settings"
android:title="Settings"
android:icon="#android:drawable/ic_menu_preferences"
app:showAsAction="always"/>
<item
android:id="#+id/menu_search"
android:title="Search"
app:showAsAction="always"
android:icon="#android:drawable/ic_menu_search"
android:actionViewClass="android.widget.SearchView"/>
</menu>

How to make option menu appear on bottom of the screen?

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:
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:
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
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
Bottom App Bar. How to start
Implementing Google’s newly launched Bottom AppBar
Implementing BottomAppBar I: Material Components for Android
Bottom App Bars
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;
}
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.
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.!
Answer by #Nilesh is very elaborate and bit complicated.
Simple Solution
Create FrameLayout and arrange your buttons inside frame layout depending on your requirements. Set id -- I use id = "menu"
Set visibility to gone android:visibility = "gone"
On menubutton click
findViewById(R.id.menu).setVisibility(View.VISIBLE);
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.
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.
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.
//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"
/>

Creating the Sub Menu in Navigation Drawer in Android

I have created the Navigation Drawer using the below link which is very nice :
http://blog.teamtreehouse.com/add-navigation-drawer-android
You can download the Navigation Drawer from this URl -
https://github.com/sanjaisy/Android-Navigation-Drawer.git
Now I want to add Submenu to this navigation drawer.Please help me with a solution.
Here is my Full java Code
public class SmoothBanlanceHome extends ActionBarActivity {
private ListView mDrawerList;
private DrawerLayout mDrawerLayout;
private ArrayAdapter<String> mAdapter;
private ActionBarDrawerToggle mDrawerToggle;
private String mActivityTitle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_smooth_banlance_home);
mDrawerList = (ListView)findViewById(R.id.navList);mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
mActivityTitle = getTitle().toString();
addDrawerItems();
setupDrawer();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
private void addDrawerItems() {
String[] MenuArray = getResources().getStringArray(R.array.Naviagation_Menu_List);
mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, MenuArray);
mDrawerList.setAdapter(mAdapter);
mDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(SmoothBanlanceHome.this, "Time for an upgrade!", Toast.LENGTH_SHORT).show();
}
});
}
private void setupDrawer() {
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.drawer_open, R.string.drawer_close) {
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getSupportActionBar().setTitle("Menu");
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
getSupportActionBar().setTitle(mActivityTitle);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
mDrawerToggle.setDrawerIndicatorEnabled(true);
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}}
Here is the layout code
<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- As the main content view, the view below consumes the entire
space available using match_parent in both dimensions. -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- android:layout_gravity="start" tells DrawerLayout to treat
this as a sliding drawer on the left side for left-to-right
languages and on the right side for right-to-left languages.
The drawer is given a fixed width in dp and extends the full height of
the container. A solid background is used for contrast
with the content view. -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
Please can anyone tell me how can I make Sub menu with this code. You can also download the full Navigation Working code from git url as I have mention above.
Here is the picture which i want
You should use NavigationView from Android Support Design Library instead of this NavigationDrawer.
Check this official sample:
https://github.com/chrisbanes/cheesesquare
It's quite easier.
Using Android Suppor Design Library you will create your submenus like this:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:icon="#drawable/ic_event"
android:title="Home" />
<item
android:id="#+id/nav_profile"
android:icon="#drawable/ic_dashboard"
android:title="Perfil" />
</group>
<item android:title="More Options">
<menu>
<item
android:icon="#drawable/ic_forum"
android:title="Forum" />
<item
android:icon="#drawable/ic_headset"
android:title="Headset" />
</menu>
</item>
</menu>
Best regards.

changing images rapidly in java android

I am having a problem in changing images rapidly on click. I have made an image button I want to change the image when the button is clicked and back to the previous image. I have searched a lot but cant find the solution.
public class Buttonone extends Activity {
ImageButton btonImage;
boolean isPressed = true;
MediaPlayer mp;
boolean isPlay = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.button_one);
btonImage = (ImageButton) findViewById(R.id.btonImage);
btonImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
playSound();toggleImage();
}
});
}
private void toggleImage() {
// TODO Auto-generated method stub
btonImage.setImageResource(R.drawable.image2);
}
}
this is the layout xml for image button
<ImageButton
android:id="#+id/btonImage"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:contentDescription="#null"
android:background="#080808"
android:src="#drawable/image1" />
Set the src to a drawable like this
<ImageButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/imgButtonBack"/>
And create a file named imgButtonBack.xml in drawable folder and set the following code
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#android:drawable/presence_video_away"
android:state_pressed="true" />
<item android:drawable="#android:drawable/presence_audio_busy"
android:state_focused="true" />
<item android:drawable="#android:drawable/presence_audio_busy" />
</selector>
Change the image as per your need
setContentView(R.layout.button_one);
This is your problem. You should set the entire layout and handle click event !

Categories