Google Maps API v2 SupportMapFragment inside ScrollView - users cannot scroll the map vertically
Apply a transparent image over the mapview fragment.
<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>
Then set requestDisallowInterceptTouchEvent(true)
for the main ScrollView. When the user touches the transparent image and moves disable the touch on the transparent image for MotionEvent.ACTION_DOWN
and MotionEvent.ACTION_MOVE
so that map fragment can take Touch Events.
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;
}
}
});
This worked for me. Hope it helps you..
Map inside scrollview not scrollable
you can scroll google map inside scrollview.
see below link i describe how to scroll map inside scrollview in android:
http://newtech4you4ever.blogspot.in/2016/08/scroll-googlemap-in-scrollview-android.html
how to set google map fragment inside scroll view
Create a custom SupportMapFragment
so that we can override its touch event:
WorkaroundMapFragment.java
import android.content.Context;
import android.os.Bundle;
import android.widget.FrameLayout;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.gms.maps.SupportMapFragment;
public class WorkaroundMapFragment extends SupportMapFragment {
private OnTouchListener mListener;
@Override
public View onCreateView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle savedInstance) {
View layout = super.onCreateView(layoutInflater, viewGroup, savedInstance);
TouchableWrapper frameLayout = new TouchableWrapper(getActivity());
frameLayout.setBackgroundColor(getResources().getColor(android.R.color.transparent));
((ViewGroup) layout).addView(frameLayout,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return layout;
}
public void setListener(OnTouchListener listener) {
mListener = listener;
}
public interface OnTouchListener {
public abstract void onTouch();
}
public class TouchableWrapper extends FrameLayout {
public TouchableWrapper(Context context) {
super(context);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mListener.onTouch();
break;
case MotionEvent.ACTION_UP:
mListener.onTouch();
break;
}
return super.dispatchTouchEvent(event);
}
}
}
In this above class, we intercept the touch event by using TouchableWrapper.class
that extends the FrameLayout
. There is also a custom listener OnTouchListener
to dispatch the touch event to the main activity named MyMapActivity
that handles the map. When the touch event occurred, dispatchTouchEvent
will be called and the listener mListener
will handle it.
Then replace fragment class in xml with this class="packagename.WorkaroundMapFragment"
instead of com.google.android.gms.maps.SupportMapFragment
Then in your activity initialize map as follows:
private GoogleMap mMap;
inside onCreate do this:
// check if we have got the googleMap already
if (mMap == null) {
SupportMapFragment mapFragment = (WorkaroundMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(new OnMapReadyCallback() {
Override
public void onMapReady(GoogleMap googleMap)
{
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mMap.getUiSettings().setZoomControlsEnabled(true);
mScrollView = findViewById(R.id.scrollMap); //parent scrollview in xml, give your scrollview id value
((WorkaroundMapFragment) getChildFragmentManager().findFragmentById(R.id.map))
.setListener(new WorkaroundMapFragment.OnTouchListener() {
@Override
public void onTouch()
{
mScrollView.requestDisallowInterceptTouchEvent(true);
}
});
}
});
}
Update: Answer updated to getMapAsync()
based on answer by @javacoder123
How to make Google Maps scroll properly inside Scroll View?
You can add a transparent ImageView that fits the mapFragment:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imagetrans"
android:layout_alignTop="@+id/mapfragment"
android:layout_alignBottom="@+id/mapfragment"
android:layout_alignEnd="@+id/mapfragment"
android:layout_alignRight="@+id/mapfragment"
android:layout_alignLeft="@+id/mapfragment"
android:layout_alignStart="@+id/mapfragment"
android:src="@color/transparent"/>
And then, when the user is touching it, disallow the scrollView:
final ScrollView scroll = (ScrollView) findViewById(R.id.scroll);
ImageView transparent = (ImageView)findViewById(R.id.imagetrans);
transparent.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.
scroll.requestDisallowInterceptTouchEvent(true);
// Disable touch on transparent view
return false;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
scroll.requestDisallowInterceptTouchEvent(false);
return true;
case MotionEvent.ACTION_MOVE:
scroll.requestDisallowInterceptTouchEvent(true);
return false;
default:
return true;
}
}
});
This way, only when the user touches the ImageView, the map will respond to touching events. The rest of the time, the ScrollView will respond.
Android SupportMapFragment for moving Google Map within Scrollview
Face same issue in my app, I resolve this using interception scroll view touch using custom Scrollview
CustomScrollView:
public class CustomScrollView extends ScrollView {
public CustomScrollView(Context context) {
super(context);
}
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
//Log.i("CustomScrollView", "onInterceptTouchEvent: DOWN super false" );
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_MOVE:
return false; // redirect MotionEvents to ourself
case MotionEvent.ACTION_CANCEL:
// Log.i("CustomScrollView", "onInterceptTouchEvent: CANCEL super false" );
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_UP:
//Log.i("CustomScrollView", "onInterceptTouchEvent: UP super false" );
return false;
default:
//Log.i("CustomScrollView", "onInterceptTouchEvent: " + action );
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
//Log.i("CustomScrollView", "onTouchEvent. action: " + ev.getAction() );
return true;
}
}
MapFragment in ScrollView
Applying a transparent image over the mapview fragment seems to resolve the issue. It's not the prettiest, but it seems to work. Here's an XML snippet that shows this:
<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>
ScrollView is catching touch event for google map
It seems you on the right way, but you should call requestDisallowInterceptTouchEvent(true) method on every touch event (see docs). Try this solution
Updated:
Try this out:
final HorizontalScrollView hsv = ...
final MapView mapView = ...
mapView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
hsv.requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
hsv.requestDisallowInterceptTouchEvent(false);
break;
}
return mapView.onTouchEvent(event);
}
});
Related Topics
How to Get App's Permission for Each App? How to Do It Programmatically on Android
Android Contacts Display Name and Phone Number(S) in Single Database Query
How to Set "Android:Layout_Below" at Runtime Programmatically
Spannablestringbuilder to Create String with Multiple Fonts/Text Sizes etc Example
Problem to Achieve Curved Animation
Search in Listview with Edittext
Android Google Maps, How to Make Each Marker Infowindow Open Different Activity
Why a New Viewmodel Is Created in Each Compose Navigation Route
How to Call a Function After Delay in Kotlin
Expand/Collapse Lollipop Toolbar Animation (Telegram App)
Autoincrement Versioncode with Gradle Extra Properties
When to Use a Content Provider
How to Secure Android Shared Preferences
List of Files in Assets Folder and Its Subfolders
How to Automatically Restart a Service Even If User Force Close It
Listview in Arrayadapter Order Get's Mixed Up When Scrolling