androidgoogle-mapsmapfragment

How to keep markers on a map fragment when configuration changes?


I have a map fragment in my Main Activity that on my onMapReady I am adding let's say 300 markers. The markers are divided into 5 categories, each category saved in a List category1(2,3,4,5) = new ArrayList. I have a button that filters the markers by category by setting them visible or not according to the users options from an alert dialog.

for (Marker marker : category1) {
                marker.setVisible(true);.....

Everything works exactly as it should until the screen configuration changes. One solution that I found to keep the visible markers on rotation was to add in my onCreate

if (savedInstanceState == null) {
    mapFragment.setRetainInstance(true);}

This works for keeping the current selection but then when I try to filter again nothing changes. The state of the map fragment remains with the markers that I filtered before the configuration changed.

On the other hand if I am not using the mapFragment.setRetainInstance(true); each time the configuration changes ALL the markers are added again on the fragment, filtering works again but i have to re filter each time.

How can I add all the markers once, and then hide/show them according to the category filter, keep the visible ones between screen rotation and filter them again starting from the last state they were?

UPDATE

Here is what I have (I tried to add only the relevant code)

    Boolean mSetCameraPosition;
    Boolean initialMarkers;
    Boolean checkBox1Checked, checkBox2Checked, checkBox3Checked,     checkBox4Checked, checkBox5Checked;
    private int mapTypeSelected;
    CheckBox cbAllDay, cbBefore12, cbBetween1216, cbBetween1620, ccbAfter20;
    AlertDialog dialog;
    List<Marker> firstCategoryList = new ArrayList<>();
    List<Marker> secondCategoryList = new ArrayList<>();
    List<Marker> thirdCategoryList = new ArrayList<>();
    List<Marker> fourthCategoryList = new ArrayList<>();
    List<Marker> fifthCategoryList = new ArrayList<>();


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


        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            checkLocationPermission();
        }


        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);


        if (savedInstanceState == null) {
            mapTypeSelected = GoogleMap.MAP_TYPE_NORMAL;
            mSetCameraPosition = true;
            mapFragment.setRetainInstance(true);
            initialMarkers = true;


        } else {
            mapTypeSelected = savedInstanceState.getInt("the_map_type", GoogleMap.MAP_TYPE_NORMAL);
            mSetCameraPosition = false;
            initialMarkers = false;

            checkBox1Checked = savedInstanceState.getBoolean("checkBox1");
            checkBox2Checked = savedInstanceState.getBoolean("checkBox2");
            checkBox3Checked = savedInstanceState.getBoolean("checkBox3");
            checkBox4Checked = savedInstanceState.getBoolean("checkBox4");
            checkBox5Checked = savedInstanceState.getBoolean("checkBox5");

  @Override
    public void onMapReady(GoogleMap googleMap) {

        mMap = googleMap;
        if (mSetCameraPosition) {
            initialLocation(TOULOUSE_LAT, TOULOUSE_LNG, 12);

        }
        mMap.setMapType(mapTypeSelected);

 if (initialMarkers) {
            addMarkers2Map();
        }

  public void addMarkers2Map() {

        // Markers location

        LatLng marker1 = new LatLng(43.607044, 1.450307);
        LatLng marker2= new LatLng(43.571505, 1.417759);
        LatLng marker3= new LatLng(43.607469, 1.447162);
        LatLng marker4= new LatLng(43.600723, 1.455917);
        LatLng marker5= new LatLng(43.604892, 1.476562);
        LatLng marker6= new LatLng(43.604496, 1.474924);
        LatLng marker7= new LatLng(43.604781, 1.474502);

        // Markers All day long
        firstCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker1).title("First Place ").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 8.30 - 22.30")));

        // Markers Before 12 PM
        secondCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker2).title("Second Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 10.30 - 11.30")));

        // Markers Between 12-16
        thirdCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker3).title("Third Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 15.30 - 16.30")));
        thirdCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker4).title("Fourth Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 15.00 - 16.00")));

        // Markers Between 16-20
        fourthCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker5).title("Fifth Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 15.30 - 16.30")));
        fourthCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker6).title("Sixth Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 16.30 - 17.30")));
        fourthCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker7).title("Seventh Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 18.30 - 19.30")));
        fourthCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker8).title("Eighth Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 17.30 - 18.30\nHH:21.30 - 22.30")));


        // Markers After 20
        fifthCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker8).title("Eighth Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 17.30 - 18.30\nHH:21.30 - 22.30")));
        fifthCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker1).title("First Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 8.30 - 22.30")));


  public void filterTheMarkers(View view) {


        if (dialog == null){
        AlertDialog.Builder builder;
        builder = new AlertDialog.Builder(this);
        LayoutInflater inflater = this.getLayoutInflater();
        @SuppressLint("InflateParams") View checkBoxView = inflater.inflate(R.layout.markers_filtering, null);
        builder.setView(checkBoxView);
        cbAllDay = (CheckBox) checkBoxView.findViewById(R.id.checkBox1);
        if (checkBox1Checked != null) {
            cbAllDay.setChecked(checkBox1Checked);

        }
        cbBefore12 = (CheckBox) checkBoxView.findViewById(R.id.checkBox2);
        if (checkBox2Checked != null) {
            cbBefore12.setChecked(checkBox2Checked);

        }
        cbBetween1216 = (CheckBox) checkBoxView.findViewById(R.id.checkBox3);
        if (checkBox3Checked != null) {
            cbBetween1216.setChecked(checkBox3Checked);

        }
        cbBetween1620 = (CheckBox) checkBoxView.findViewById(R.id.checkBox4);
        if (checkBox4Checked != null) {
            cbBetween1620.setChecked(checkBox4Checked);

        }
        ccbAfter20 = (CheckBox) checkBoxView.findViewById(R.id.checkBox5);
        if (checkBox5Checked != null) {
            ccbAfter20.setChecked(checkBox5Checked);

        }

        dialog = builder.create();


    }

        dialog.show();
    }

  public void displaySelectedMarkers(View view) {

        dialog.dismiss();
        Log.i("TAG", "All Day " + cbAllDay.isChecked() + " Before 12 " + cbBefore12.isChecked() + " Between 12-16 " + cbBetween1216.isChecked() + " Between 16-20" + cbBetween1620.isChecked() + " After 20 " + ccbAfter20.isChecked());
        //according these check boxes status execute your code to show/hide markers


        if (cbAllDay.isChecked() && cbBefore12.isChecked() && cbBetween1216.isChecked() && cbBetween1620.isChecked() && ccbAfter20.isChecked()) {
            // show all markers
            for (Marker marker : firstCategoryList) {
                marker.setVisible(true);
            }
            for (Marker marker : secondCategoryList) {
                marker.setVisible(true);
            }
            for (Marker marker : thirdCategoryList) {
                marker.setVisible(true);
            }
            for (Marker marker : fourthCategoryList) {
                marker.setVisible(true);
            }
            for (Marker marker : fifthCategoryList) {
                marker.setVisible(true);
            }
        } else if (cbAllDay.isChecked() && !cbBefore12.isChecked() && !cbBetween1216.isChecked() && !cbBetween1620.isChecked() && !ccbAfter20.isChecked()) {
            // show only All Day Markers
            for (Marker marker : firstCategoryList) {
                marker.setVisible(true);
            }
            for (Marker marker : secondCategoryList) {
                marker.setVisible(false);
            }
            for (Marker marker : thirdCategoryList) {
                marker.setVisible(false);
            }
            for (Marker marker : fourthCategoryList) {
                marker.setVisible(false);
            }
            for (Marker marker : fifthCategoryList) {
                marker.setVisible(false);
            }
        }
//....and it goes like this for a while until I finish all the possibilities

  @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("the_map_type", mapTypeSelected);

        outState.putBoolean("checkBox1", cbAllDay.isChecked());
        outState.putBoolean("checkBox2", cbBefore12.isChecked());
        outState.putBoolean("checkBox3", cbBetween1216.isChecked());
        outState.putBoolean("checkBox4", cbBetween1620.isChecked());
        outState.putBoolean("checkBox5", ccbAfter20.isChecked());

    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        savedInstanceState.get("the_map_type");

        checkBox1Checked = savedInstanceState.getBoolean("checkBox1");
        checkBox2Checked = savedInstanceState.getBoolean("checkBox2");
        checkBox3Checked = savedInstanceState.getBoolean("checkBox3");
        checkBox4Checked = savedInstanceState.getBoolean("checkBox4");
        checkBox5Checked = savedInstanceState.getBoolean("checkBox5");

Solution

  • You could handle orientation changes yourself in your manifest:

    <activity android:name=".MyActivity"
              android:configChanges="orientation|screenSize"
              android:label="@string/app_name">
    

    (from Handling Runtime Changes)

    That way, your Activity isn't recreated when the orientation or screen size changes. You'll have to handle things like layout switching yourself though if you have overrides for landscape/portrait.