I am trying to add small maps to a list and have created a Cursor adapter to handle a list of locations.
The layout for the individual location looks like this:
<LinearLayout
... >
<TextView android:id="#+id/start_loc"
...
/>
<fragment android:id="#+id/start_loc_map"
android:name="com.google.android.gms.maps.MapFragment"
...
/>
</LinearLayout>
Then in the adapter:
#Override
public void bindView(View view, Context context, Cursor cursor) {
startLocView = (TextView) view.findViewById(R.id.start_loc);
then something like:
SupportMapFragment startLocMap =
(SupportMapFragment) view.findViewById(R.id.start_loc_map);
or:
SupportMapFragment startLocMap =
(SupportMapFragment) getChildFragmentManager()
.findFragmentById(R.id.start_loc_map);
Neither of these works. The view (not surprisingly) can't be cast as a fragment and there is no fragment or activity available to the adapter. I can get a Context and (Activity) context.getFragmentManager but I can't find any way to get to getChildFragmentManager from that. I can get a FrameLayout, which is what the container object is but I don't know any way to reference to the Fragment contained therein.
How do I get a reference to a static (?) fragment in a layout from an adapter? Is getting a <fragment> less straightforward than a <TextView>?
There would be a lot of work to display map in the list view using cursor adapter. The other problem that you shall be facing is the degraded performance and frequent app crash. Direct use of the mapView in a listView is a heavy operation. This is going to cause a delay and result will be sluggish User Experience of your app. To avoid this behavior you have an alternative to use Static maps. This will enable Lazy Loading of maps in your list view and therby user wont have to tap map now and then. If you are not providing current location of the user on the map litview Static maps are the best option.
I am providing a small example below that use this method. First create a list view from the data (Either API or DB). Then pass data such as latitude and longitude to a string with some static variables defined as follows.
String getMapURL = "http://maps.googleapis.com/maps/api/staticmap?zoom=12&size=360x180&markers=size:mid|color:green|"
+ JOLocation.getString("latitude")
+ ","
+ JOLocation.getString("longitude")
+ "&sensor=false";
The above constructed URL, when used in a browser, returns a .PNG file. Then, in my adapter for the activity, This method results in the lazy loading of the maps in the app where your marker displaying the coordinates are fetched at runtime, avoiding heavy work in the code.
Hope this would help!!!
Related
I have one fragment in which I'm generating an ArrayList. After the ArrayList is generated, I'm sending it to the Activity using interface
Inside my fragment-
public interface sendTheArraylist{
void ArrayList(ArrayList<Song> songArrayList);
}
And in the MainActivity-
#Override
public void accessArrayList(ArrayList<Song> songArrayList) {
this.queueArrayList=songArrayList;
queueAdapter =new SongAdapter(this,queueArrayList);
....
}
However, I see that whenever any changes are made in the queueArrayList in MainActivity, the songArrayList in the fragment is also getting affected. How can I stop the ArrayList in the Fragment from getting changed?
Try with the following.
this.queueArrayList.clear();
this.queueArrayList.addAll(songArrayList);
The reason is that you are referencing the arraylist to queueArrayList directly which also reflects changes back in songArrayList
Using an interface you pass the reference of that list so whenever you change that list will also affect on fragment list too. so the solution is rather than pass a reference to that list create one new list and make copy of it.
You can try and give a look at the Collections.copy method:
public static void copy(List dest, List src)
Copies all of the elements from one list into another. After the operation, the index of each copied element in the destination list will be identical to its index in the source list. The destination list must be at least as long as the source list. If it is longer, the remaining elements in the destination list are unaffected. This method runs in linear time.
Parameters: dest - The destination list. src - The source list.
hope it will help you.
Here is the complete solution:
before calling sendTheArraylist Inside your fragment-
ArrayList<Song> songArrayListToPass= new ArrayList<Song>(songArrayList.size());
Collections.copy(songArrayListToPass, songArrayList);
YourActivityRef.sendTheArraylist(songArrayListToPass);
This way your any update on your songArrayListToPass inside Activity will not reflect in Fragment.
I have a Google's NavigationDrawer which adds/replaces fragments. One of fragments has a listView filled with custom BaseAdapter by network request (asyncTask, takes times). What i want is to save listView contents somewhere so if user navigates to another fragment through navigationDrawer and then or later navigates back to the fragment containing listView - i want a listView to be populated immediately with saved old content before asyncTask finished loading new content. Minimum API is 10.
What did i try.
onSaveInstanceState - serialize Parcelable ArrayList<CustomObject>. Somehow i didn't get it working. Also, that isn't solving my problem however, because onSaveInstaceState doesn't triggers on navigating through navigationDrawer.
Setting new fragment's InitialState(setInitialSavedState) then saving(saveFragmentInstanceSate)/loading it. That works for simple Views like EditTexts and TextView, but didn't get it working for the listView.
What is a best way to save listView contents? Please help me.
First get all items of list view.
CustomListViewAdapter listadapter = (CustomListViewAdapter) listview.getAdapter();
ArrayList<CustomObject> object=new ArrayList<CustomObject>();
for(int position=0;position<listadapter.getCount();position++)
object.add(videoadapter.getItem(position));
Now Use the object to store the items of the listview
Then use shared preferences to save the object.
Android ArrayList of custom objects - Save to SharedPreferences - Serializable?
The proper way to do this is to save your network query results in a database (sqlite), and use data from that db to display items in your list (CursorAdapter works best for this).
These tutorials nicely explain how to make your own Content Provider using Sqlite, and use a CursorAdapter to display your data on a list.
http://docs.xamarin.com/guides/android/user_interface/working_with_listviews_and_adapters/part_4_-_using_cursoradapters/
http://www.vogella.com/tutorials/AndroidSQLite/article.html
I found a good way.
String list_items = ""; // all your items are here, but separate it with a comma (,)
String[] list = list_items.separate(",");
And save the list_items in a shared preference. To retrieve just use getString() and use the code above
Objective- I want to show slide shows of different Map Activities which show data according to database, using view flipper(or something similar).
Issues:
View Flipper can't be added to an Activity that is not a MapActivity if flipper contains a mapview.
View Flipper does not allows adding multiple mapviews as one MapActivity can have only one map view.
What I wish to implement
Want to show slide show of multiple MapActivities which show markers,route etc based on database data.
Want to refresh these MapActivities also new data is fetched periodically and database is updated.
I'am unable to find a solution to my problem. I have gone through the following links but they provided no relevant solution:
How can i Implement SlideShow in android?
Can a MapView be placed inside a ViewFlipper somehow?
Please help and suggest what is the best approach for this problem.
Thanks!
I did not find standard solution to my problem as view flipper could not be used.I did the following to implement mapview slide show. Its more of a hack than a proper solution but I had no choice.
In a while loop, I kept re-rendering the same map view in the async map task.
2.After 1st map is loaded I called thread.sleep(10000).
3.I cleared the mapview of all routes and markers.
4.I re rendered the 2nd map view.
5.And the steps were repeated continuously.
#Override
protected Void doInBackground(Void... params) {
final Drawable marker_inBetween;
marker_inBetween = getResources().getDrawable(R.drawable.blue_pin);
marker_inBetween.setBounds(0, 0,
marker_inBetween.getIntrinsicWidth(),
marker_inBetween.getIntrinsicHeight());
helper = new DbHelper(getApplicationContext());
// show slide show
while (true) {
ArrayList<String> IdList =showAllPeopleOnMap();
util.haveASleep(slideShowInterval);
showEachPersonRouteOnMap(IdList);
resetVariables();//resets lists,routes,removes markers etc
}
}
return null;
}
Thanks.
I've got an Activity that holds a ListFragment on the left and a SupportMapFragment on the right.
List and Map are both backed by the same data. The visual representation of the data on the Map are Markers.
I want to be able to perform a click on either a list item or a Marker and get the corresponding item in the other visual representation.
Restrictions of the framework and my data are:
The Marker class is final and the Marker's id does not have a modificator. This is why I can't use the easiest possible way.
"It's important to not hold on to objects (e.g. Marker) beyond the
view's life. Otherwise it will cause a memory leak as the view cannot
be released." (see SupportMapFragment)
Titles of Markers can occur multiple times. This is why the expensive String comparison is not a way I can go.
Does anyone have a working solution for this issue or can provide a nudge in the right direction?
If you want to be able to register to clicks on a Marker, you'll need to override the InfoWindowAdapter.
You can provide unique information to the title and snippet of a Marker and implement the interface's methods in this style:
#Override
public View getInfoWindow(Marker marker) {
// do nothing here in order to obtain the original info window border.
return null;
}
#Override
public View getInfoContents(Marker marker) {
// Create your own view here. Obtain the unique information stored
// in title / snippet of the current marker.
return createdView;
}
Now you can set the OnInfoWindowClickListener and work with the unique information stored there.
Here's another option. The latest APIs provide an OnMarkerClickListener interface.
https://developers.google.com/maps/documentation/android/marker#marker_click_events
I am trying to take advantage of an InfoWindowAdapter to provide custom content for the InfoView. I'm pulling down a JSONArray from my web service and adding the Markers but I'm not seeing how to pass the detail to the call back via a Marker.
#Override
public View getInfoWindow(Marker marker)
In the Javascript API I was able to just set arbitrary marker info. I want to be able to pass info that can be used as conditionals for the custom content, example a marker.status string. So something other than title etc. The view will need a number of custom fields I need to pass in.
perhaps try adding your info or object to the marker as explained here:
http://bon-app-etit.blogspot.be/2012/12/add-informationobject-to-marker-in.html
Edit: I also made a post that continues the previous to use the InfoWindowAdapter.
Check it out here!