How to insert markers (marker) on a map in another fragment?

2

I'm developing an Android app where you enter a list of courier tasks (get something in point A and take it to the point B ) and these points are shown on a map

App has two snippets:

  • ReclyclerView containing the task list.

  • Bulleted map showing points A and B of each list item in recyclerView .

  • When the map is created (or recreated) it takes the coordinates of the database (which also feeds the to-do list).

    The question arises when inserting a new task. New bookmarks will only appear if you force map re-creation (by rotating the device or restarting the app ).

    How do I insert bookmarks into the map when inserting a new task?

    UPDATE: As Ack Lay observed, my question lacked more detail. And as a picture is worth a thousand words ...

    ** I'm new here and I can only publish two images ... Then it will be the last two.

    1.When you open the application, an empty panel appears in the left half and an empty map on the right.

  • Touching the + push button opens a form. to enter the task. You should be informed: What will be transported, where to pick up with whom, where to deliver, for whom.

  • Complete form, tap Finish and ...

  • Thetaskdataiswrittentothedatabase.The'adapter'isupdatedalongwiththe'reviewer'andthecardappearsshowingtheinformation.Themapisstillempty.

  • **Operationsinthedatabase(SQLite)aredonebya'dbHelper'classwiththeCRUDmethods.

  • You need to change the device orientation or restart the application for the bookmarks to appear.
  • That is, the markers appear when the'fragment 'is (re) created. What does not work is updating the map, along with the reviewer, when I enter a new task.

    Now it's time to describe the structure of app .

    The main activity is

    public class MainActivity extends FragmentActivity 
    

    It loads the layout it has is made up of

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:baselineAligned="false"
        android:fitsSystemWindows="true"
        android:id="@+id/myContainer"
        android:orientation="horizontal">
        <fragment
            android:id="@+id/runFragment"
            android:name="br.com.medamais.motonoix.RecyclerFragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            tools:layout="@layout/fragment_recycler" />
        <fragment
            android:id="@+id/markersMapFragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            tools:layout="@layout/fragment_map"
            android:name="br.com.medamais.motonoix.MarkersFragment"
            />
    </LinearLayout>
    

    The task list class

    public class RecyclerFragment extends Fragment 
    

    The map class

    public class MapFragment extends Fragment
    

    The code is very similar to what you ordered, it is only more adapted to the app . For example, the pins are fixed. We do not want them to change by touching the map. Only updating the card. To avoid course problems.

    It seems to have several possible approaches. I have some experience as a developer, but this is my first Android app.

    I imagine the solution is a way to access the map instance and add the new'marker '.

    This would be done in'A' event 'onClick ()' of the'positiveButton 'of the dialog that inflates the form (ie when you hit CONFIRM). Or 'B' method wouldbHelper.insert () '

    But there have to be other ways.

    Can someone give me a light?

    UPDATE: In response to @ramaral's tips

    Implementing the 'interface' worked. It was not even necessary to create a custom 'listener', since the button had already been implemented.

    But it's not over yet: - (

    When the device is vertically oriented (portrait), it works correctly. However, when it is horizontal (landscape) not yet.

    Vertical layout is composed like this:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/myContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        android:orientation="vertical">
        <android.support.design.widget.TabLayout
            android:id="@+id/sliding_tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabGravity="fill"
            app:tabMaxWidth="0dp"
            app:tabMode="fixed" />
        <android.support.v4.view.ViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="0px"
            android:layout_weight="1"
            android:background="@android:color/white" />
    </LinearLayout>
    

    Horizontally:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:baselineAligned="false"
        android:fitsSystemWindows="true"
        android:id="@+id/myContainer"
        android:orientation="horizontal">
        <fragment
            android:id="@+id/runFragment"
            android:name="br.com.medamais.motonoix.RecyclerFragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            tools:layout="@layout/fragment_recycler" />
        <fragment
            android:id="@+id/markersMapFragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            tools:layout="@layout/fragment_map"
            android:name="br.com.medamais.motonoix.MarkersFragment"
            />
    </LinearLayout>
    

    Map fragment layout

    <?xml version="1.0" encoding="utf-8"?>
    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:map="http://schemas.android.com/apk/res-auto"
        android:id="@+id/markersMapFragment"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        map:cameraTargetLat="-23.7941"
        map:cameraTargetLng="-46.8825"
        map:cameraZoom="13"
    />
    

    Next, the parts of code that I consider pertinent to this question, especially this line of 'MainActivity':

    MarkersFragment mFragment = (MarkersFragment) getSupportFragmentManager().findFragmentById(R.id.viewpager);
    

    I tried'findFragmentById 'with R.id.markersMapFragment, R.id.myContainer, but all return null. The only one that returns the object is R.id.viewpager and it works.

    The fragment that shows the list and the + button

    public class RecyclerFragment extends Fragment implements AlertDialog.OnClickListener {
        ...
        ...
        public RecyclerFragment() { 
            this.mCallback = null;
        }
        ...
        ...
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            ...
            ...        
            FloatingActionButton fab = (FloatingActionButton) mInflate.findViewById(R.id.fabAdd);
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // abre o dialogo de inserção de dados
                    dialogInsertRun();
                }
            });
            ...
            ...
        }
    
        public void dialogInsertRun() { // implementa a janela de dialogo de inserção de dados
            ...
            ...
            addRunDialog.setPositiveButton(R.string.button_positive, new DialogInterface.OnClickListener() { // implementa botão <CONFIRMAR>
    
                @Override
                public void onClick(DialogInterface dialog, int id) { // Listener 'padrão'
                    ...
                    ...
                    mCallback.addMarkersToMap(runData); // metodo definido na Activity
                }
                ...
                ...
            }
        }
        ...
        ...
        @Override
        public void onClick(DialogInterface dialogInterface, int i) { 
            Log.d(TAG, "onClick: ");
        }
        ...
        ...
        private OnOkButtonListener mCallback;
        public interface OnOkButtonListener {
            void addMarkersToMap(RunData runData);
        }
        ...
        ...
    }
    

    In the 'activity' that controls the fragments we have

    public class MainActivity extends FragmentActivity implements RecyclerFragment.OnOkButtonListener{
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // replace the splash theme with app theme
            setTheme(R.style.AppTheme);
            // finish is overdue
            checkDateLimit();
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.activity_main);
    
            ScreenUtility utility = new ScreenUtility(this);
            if (utility.getWidth() < 500.0) {
                // Get the ViewPager and set it's PagerAdapter so that it can display items
                ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
                viewPager.setAdapter(new TabsPagerAdapter(getSupportFragmentManager(), getApplicationContext()));
    
                // Give the TabLayout the ViewPager
                TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
                tabLayout.setupWithViewPager(viewPager);
            }
        }
    
        ...
        ...
        public void addMarkersToMap(RunData runData) {
            if (runData != null) {
                MarkersFragment mFragment = (MarkersFragment) getSupportFragmentManager().findFragmentById(R.id.viewpager);
    
                mFragment.addSingleMarker(runData); 
        }
    }
    

    And in the fragment that controls the map

    public class MarkersFragment extends Fragment {
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            setUpMapIfNeeded(); 
        }
        private void setUpMapIfNeeded() { 
            // Do a null check to confirm that we have not already instantiated the map.
            if (markersMapFragment == null) {
                markersMapFragment = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.markersMapFragment));
                // Check if we were successful in obtaining the map.
                if (markersMapFragment != null) {
                    markersMapFragment.getMapAsync(new OnMapReadyCallback() {
                        @Override
                        public void onMapReady(GoogleMap mGoogleMap) {
                            if (mGoogleMap != null) {
                                ...
                                ...
                                LatLng tLatLng, mLatLng;
                                mLatLng = new LatLng(-23.5492, -46.6336);
                                // iterates through the runList as instance of RunData
                                for (RunData runData : runList) { 
                                    tLatLng = addMarkers(runData.collect_lat, runData.collect_lng, runData.collect_address, runData.collect_person, runData.delivery_lat, runData.delivery_lng, runData.delivery_address, runData.delivery_person, runData.run_parcel, mGoogleMap);
                                    ...
                                    ...                               
                                }
                                // Show the current location in Google Map
                                mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(mLatLng));
                                // Zoom in the Google Map
                                mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(13));
                                ...
                                ...
                            }
                        }
                    });
                }
            }
        }
    
        // metodo que adiciona os marcadores.
        public LatLng addMarkers(String collectLat, String collectLng, String collectAddress, String collectPerson,
                                 String deliveryLat, String deliveryLng, String deliveryAddress, String deliveryPerson,
                                 String parcel, GoogleMap googleMap) {
            LatLng cLatLng, dLatLng;
            String mSnippet;
            // add collect marker
            if ((collectLat != null & collectLng != null) && (collectLat.length() > 0 & collectLng.length() > 0)) {
                ...
                ...
                googleMap.addMarker(new MarkerOptions()
                        .position(cLatLng)
                        .icon(collectMarker)
                        .title(collectAddress)
                        .draggable(false)
                        .snippet(mSnippet)
                );
            } 
    
            // add delivery marker
            if ((deliveryLat != null & deliveryLng != null) && (deliveryLat.length() > 0 & deliveryLng.length() > 0)) {
                ...
                ...
                googleMap.addMarker(new MarkerOptions()
                        .position(dLatLng)
                        .icon(deliveryMarker)
                        .title(deliveryAddress)
                        .draggable(false)
                        .snippet(mSnippet)
                );
            }
            // retorna LatLng ou null
            if (cLatLng != null) {
                return cLatLng;
            } else if (dLatLng != null) {
                return dLatLng;
            } else {
                return null;
            }
        }
    
        // metodo que adiciona os marcadores de coleta e entrega de um unico registro
        // executado pela atividade controladora
        public void addSingleMarker(RunData runData) {
            final String collectLat = runData.collect_lat;
            final String collectLng = runData.collect_lng;
            ...
            ...
    
            if (markersMapFragment == null) {
                markersMapFragment = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.markersMapFragment));
                // Check if we were successful in obtaining the map.
                if (markersMapFragment != null) {
                    markersMapFragment.getMapAsync(new OnMapReadyCallback() {
                        @Override
                        public void onMapReady(GoogleMap mGoogleMap) {
                            LatLng mLatLng;
                            mLatLng = new LatLng(-23.5492, -46.6336);
                            if (mGoogleMap != null) {
                                mLatLng = addMarkers(collectLat, collectLng, collectAddress, collectPerson, deliveryLat, deliveryLng, deliveryAddress, deliveryPerson, parcel, mGoogleMap);
                                mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(mLatLng));
                                mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(13));
                            }
                        }
                    });
                }
            } else {
                if (markersMapFragment != null) {
                    markersMapFragment.getMapAsync(new OnMapReadyCallback() {
                        @Override
                        public void onMapReady(GoogleMap mGoogleMap) {
                            LatLng mLatLng;
                            mLatLng = new LatLng(-23.5492, -46.6336);
                            if (mGoogleMap != null) {
                                mLatLng = addMarkers(collectLat, collectLng, collectAddress, collectPerson, deliveryLat, deliveryLng, deliveryAddress, deliveryPerson, parcel, mGoogleMap);
                                mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(mLatLng));
                                mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(13));
                            }
                        }
                    });
                }
            }
        }
    }
    

    I highlight the line again

    MarkersFragment mFragment = (MarkersFragment) getSupportFragmentManager().findFragmentById(R.id.viewpager);
    

    It works vertically because the view R.id.viewpager is instantiated, and like I said the other views return null

    Given the above code, could you guide me how to reference the most appropriate view?

    (If you think you have too much code, feel free to eliminate any excess.)

        
    asked by anonymous 08.01.2017 / 18:31

    3 answers

    2

    How to resolve this depends on how you have structured your code.

    One of the approaches used is to manage the two Fragments, acting as an intermediary between them.

    So when a Fragment wants an action to be executed in another Fragment, the first one asks Activity to report the second of that intention.

    In this case the Dialog Fragment calls an Activity method, passing on the necessary information, so that it calls a Map Fragment method to add the Marker.

    See How to pass the EditText value of a Fragment to the TextView of another Fragment? and Changing Fragment components through an Activity how similar situations have been resolved.

        
    09.01.2017 / 18:33
    1

    Given the minimum of details provided in your question, I'll try below to show you how it would be the basics of Google Maps API . See below for a simple class in which it is marked with a point defining latitude and latitude using Bookmarks > :

    public class MapPane extends Activity implements OnMapReadyCallback {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.map_activity);
    
            MapFragment mapFragment = (MapFragment) getFragmentManager()
                    .findFragmentById(R.id.map);
            mapFragment.getMapAsync(this);
        }
    
        @Override
        public void onMapReady(GoogleMap map) {
            map.moveCamera(CameraUpdateFactory.newLatLngZoom(
                    new LatLng(41.889, -87.622), 16));
    
            // You can customize the marker image using images bundled with
            // your app, or dynamically generated bitmaps.
            map.addMarker(new MarkerOptions()
                    .icon(BitmapDescriptorFactory.fromResource(R.drawable.house_flag))
                    .anchor(0.0f, 1.0f) // Anchors the marker on the bottom left
                    .position(new LatLng(41.889, -87.622)));
        }
    }
    
      

    How do I insert bookmarks on the map when I insert a new one   task?

    By the time you enter this new task, you simply insert a new label like this:

    map.addMarker(new MarkerOptions().icon(BitmapDescriptorFactory.
    fromResource(R.drawable.house_flag))
                        .anchor(0.0f, 1.0f) 
                        .position(new LatLng(41.889, -87.622)));
    

    Below is an additional in which you can do a test by clicking anywhere on the map to add a marker according to the coordinate. See:

    map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
    
                    @Override
                    public void onMapClick(LatLng point) {
    
                        MarkerOptions marker = new MarkerOptions().position(
                                new LatLng(point.latitude, point.longitude)).title("New Marker");
    
                        googleMap.addMarker(marker);
    
                    System.out.println(point.latitude+"---"+ point.longitude);  
                    }
                });
    

    For more details, just follow the documentation on the Android website.

        
    08.01.2017 / 20:58
    1

    I ended up finding a solution to 'find' the correct element in the map fragment and insert the markers. The interface method:

    public void addMarkersToMap(RunData runData) {
        if (runData != null) {
            MarkersFragment mFragment = (MarkersFragment) getSupportFragmentManager().findFragmentById(R.id.viewpager);
    
            mFragment.addSingleMarker(runData); 
    }
    

    looks like this:

    public void addMarkersToMap(RunData runData) {
        if (runData != null) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            MarkersFragment mFragment;
    
            if(getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE) {
                mFragment = (MarkersFragment) fragmentManager.findFragmentById(R.id.markersMapPanel);
            } else if(getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT){
                mFragment = (MarkersFragment) fragmentManager.findFragmentById(R.id.viewpager);
            }
    
            if (mFragment != null) {
                mFragment.addSingleMarker(runData);
            }
    
        }
    }
    
        
    11.01.2017 / 00:00