How do I add my Floating Action Button focus and clickable when navigation drawer is open?

I want my floating action button to appear when navigation drawer is open and will disappear when navigation drawer is closed, how do I do this? Here is a image for you to see what I am talking about. Here is the image.

Here is my code for the activity.xml

<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/drawer_layout"
   >

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/drawerNavigationView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/navigation_drawer_header"
        app:menu="@menu/navigation_drawer_menu"
        android:fitsSystemWindows="true"
        app:insetForeground="@android:color/transparent">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="bottom"
            android:paddingLeft="20dp"
            android:paddingBottom="20dp"
            android:paddingTop="40dp">
            <ImageView
                android:id="@+id/logoutNavigationDrawer"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src ="@drawable/icon_logout"
                android:layout_centerVertical="true"
                />

            <TextView
                android:id="@+id/logoutTxt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@color/orangeText"
                android:paddingLeft="14dp"
                android:textSize="16sp"
                android:fontFamily="@font/century_gothic_bold"
                android:text="Log out"
                android:layout_toEndOf="@+id/logoutNavigationDrawer"
                android:layout_toRightOf="@+id/logoutNavigationDrawer"
                android:layout_centerVertical="true"/>
        </RelativeLayout>

    </com.google.android.material.navigation.NavigationView>
<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/emergencyCallFAB"
            android:layout_width="wrap_content"
            app:tint="@color/white"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:src="@drawable/emergency_call_button_round"
            app:backgroundTint="@color/red"
            android:layout_marginStart="370dp"
            android:layout_marginEnd="50dp"
            android:layout_marginTop="800dp"
            android:layout_marginBottom="50dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.drawerlayout.widget.DrawerLayout>

Here is my java code in where I implemented the NavigationDrawer

        //Setting Emergency Floating Action Button
        emergenyCallFABBtn = findViewById(R.id.emergencyCallFAB);

        //Will open the menu, once hamburger button has been clicked
        hamburgerMenuButton = findViewById(R.id.hamburgerMenuIcon);
        hamburgerMenuButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               drawerLayout.openDrawer(GravityCompat.START);
            }
        });

        drawerLayout.setScrimColor(Color.parseColor("#00000000")); // set screen color behind navigation , this is what makes screen behind navigation looks as same color

        //NavigationDrawer Function
        navigationView.bringToFront();
        ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(Location.this, drawerLayout,
                R.string.navigation_drawer_open, R.string.navigation_drawer_close){
            public void onDrawerOpened(View drawerView){
                super.onDrawerClosed(drawerView);
                emergenyCallFABBtn.setVisibility(View.VISIBLE); // make it visible and bring to front
                emergenyCallFABBtn.bringToFront();
            }

            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {
                super.onDrawerSlide(drawerView, slideOffset);
                emergenyCallFABBtn.setVisibility(View.VISIBLE);
                emergenyCallFABBtn.setAlpha(slideOffset); // makes it visible it animation , as drawer opens button becomes less faded and vice versa in case of close
            }

            public void onDrawerClosed(View view){
                super.onDrawerClosed(view);
                emergenyCallFABBtn.setVisibility(View.GONE); // hide button on drawer close
            }
        };
        actionBarDrawerToggle.setDrawerIndicatorEnabled(false);
        drawerLayout.addDrawerListener(actionBarDrawerToggle);
        actionBarDrawerToggle.syncState();
        navigationView.setItemIconTintList(null);
        navigationView.setNavigationItemSelectedListener(Location.this);

        emergenyCallFABBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(Location.this, EmergencyCall.class);
                startActivity(intent);
                Toast.makeText(Location.this, "Clicked on Emergency Call", Toast.LENGTH_SHORT).show();
            }
        });

Here is my onNavigationItemSelected and my onBackPressed function

    //Case switch function for the hamburger menu.
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        switch (menuItem.getItemId()) {
            case R.id.homeNavigationDrawer:
                Intent homeNavDrawer = new Intent(Location.this, TrackActivity.class);
                startActivity(homeNavDrawer);
                break;
            case R.id.profileNavigationDrawer:
                Intent profileNavDrawer = new Intent(Location.this, Profile.class);
                startActivity(profileNavDrawer);
                break;
            case R.id.changeCityNavigationDrawer:
                Intent changeCityNavDrawer = new Intent(Location.this, NCR.class);
                startActivity(changeCityNavDrawer);
                break;
//            case R.id.nav_logout:
//                try {
//                    auth.signOut();
//                    Intent i = new Intent(getApplicationContext(), Location.class);
//                    startActivity(i);
//                    // signed out
//                } catch (Exception e) {
//                    // Error handling!
//                }
//                break;
        }
        return true;
    }

    @Override
    public void onBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            if (drawerLayout.isDrawerOpen(navigationView)) {

                View content = findViewById(R.id.emergencyCallFAB); // find the id of the view you want to check for clicable
                int[] contentLocation = new int[2];
                content.getLocationOnScreen(contentLocation);
                Rect rect = new Rect(contentLocation[0],
                        contentLocation[1],
                        contentLocation[0] + content.getWidth(),
                        contentLocation[1] + content.getHeight());

                if ((rect.contains((int) event.getX(), (int) event.getY()))) { // your view is clicked , perform you action
                    emergenyCallFAB.performClick();
                    isOutSideClicked = false;
                } else { // clicked outside the button
                    isOutSideClicked = true;
                }

            }
        }

        return super.dispatchTouchEvent(event);
    }

Update: There is Error now.

Upvotes: 1

Views: 482

Answers (1)

Nitish
Nitish

Reputation: 3411

I have made changes to your code to make fab focus, and added comments where I made a change , let me know if anything still unclear.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/drawerNavigationView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/navigation_drawer_header"
        app:insetForeground="@android:color/transparent"
        app:menu="@menu/navigation_drawer_menu">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="bottom"
            android:paddingLeft="20dp"
            android:paddingTop="40dp"
            android:paddingBottom="20dp">

            <ImageView
                android:id="@+id/logoutNavigationDrawer"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:src="@drawable/ic_launcher_background" />

            <TextView
                android:id="@+id/logoutTxt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_toEndOf="@+id/logoutNavigationDrawer"
                android:layout_toRightOf="@+id/logoutNavigationDrawer"
                android:paddingLeft="14dp"
                android:text="Log out"
                android:textColor="@color/colorPrimaryDark"
                android:textSize="16sp" />
        </RelativeLayout>

    </com.google.android.material.navigation.NavigationView>

<!--    added relative layout as you didn't have any view group using UI to distort in different devices-->
<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!-- removed extra params , set visiblity gone to hide first time -->

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/emergencyCallFAB"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_alignParentEnd="true"
            android:layout_alignParentBottom="true"
            android:layout_centerVertical="true"
            android:layout_marginEnd="20dp"
            android:visibility="gone"
            android:layout_marginBottom="20dp"
            android:src="@android:drawable/sym_call_incoming"/>
    </RelativeLayout>

</androidx.drawerlayout.widget.DrawerLayout>

MainActivity

  drawerLayout = findViewById(R.id.drawer_layout);
        drawerLayout.setScrimColor(Color.parseColor("#00000000")); // set screen color behind navigation , this is what makes screen behind navigation looks as same color
        navigationView = findViewById(R.id.drawerNavigationView);
        emergenyCall = findViewById(R.id.emergencyCallFAB);
        //NavigationDrawer Function
        navigationView.bringToFront();
        ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
                R.string.navigation_drawer_open, R.string.navigation_drawer_close){
            public void onDrawerOpened(View drawerView){
                super.onDrawerClosed(drawerView);
                emergenyCall.setVisibility(View.VISIBLE); // make it visible and bring to front
                emergenyCall.bringToFront();
            }

            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {
                super.onDrawerSlide(drawerView, slideOffset);
                emergenyCall.setVisibility(View.VISIBLE);
                emergenyCall.setAlpha(slideOffset); // makes it visible in animation , as drawer opens button becomes less faded and vice versa in case of close.
            }

            public void onDrawerClosed(View view){
                super.onDrawerClosed(view);
                emergenyCall.setVisibility(View.GONE); // hide button on drawer close
            }
        };
        actionBarDrawerToggle.setDrawerIndicatorEnabled(false);
        drawerLayout.addDrawerListener(actionBarDrawerToggle);
        actionBarDrawerToggle.syncState();
        navigationView.setItemIconTintList(null);

Update : To make FAB clickable to need to override dispatchTouchEvent and detect the touch on your button

 @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            if (drawerLayout.isDrawerOpen(navigationView)) {

                View content = findViewById(R.id.emergencyCallFAB); // find the id of the view you want to check for clicable
                int[] contentLocation = new int[2];
                content.getLocationOnScreen(contentLocation);
                Rect rect = new Rect(contentLocation[0],
                        contentLocation[1],
                        contentLocation[0] + content.getWidth(),
                        contentLocation[1] + content.getHeight());

                if ((rect.contains((int) event.getX(), (int) event.getY()))) { // your view is clicked , perform you action
                    emergenyCall.performClick();
                    isOutSideClicked = false;
                } else { // clicked outside the button
                    isOutSideClicked = true;
                }

            }
        }

        return super.dispatchTouchEvent(event);
    }

Final Result

enter image description here

Upvotes: 1

Related Questions