Android – MapView, содержащийся в Listview

В настоящее время я пытаюсь разместить MapView в ListView. Кто-нибудь имел успех в этом? Возможно ли это? Вот мой код:

ListView myList = (ListView) findViewById(android.R.id.list); List<Map<String, Object>> groupData = new ArrayList<Map<String, Object>>(); Map<String, Object> curGroupMap = new HashMap<String, Object>(); groupData.add(curGroupMap); curGroupMap.put("ICON", R.drawable.back_icon); curGroupMap.put("NAME","Go Back"); curGroupMap.put("VALUE","By clicking here"); Iterator it = data.entrySet().iterator(); while (it.hasNext()) { //Get the key name and value for it Map.Entry pair = (Map.Entry)it.next(); String keyName = (String) pair.getKey(); String value = pair.getValue().toString(); if (value != null) { //Add the parents -- aka main categories curGroupMap = new HashMap<String, Object>(); groupData.add(curGroupMap); //Push the correct Icon if (keyName.equalsIgnoreCase("Phone")) curGroupMap.put("ICON", R.drawable.phone_icon); else if (keyName.equalsIgnoreCase("Housing")) curGroupMap.put("ICON", R.drawable.house_icon); else if (keyName.equalsIgnoreCase("Website")) curGroupMap.put("ICON", R.drawable.web_icon); else if (keyName.equalsIgnoreCase("Area Snapshot")) curGroupMap.put("ICON", R.drawable.camera_icon); else if (keyName.equalsIgnoreCase("Overview")) curGroupMap.put("ICON", R.drawable.overview_icon); else if (keyName.equalsIgnoreCase("Location")) curGroupMap.put("ICON", R.drawable.map_icon); else curGroupMap.put("ICON", R.drawable.icon); //Pop on the Name and Value curGroupMap.put("NAME", keyName); curGroupMap.put("VALUE", value); } } curGroupMap = new HashMap<String, Object>(); groupData.add(curGroupMap); curGroupMap.put("ICON", R.drawable.back_icon); curGroupMap.put("NAME","Go Back"); curGroupMap.put("VALUE","By clicking here"); //Set up adapter mAdapter = new SimpleAdapter( mContext, groupData, R.layout.exp_list_parent, new String[] { "ICON", "NAME", "VALUE" }, new int[] { R.id.photoAlbumImg, R.id.rowText1, R.id.rowText2 } ); myList.setAdapter(mAdapter); //Bind the adapter to the list 

Заранее спасибо за вашу помощь!!

Solutions Collecting From Web of "Android – MapView, содержащийся в Listview"

В этом случае вы добавили MapView в список так же, как и любое другое представление. Вот краткое руководство по созданию адаптера пользовательского списка. Но я должен предупредить вас, MapView – довольно тяжелый вид, и если вы попытаетесь получить кучу их на экране, вы заметите, что приложение вяло! Вы можете просто добавить кнопку в элемент списка, который переводит пользователя на другую страницу с дополнительной информацией, включая карту.

Чтобы отправить альтернативное решение на довольно старый ответ (более 2 лет на самом деле), но я думал, что это может помочь кому-то, кто может наткнуться на этот пост, как я.

ПРИМЕЧАНИЕ. Это может быть полезно для тех, кому просто нужно отобразить местоположение в «Карте», но не нужно взаимодействовать с ним в ListView . Фактическая карта может отображаться на странице сведений , после нажатия на элемент в ListView

Как уже отмечалось в @CaseyB, MapView выглядит довольно тяжелым. Чтобы противостоять этому аспекту (и сделать жизнь немного легче, но проще для меня ;-)), я решил создать такой URL, как вы бы, для статической карты Google, используя несколько параметров, необходимых для моего приложения. Здесь вы можете получить больше опций: https://developers.google.com/maps/documentation/staticmaps/

Во-первых, когда я создаю данные для своего ListView , я передаю данные, такие как широта и долгота, в строку с некоторыми статическими переменными, взятыми из ссылки, упомянутой выше. Я получаю свои координаты от API Facebook.

Код, который я использую для построения ссылки:

 String getMapURL = "http://maps.googleapis.com/maps/api/staticmap?zoom=18&size=560x240&markers=size:mid|color:red|" + JOLocation.getString("latitude") + "," + JOLocation.getString("longitude") + "&sensor=false"; 

Вышеприведенный URL-адрес, используемый в браузере, возвращает файл .PNG . Затем, в моем adapter для активности, я использую Lazy Loading @ Fedor для отображения изображения, сгенерированного из URL, ранее описанного для отображения в пользовательском ListView . Вы можете, конечно, выбрать свой собственный метод для отображения этой Map (на самом деле карты).

Пример конечного результата.

Введите описание изображения здесь

В настоящее время у меня около 30 нечетных карт Checkin (я использую его совместно с SDK для Facebook) в этом ListView , но пользователи могут иметь 100 из них, и нет никаких сообщений об этом замедлении.

Я подозреваю, что это не поможет OP, учитывая время, прошедшее с момента вопроса, но надеюсь, что это поможет другим пользователям, приземляющимся на этой странице в будущем.

Во-первых, я не думаю, что одновременное отображение нескольких MapViews будет работать. Документы MapActivity, поддерживаемые только одним процессом:

«Только один MapActivity поддерживается для каждого процесса. Несколько одновременных действий MapActivities могут влиять на неожиданные и нежелательные способы».

( http://code.google.com/android/add-ons/google-apis/reference/index.html )

В нем явно не указано, что вы не можете иметь несколько MapView в MapActivity, но я думаю, что они тоже будут вмешиваться, независимо от того, в какой родительской ViewGroup они находятся.

Во-вторых, вы можете использовать API статических карт, чтобы получить простой образ для включения в ListView. Полноценный MapView может быть излишне тяжелым в любом случае:

http://code.google.com/apis/maps/documentation/staticmaps/

Единственная проблема, с которой вы можете столкнуться, заключается в том, что API статических карт ограничивает использование «пользователем», что, вероятно, означает IP (для этого не требуется ключ API), а мобильные сети могут быть проблематичными при ограничении использования IP-адресов. Я точно не знаю, как это получится.

Это возможно, из самого кода GoogleMapSample:

 /** * This shows to include a map in lite mode in a ListView. * Note the use of the view holder pattern with the * {@link com.google.android.gms.maps.OnMapReadyCallback}. */ public class LiteListDemoActivity extends AppCompatActivity { private ListFragment mList; private MapAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.lite_list_demo); // Set a custom list adapter for a list of locations mAdapter = new MapAdapter(this, LIST_LOCATIONS); mList = (ListFragment) getSupportFragmentManager().findFragmentById(R.id.list); mList.setListAdapter(mAdapter); // Set a RecyclerListener to clean up MapView from ListView AbsListView lv = mList.getListView(); lv.setRecyclerListener(mRecycleListener); } /** * Adapter that displays a title and {@link com.google.android.gms.maps.MapView} for each item. * The layout is defined in <code>lite_list_demo_row.xml</code>. It contains a MapView * that is programatically initialised in * {@link #getView(int, android.view.View, android.view.ViewGroup)} */ private class MapAdapter extends ArrayAdapter<NamedLocation> { private final HashSet<MapView> mMaps = new HashSet<MapView>(); public MapAdapter(Context context, NamedLocation[] locations) { super(context, R.layout.lite_list_demo_row, R.id.lite_listrow_text, locations); } @Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; ViewHolder holder; // Check if a view can be reused, otherwise inflate a layout and set up the view holder if (row == null) { // Inflate view from layout file row = getLayoutInflater().inflate(R.layout.lite_list_demo_row, null); // Set up holder and assign it to the View holder = new ViewHolder(); holder.mapView = (MapView) row.findViewById(R.id.lite_listrow_map); holder.title = (TextView) row.findViewById(R.id.lite_listrow_text); // Set holder as tag for row for more efficient access. row.setTag(holder); // Initialise the MapView holder.initializeMapView(); // Keep track of MapView mMaps.add(holder.mapView); } else { // View has already been initialised, get its holder holder = (ViewHolder) row.getTag(); } // Get the NamedLocation for this item and attach it to the MapView NamedLocation item = getItem(position); holder.mapView.setTag(item); // Ensure the map has been initialised by the on map ready callback in ViewHolder. // If it is not ready yet, it will be initialised with the NamedLocation set as its tag // when the callback is received. if (holder.map != null) { // The map is already ready to be used setMapLocation(holder.map, item); } // Set the text label for this item holder.title.setText(item.name); return row; } /** * Retuns the set of all initialised {@link MapView} objects. * * @return All MapViews that have been initialised programmatically by this adapter */ public HashSet<MapView> getMaps() { return mMaps; } } /** * Displays a {@link LiteListDemoActivity.NamedLocation} on a * {@link com.google.android.gms.maps.GoogleMap}. * Adds a marker and centers the camera on the NamedLocation with the normal map type. */ private static void setMapLocation(GoogleMap map, NamedLocation data) { // Add a marker for this item and set the camera map.moveCamera(CameraUpdateFactory.newLatLngZoom(data.location, 13f)); map.addMarker(new MarkerOptions().position(data.location)); // Set the map type back to normal. map.setMapType(GoogleMap.MAP_TYPE_NORMAL); } /** * Holder for Views used in the {@link LiteListDemoActivity.MapAdapter}. * Once the the <code>map</code> field is set, otherwise it is null. * When the {@link #onMapReady(com.google.android.gms.maps.GoogleMap)} callback is received and * the {@link com.google.android.gms.maps.GoogleMap} is ready, it stored in the {@link #map} * field. The map is then initialised with the NamedLocation that is stored as the tag of the * MapView. This ensures that the map is initialised with the latest data that it should * display. */ class ViewHolder implements OnMapReadyCallback { MapView mapView; TextView title; GoogleMap map; @Override public void onMapReady(GoogleMap googleMap) { MapsInitializer.initialize(getApplicationContext()); map = googleMap; NamedLocation data = (NamedLocation) mapView.getTag(); if (data != null) { setMapLocation(map, data); } } /** * Initialises the MapView by calling its lifecycle methods. */ public void initializeMapView() { if (mapView != null) { // Initialise the MapView mapView.onCreate(null); // Set the map ready callback to receive the GoogleMap object mapView.getMapAsync(this); } } } /** * RecycleListener that completely clears the {@link com.google.android.gms.maps.GoogleMap} * attached to a row in the ListView. * Sets the map type to {@link com.google.android.gms.maps.GoogleMap#MAP_TYPE_NONE} and clears * the map. */ private AbsListView.RecyclerListener mRecycleListener = new AbsListView.RecyclerListener() { @Override public void onMovedToScrapHeap(View view) { ViewHolder holder = (ViewHolder) view.getTag(); if (holder != null && holder.map != null) { // Clear the map and free up resources by changing the map type to none holder.map.clear(); holder.map.setMapType(GoogleMap.MAP_TYPE_NONE); } } }; /** * Location represented by a position ({@link com.google.android.gms.maps.model.LatLng} and a * name ({@link java.lang.String}). */ private static class NamedLocation { public final String name; public final LatLng location; NamedLocation(String name, LatLng location) { this.name = name; this.location = location; } } } 

Полный код доступен по адресу: https://github.com/googlemaps/android-samples/blob/master/ApiDemos/app/src/main/java/com/example/mapdemo/LiteListDemoActivity.java

Я столкнулся с той же проблемой сегодня – оказывается, что вам нужно создать MapView внутри вашей MapActivity, иначе вы получите сообщение об ошибке, например Unable to Inflate View. Com.google.maps.MapView или так … Чем передать этот MapView в ваш ListAdapter И выплюнуть его, когда это необходимо. Мне пришлось поместить MapView внутри RelativeLayout, чтобы отрегулировать высоту и ширину, как я хочу (по какой-то причине MapView не ведет себя «обычным» способом просмотра). Вы можете спросить меня, если хотите: