0

I have created a MapView in which i plot the multiple markers using longitude and latitude calling from Database.

Now, I want show bottomsheet while click on this markers and show specific data on sheet. I taken some references for bottomsheet from here Slide in view from bottom over Google Map on Marker click

but after implementing this article i get an error

error is

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: part.time.job.v2, PID: 4236
    java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.material.bottomsheet.BottomSheetBehavior.setPeekHeight(int)' on a null object reference
        at part.time.job.v2.LabourFragment.onCreateView(LabourFragment.java:115)

this is my JAVA code

package part.time.job.v2;


import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.libraries.places.api.Places;
import com.google.android.libraries.places.api.model.Place;
import com.google.android.libraries.places.api.model.PlaceLikelihood;
import com.google.android.libraries.places.api.net.FindCurrentPlaceRequest;
import com.google.android.libraries.places.api.net.FindCurrentPlaceResponse;
import com.google.android.libraries.places.api.net.PlacesClient;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import com.google.maps.android.ui.IconGenerator;

import java.util.Arrays;
import java.util.List;

import model.Jobpost;

import static com.android.volley.VolleyLog.TAG;


/**
 * A simple {@link Fragment} subclass.
 */
public class LabourFragment extends Fragment  implements OnMapReadyCallback {
    private GoogleMap mGoogleMap;
    private MapView mMapview;
    private int STORAGE_PERMISSION_CODE = 1;
    private CameraPosition mCameraPosition;
    private FusedLocationProviderClient mFusedLocationProviderClient;

    private final LatLng mDefaultLocation = new LatLng(-33.8523341, 151.2106085);
    private static final int DEFAULT_ZOOM = 15;
    private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
    private boolean mLocationPermissionGranted;

    private Location mLastKnownLocation;
    Dialog myDialog;
    private BottomSheetBehavior bottomSheetBehavior;
    private View bottomSheet;


    // Keys for storing activity state.
    private static final String KEY_CAMERA_POSITION = "camera_position";
    private static final String KEY_LOCATION = "location";

    // Used for selecting the current place.
    private static final int M_MAX_ENTRIES = 5;
    private String[] mLikelyPlaceNames;
    private String[] mLikelyPlaceAddresses;
    private List[] mLikelyPlaceAttributions;
    private LatLng[] mLikelyPlaceLatLngs;
    private PlacesClient mPlacesClient;

    public LabourFragment() {
        // Required empty public constructor
    }

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



        if (savedInstanceState != null) {
            mLastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION);
            mCameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION);
        }
        // Inflate the layout for this fragment
        View view= inflater.inflate(R.layout.fragment_labour, container, false);
//        myDialog = new Dialog(getActivity());
        bottomSheet = view.findViewById(R.id.bottom_sheet);
        bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);  //error occur on this line
        bottomSheetBehavior.setPeekHeight(200);
        bottomSheetBehavior.setHideable(true);
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);


        Places.initialize(getActivity(), getString(R.string.google_maps_key));
        mPlacesClient = Places.createClient(getActivity());


        mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getActivity());


        return view;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        if (mGoogleMap != null) {
            outState.putParcelable(KEY_CAMERA_POSITION, mGoogleMap.getCameraPosition());
            outState.putParcelable(KEY_LOCATION, mLastKnownLocation);
            super.onSaveInstanceState(outState);
        }
    }

    @Override
    public void onViewCreated(@NonNull View view,  Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mMapview = (MapView) view.findViewById(R.id.mapView);

        if (mMapview!=null){
            mMapview.onCreate(null);
            mMapview.onResume();
            mMapview.getMapAsync(this);
        }
    }



    @Override
    public void onMapReady(final GoogleMap googleMap) {

        mGoogleMap=googleMap;

        FirebaseFirestore mDatabase = FirebaseFirestore.getInstance();
        CollectionReference mOrderRef = mDatabase.collection("Job Post1");

        mOrderRef.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
            @Override
            public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                for(QueryDocumentSnapshot documentSnapshot : queryDocumentSnapshots) {
                    if(documentSnapshot.contains("lat") && documentSnapshot.contains("lon")) {
                        String lat = (String) documentSnapshot.get("lat");
                        String lon = (String) documentSnapshot.get("lon");
                        final String title = (String) documentSnapshot.get("title");
                        final String jobdate = (String) documentSnapshot.get("jobdate");
                        final String time = (String) documentSnapshot.get("time");



                            if(lat != null && lon != null && !lat.isEmpty() && !lon.isEmpty()) {
                            double latitude = Double.parseDouble(lat.trim());
                            double longitude = Double.parseDouble(lon.trim());
                            IconGenerator iconGen = new IconGenerator(getActivity());

                            googleMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).icon(BitmapDescriptorFactory.fromBitmap(iconGen.makeIcon(title))));
                            googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 18.0f));



                          googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
                              @Override
                              public boolean onMarkerClick(Marker marker) {
                                  updateBottomSheetContent(marker);
                                  return false;
                              }
                          });
                                googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
                                    @Override
                                    public void onMapClick(LatLng latLng) {
                                        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
                                    }
                                });
                        }

                    }
                }

            }

        });



    }

    private void updateBottomSheetContent(Marker marker) {
        TextView name = (TextView) bottomSheet.findViewById(R.id.detail_name);
        name.setText(marker.getTitle());
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
    }


}

xml view

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context="part.time.job.v2.LabourFragment">


    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        app:itemBackground="@color/purple"
        app:itemIconTint="@color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/nav_items"
        tools:ignore="MissingConstraints" />

    <com.google.android.gms.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="675dp"
        tools:ignore="MissingConstraints" />

    <include layout="@layout/bottom_sheet" />



</androidx.constraintlayout.widget.ConstraintLayout>

bottom_sheet xml

  <?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"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:fitsSystemWindows="true">


    <androidx.core.widget.NestedScrollView android:id="@+id/bottom_sheet"
        android:layout_width="match_parent" android:layout_height="550dp"
        android:background="@android:color/white" android:clipToPadding="true"
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">


        <TextView android:id="@+id/detail_name" android:layout_width="0dp"
            android:layout_height="wrap_content" android:layout_margin="25dp"
            android:layout_weight="3" android:gravity="center_vertical"
            android:textAppearance="?android:textAppearanceLarge" />

    </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
SHUBHAM SHEDGE
  • 1,695
  • 2
  • 6
  • 16

2 Answers2

1

I have checked your code and it shows bottom sheet as expected. But there are some problems.

  • Most of the part of Bottom Sheet hides behind BottomNavigationView. To overcome this increase PeekHeight slightly.
bottomSheetBehavior.setPeekHeight(300);
  • You set BackgroundColor of Bottom Sheet container to android:color/white. Try changing it to different color.
android:background="@android:color/holo_green_light"
  • You set layout_width of detail_name to 0dp which make the view invisible. Try to make it match_parent
android:layout_width="match_parent"

Here is the complete layout of Bottom Sheet Container:

<androidx.core.widget.NestedScrollView
    android:id="@+id/bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="550dp"
    android:background="@android:color/holo_green_light"
    android:clipToPadding="true"
    app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">


    <TextView
        android:id="@+id/detail_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="25dp"
        android:layout_weight="3"
        android:gravity="center_vertical"
        android:textAppearance="?android:textAppearanceLarge" />

</androidx.core.widget.NestedScrollView>

Output:
enter image description here

Boken
  • 4,825
  • 10
  • 32
  • 42
Md. Asaduzzaman
  • 14,963
  • 2
  • 34
  • 46
0

There have no view in your xml having "R.id.bottom_sheet" id, but you are trying to get the view by findViewbyId(), thats why bottomSheet variable is having null value also the bottomsheetbehaviour value is null and producing null pointer exception when trying to access any method on it. In your case the following line:

bottomSheetBehavior.setPeekHeight(200);
Md Golam Rahman Tushar
  • 2,175
  • 1
  • 14
  • 29