今天做的一个页面,要在scrollview中嵌套高德地图,产生触摸冲突,拖动地图和scrollview的滑动事件冲突。
先说一下最终的解决方案。亲测可用。。。
1、自定义一个viewGroup,继承Relativelayout(或者别的layout)
重点是重写了onInterceptTouchEvent(MotionEvent ev)和onTouchEvent(MotionEvent event)
/**
*解决地图在主scrollview中滑动冲突的问题由于MapView被定义成final class,所以只能在容器中操作了
Created by 张玉水 on 2016/7/18.
*/
public class MapContainer extends RelativeLayout {
private ScrollView scrollView;
public MapContainer(Context context) {
super(context);
}
public MapContainer(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setScrollView(ScrollView scrollView) {
this.scrollView = scrollView;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
scrollView.requestDisallowInterceptTouchEvent(false);
} else {
scrollView.requestDisallowInterceptTouchEvent(true);
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return true;
}
}
2、在布局文件中,用上边定义的父控件包裹住高德地图的com.amap.api.maps2d.MapView.当然最外边是咱们的scrollview。
<com.babyrun.mmsh.widget.MapContainer
android:id="@+id/map_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.amap.api.maps2d.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="350dp" />
</com.babyrun.mmsh.widget.MapContainer>
3、在代码中设置一下要关联的Scrollview
scrollView = (ScrollView) findViewById(R.id.scrollview);
map_container = (MapContainer) findViewById(R.id.map_container);
map_container.setScrollView(scrollView);
上边三步做完后就可以完美解决问题。
另附:网上其他方法,都不怎么好用,亲测的。真心的。
一、这个代码网上出现很多次,但真的不管用啊。假的
// 重写onTouch()事件,在事件里通过requestDisallowInterceptTouchEvent(boolean)方法来设置父类的不可用,true表示父类的不可用
//解决地图的touch事件和scrollView的touch事件冲突问题
mMapView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){
scrollView.requestDisallowInterceptTouchEvent(false);
}else{
scrollView.requestDisallowInterceptTouchEvent(true);
}
return false;
}
});
如果是ListView嵌套在ScrollView中,解决方法是一样的。
二、重写scrollview,计算布局MapView所在的矩形区域,在矩形区域的时候,屏蔽scrollview的触摸事件的传递。下边的代码,有作用,但是效果不是很好啊。有的时候能动,有的时候不能。
/**
* Created by 张玉水 on 2016/7/18.
*/
public class LocationScrollView extends ScrollView {
public LocationScrollView(Context context) {
super(context);
}
public LocationScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LocationScrollView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
private Boolean mIfOnMap = false;//是否点击到地图了
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
int x = (int) ev.getX();
int y = (int) ev.getY();
Rect rect = new Rect();
if (ServiceLocationActivity.mapView != null) {
ServiceLocationActivity.mapView.measure(0,0);
ServiceLocationActivity.mapView.getDrawingRect(rect);
}
mIfOnMap = !rect.contains(x, y);
if (mIfOnMap) {
return false;
}else {
return super.onInterceptTouchEvent(ev);
}
}
// //得到view到 屏幕的距离
// public int[] getLocation(View v) {
// int[] loc = new int[4];
// int[] location = new int[2];
// v.getLocationOnScreen(location);
// loc[0] = location[0];
// loc[1] = location[1];
// int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
// int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
// v.measure(w, h);
//
// loc[2] = v.getMeasuredWidth();
// loc[3] = v.getMeasuredHeight()+loc[1];//底部距离 屏幕上边的 高
//
// int [] up_down=new int[2];
// up_down[0]=loc[1];//上边距离屏幕的距离
// up_down[1]=loc[3];// 底部距离屏幕的距离
// //base = computeWH();
// return up_down;
// }
}