2
I’m developing a app Android where you insert a courier task list (pick something up on the dot A
and bring to the point B
) and these dots are shown on a map.
The App has two fragments:
ReclyclerView
containing the list of tasks.map with markers showing points
A
andB
of each item in therecyclerView
.
When the map is created (or recreated) it takes the coordinates from the database (which also feeds the task list).
The question arises when inserting a new task. The new markers only appear if you force the map to be recreated (by rotating the device or restarting the app).
How do I insert the markers into the map when inserting a new task?
UPDATE: As Ack Lay noted my question needed more details. And how an image is worth a thousand words...
** I’m new here and I can only publish two images... Then it’ll be the last two.
1.When opening the application appears an empty panel in the left half and an empty map on the right.
When you touch the +drop button, you open a form. for the task input. You must be informed: What will be transported, where to pick up with whom ,where to deliver, to whom.
The task data is recorded in the database. Adapter is updated along with recyclerview and the card appears showing the information. The map is still empty.
** Database operations (Sqlite) are performed by a dbHelper class with CRUD methods.
- You need to change the orientation of the device or restart the application for the markers to appear.
That is, markers appear when Fragment is (re)created. What doesn’t work is updating the map, along with recyclerview , when I enter a new task.
The structure of the app.
The main activity is
public class MainActivity extends FragmentActivity
It loads the layout it has is formed by
<?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 class of the task list
public class RecyclerFragment extends Fragment
The class of the map
public class MapFragment extends Fragment
The code is very similar to what you sent, is only more adapted to the app. For example, the pins are fixed. We don’t want them to change when you touch the map. Only updating the card. To avoid course problems.
It seems that there are 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 instance of the map and add the new Marker.
This would be done in The onClick() event from the positiveButton dialog that inflates the form (i.e., when you tap CONFIRM). Or B method dbHelper.Insert()
But there must be other ways.
Someone can give me a light?
UPDATE: In response to @ramaral tips
Implementing the interface worked. There was no need to create a custom system once the button had already been implemented.
But it’s not over yet :-(
When the device is oriented vertically (portrait), it works correctly. However, when it is horizontal (landscape) not yet.
The 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>
Layout of the map fragment
<?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"
/>
Then the code parts that I consider relevant to this issue, especially this Mainactivity line:
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 is the one that 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 again the line
MarkersFragment mFragment = (MarkersFragment) getSupportFragmentManager().findFragmentById(R.id.viewpager);
It works vertically because the R.id.viewpager view is instantiated, and as I said the other views return null
Given the above code, you could guide me how to reference the most appropriate view?
(If you feel you have too much code, feel free to eliminate any excess).
I hope that, with the new details, you see that the correct answer you gave has no relation to the central question.
– Rene Freak
@Renefreak Bookmarks are being added via sqlite?
– viana
No. The database only has one table with the data you see on the card, plus the coordinates. That is, I save the addresses and the lat. and long. both collection and delivery.
– Rene Freak
At the event
onMapReady
I retrieve the table and interact with each record, using the lat/lng to add the marker. If there is no lat. /long. I use the address to try to find them.– Rene Freak