Android SupportMapFragment 用于在 Scrollview 中移动 Google 地图
Android SupportMapFragment for moving Google Map within Scrollview
我想在垂直 ScrollView 中设置一个 Google 地图子片段。为了解决垂直平移不滚动的问题我尝试使用这种方法Google Map Fragment scrolling inside NestedScrollView但是在地图内部移动时scrollview不会停止
这是我的 xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="10dp"
android:fadeScrollbars="false"
android:padding="0dp"
tools:context=".fragments.add.AddFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="0dp">
<TextView
android:id="@+id/textView_text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:ems="10"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<fragment
android:id="@+id/map"
android:name="com.example.myapp.fragments.add.MySupportMapFragment"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView_text1"
app:mapType="normal" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
MySupportMapFragment
import android.R
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import com.google.android.gms.maps.SupportMapFragment
class MySupportMapFragment : SupportMapFragment() {
private var mListener: OnTouchListener? = null
override fun onCreateView(
inflater: LayoutInflater,
parent: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val layout: View? = super.onCreateView(inflater, parent, savedInstanceState)
val frameLayout = TouchableWrapper(activity)
frameLayout.setBackgroundColor(resources.getColor(R.color.transparent))
(layout as ViewGroup?)!!.addView(
frameLayout,
ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
)
return layout
}
fun setListener(listener: OnTouchListener?) {
mListener = listener
}
interface OnTouchListener {
fun onTouch()
}
inner class TouchableWrapper(context: Context?) : FrameLayout(context!!) {
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> mListener!!.onTouch()
MotionEvent.ACTION_UP -> mListener!!.onTouch()
}
return super.dispatchTouchEvent(event)
}
}
}
和我的代码
class AddFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_add, container, false)
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as MySupportMapFragment
mapFragment.getMapAsync(object:OnMapReadyCallback {
override fun onMapReady(googleMap:GoogleMap) {
mMap = googleMap
with(googleMap) {
// We will provide our own zoom controls.
uiSettings.isZoomControlsEnabled = true
uiSettings.isMyLocationButtonEnabled = true
uiSettings.isScrollGesturesEnabled = true
this.mapType = GoogleMap.MAP_TYPE_HYBRID
moveCamera(CameraUpdateFactory.newLatLngZoom(StartPosition, 10f))
}
mMap.setOnCameraIdleListener(object : GoogleMap.OnCameraIdleListener {
override fun onCameraIdle() {
mPositionLatitude = mMap.getCameraPosition().target.latitude
mPositionLongitude = mMap.getCameraPosition().target.longitude
}
})
var mScrollView = view.findViewById(R.id.scroll_view) as ScrollView
mapFragment.setListener(object :
MySupportMapFragment.OnTouchListener {
override fun onTouch() {
mScrollView.parent.requestDisallowInterceptTouchEvent(true)
}
})
}
})
return view
}
}
}
在我的应用程序中遇到同样的问题,我使用自定义滚动视图使用拦截滚动视图触摸解决了这个问题
自定义滚动视图:
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;
}
}
我想在垂直 ScrollView 中设置一个 Google 地图子片段。为了解决垂直平移不滚动的问题我尝试使用这种方法Google Map Fragment scrolling inside NestedScrollView但是在地图内部移动时scrollview不会停止
这是我的 xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="10dp"
android:fadeScrollbars="false"
android:padding="0dp"
tools:context=".fragments.add.AddFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="0dp">
<TextView
android:id="@+id/textView_text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:ems="10"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<fragment
android:id="@+id/map"
android:name="com.example.myapp.fragments.add.MySupportMapFragment"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView_text1"
app:mapType="normal" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
MySupportMapFragment
import android.R
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import com.google.android.gms.maps.SupportMapFragment
class MySupportMapFragment : SupportMapFragment() {
private var mListener: OnTouchListener? = null
override fun onCreateView(
inflater: LayoutInflater,
parent: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val layout: View? = super.onCreateView(inflater, parent, savedInstanceState)
val frameLayout = TouchableWrapper(activity)
frameLayout.setBackgroundColor(resources.getColor(R.color.transparent))
(layout as ViewGroup?)!!.addView(
frameLayout,
ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
)
return layout
}
fun setListener(listener: OnTouchListener?) {
mListener = listener
}
interface OnTouchListener {
fun onTouch()
}
inner class TouchableWrapper(context: Context?) : FrameLayout(context!!) {
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> mListener!!.onTouch()
MotionEvent.ACTION_UP -> mListener!!.onTouch()
}
return super.dispatchTouchEvent(event)
}
}
}
和我的代码
class AddFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_add, container, false)
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as MySupportMapFragment
mapFragment.getMapAsync(object:OnMapReadyCallback {
override fun onMapReady(googleMap:GoogleMap) {
mMap = googleMap
with(googleMap) {
// We will provide our own zoom controls.
uiSettings.isZoomControlsEnabled = true
uiSettings.isMyLocationButtonEnabled = true
uiSettings.isScrollGesturesEnabled = true
this.mapType = GoogleMap.MAP_TYPE_HYBRID
moveCamera(CameraUpdateFactory.newLatLngZoom(StartPosition, 10f))
}
mMap.setOnCameraIdleListener(object : GoogleMap.OnCameraIdleListener {
override fun onCameraIdle() {
mPositionLatitude = mMap.getCameraPosition().target.latitude
mPositionLongitude = mMap.getCameraPosition().target.longitude
}
})
var mScrollView = view.findViewById(R.id.scroll_view) as ScrollView
mapFragment.setListener(object :
MySupportMapFragment.OnTouchListener {
override fun onTouch() {
mScrollView.parent.requestDisallowInterceptTouchEvent(true)
}
})
}
})
return view
}
}
}
在我的应用程序中遇到同样的问题,我使用自定义滚动视图使用拦截滚动视图触摸解决了这个问题
自定义滚动视图:
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;
}
}