MapFragment в ScrollView

У меня есть один из новых MapFragment s в ScrollView . На самом деле это SupportMapFragment , но в любом случае. Он работает, но есть две проблемы:

  1. При прокрутке он оставляет черную маску. Черные покрывают именно ту область, где была карта, за исключением отверстия, где были кнопки +/- масштабирования. См. Снимок экрана ниже. Это на Android 4.0.

  2. Представление не использует requestDisallowInterceptTouchEvent() когда пользователь взаимодействует с картой, чтобы предотвратить перехватывание ScrollView , поэтому, если вы попытаетесь панорамировать вертикально на карте, он просто прокручивает содержащее ScrollView . Теоретически я мог бы получить класс MapView вида и добавить эту функциональность, но как я могу заставить MapFragment использовать свой настраиваемый MapView вместо стандартного?

Частичный снимок экрана прокрутки

Solutions Collecting From Web of "MapFragment в ScrollView"

Применение прозрачного изображения над фрагментом mapview, похоже, решает проблему. Это не самый красивый, но, похоже, он работает. Вот фрагмент XML, который показывает это:

 <RelativeLayout android:id="@+id/relativeLayout1" android:layout_width="match_parent" android:layout_height="300dp" > <fragment android:id="@+id/map" android:name="com.google.android.gms.maps.MapFragment" android:layout_width="fill_parent" android:layout_height="fill_parent"/> <ImageView android:id="@+id/imageView123" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/temp_transparent" /> </RelativeLayout> 

Для меня добавление прозрачного ImageView не помогло полностью удалить черную маску. Верхняя и нижняя части карты по-прежнему отображали черную маску во время прокрутки.

Поэтому решение для этого я нашел в этом ответе с небольшим изменением. Я добавил,

 android:layout_marginTop="-100dp" android:layout_marginBottom="-100dp" 

К моему фрагменту карты, так как он был вертикальным scrollview. Поэтому мой макет теперь выглядел так:

 <RelativeLayout android:id="@+id/map_layout" android:layout_width="match_parent" android:layout_height="300dp"> <fragment android:id="@+id/mapview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="-100dp" android:layout_marginBottom="-100dp" android:name="com.google.android.gms.maps.MapFragment"/> <ImageView android:id="@+id/transparent_image" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@color/transparent" /> </RelativeLayout> 

Чтобы решить вторую часть вопроса, я задал requestDisallowInterceptTouchEvent(true) для моего основного ScrollView. Когда пользователь коснулся прозрачного изображения и переместился, я отключил касание прозрачного изображения для MotionEvent.ACTION_DOWN и MotionEvent.ACTION_MOVE чтобы фрагмент карты мог принимать события касания.

 ScrollView mainScrollView = (ScrollView) findViewById(R.id.main_scrollview); ImageView transparentImageView = (ImageView) findViewById(R.id.transparent_image); transparentImageView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: // Disallow ScrollView to intercept touch events. mainScrollView.requestDisallowInterceptTouchEvent(true); // Disable touch on transparent view return false; case MotionEvent.ACTION_UP: // Allow ScrollView to intercept touch events. mainScrollView.requestDisallowInterceptTouchEvent(false); return true; case MotionEvent.ACTION_MOVE: mainScrollView.requestDisallowInterceptTouchEvent(true); return false; default: return true; } } }); 

Это сработало для меня. Надеюсь, это поможет вам.

Это, вероятно, имеет свои корни в одном и том же месте по причинам проблемы в этом вопросе . Решение заключается в использовании прозрачной рамки, которая немного меньше веса, чем прозрачное изображение.

Сделано после много исследований и разработок:

Fragment_one.xml должен выглядеть так:

 <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/scrollViewParent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="400dip" > <com.google.android.gms.maps.MapView android:id="@+id/mapView" android:layout_width="match_parent" android:layout_height="match_parent" /> <View android:id="@+id/customView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:color/transparent" /> </RelativeLayout> <!-- Your other elements are here --> </LinearLayout> </ScrollView> 

Ваш класс Java FragmentOne.java выглядит так:

 private GoogleMap mMap; private MapView mapView; private UiSettings mUiSettings; private View customView 

onCreateView

 mapView = (MapView) rootView.findViewById(R.id.mapView); mapView.onCreate(savedInstanceState); if (mapView != null) { mMap = mapView.getMap(); mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); mUiSettings = mMap.getUiSettings(); mMap.setMyLocationEnabled(true); mUiSettings.setCompassEnabled(true); mUiSettings.setMyLocationButtonEnabled(false); } scrollViewParent = (ScrollView)rootView.findViewById(R.id.scrollViewParent); customView = (View)rootView.findViewById(R.id.customView); customView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: // Disallow ScrollView to intercept touch events. scrollViewParent.requestDisallowInterceptTouchEvent(true); // Disable touch on transparent view return false; case MotionEvent.ACTION_UP: // Allow ScrollView to intercept touch events. scrollViewParent.requestDisallowInterceptTouchEvent(false); return true; case MotionEvent.ACTION_MOVE: scrollViewParent.requestDisallowInterceptTouchEvent(true); return false; default: return true; } } }); 

Я использовал эти структуры, и я преодолел проблему.

Я использовал контейнерный вид для фрагмента карты.

 <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:text="Another elements in scroll view1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <com.erolsoftware.views.MyMapFragmentContainer android:orientation="vertical" android:layout_width="match_parent" android:layout_height="250dp"> <fragment 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:id="@+id/eventMap" tools:context="com.erolsoftware.eventapp.EventDetails" android:name="com.google.android.gms.maps.SupportMapFragment"/> </com.erolsoftware.views.MyMapFragmentContainer> <TextView android:text="Another elements in scroll view2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </ScrollView> 

Класс контейнера:

 public class MyMapFragmentContainer extends LinearLayout { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { ViewParent p = getParent(); if (p != null) p.requestDisallowInterceptTouchEvent(true); } return false; } public MyMapFragmentContainer(Context context) { super(context); } public MyMapFragmentContainer(Context context, AttributeSet attrs) { super(context, attrs); } public MyMapFragmentContainer(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } } 

Для второй части вопроса – вы можете получить класс фрагмента из SupportMapFragment и использовать его в своем макете. Затем вы можете переопределить Fragment # onCreateView и создать экземпляр своего настраиваемого MapView.

Если это не сработает, вы всегда можете создать свой собственный фрагмент – тогда вам просто нужно позаботиться о вызове всех методов жизненного цикла самостоятельно (onCreate, onResume и т. Д.). Этот ответ содержит более подробную информацию.

 <ScrollView android:layout_width="match_parent" :: :: :: <FrameLayout android:id="@+id/map_add_business_one_rl" android:layout_width="match_parent" android:layout_height="100dp" > <fragment android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="-100dp" android:layout_marginBottom="-100dp" /> </FrameLayout> :: :: :: </ScrollView>