【问题标题】:MapView inside a ScrollView?ScrollView 中的 MapView?
【发布时间】:2011-07-01 09:29:51
【问题描述】:

我想在 ScrollView 中有一个 MapView,但是当我尝试滚动地图时,ScrollView 优先!有没有办法在地图内滚动时赋予 MapView 优先权,否则赋予 ScrollView?

谢谢!

【问题讨论】:

  • 你的布局是什么?你能发布一个最终呈现的布局的屏幕截图吗?
  • MapView 自动处理滚动....
  • 我知道。我有一个 ScrollView,其中包含很多不同的东西,包括 MapView。问题是当我尝试在地图视图内滚动时,滚动视图会覆盖它。
  • 我也在我的应用程序中这样做,但没有得到任何解决方案,所以我将 mapview 放在滚动视图之外,将其余布局放在滚动视图中。
  • 其他答案没什么新意,但我创建了一个关于如何解决这个问题的要点。 gist.github.com/Sottti/890daaeead1bd4784dfce7066a9011aa

标签: android google-maps android-maps


【解决方案1】:

我遇到同样的问题已经 10 天了,但几分钟前我得到了解决方案! 这是解决方案。 我制作了一个自定义 MapView 并像这样覆盖 onTouchEvent()。

@Override
public boolean onTouchEvent(MotionEvent ev) {
    int action = ev.getAction();
    switch (action) {
    case MotionEvent.ACTION_DOWN:
        // Disallow ScrollView to intercept touch events.
        this.getParent().requestDisallowInterceptTouchEvent(true);
        break;

    case MotionEvent.ACTION_UP:
        // Allow ScrollView to intercept touch events.
        this.getParent().requestDisallowInterceptTouchEvent(false);
        break;
    }

    // Handle MapView's touch events.
    super.onTouchEvent(ev);
    return true;
}

【讨论】:

  • @Luizje:闪烁是由您为每个视图使用的背景颜色引起的。因此,请确保使用 corect bg 颜色获得最外层视图。
  • 如果它对你不起作用,请尝试重写 dispatchTouchEvent 方法(相同的实现,只是在最后更改 super 调用)。谢谢。
  • @Rotem 您的解决方案对我有用。我在 ScrollView 中有一个 com.google.android.gms.maps.MapView ,它不适用于上面的代码。我扩展了这个类,并通过重写 dispatchTouchEvent 方法编写了您的解决方案。
  • @Rotem:它适用于 dispatchTouchEvent。谢谢哥们.. Njoyee 编码。
  • @Rotem,你的评论救了我的命。谢谢老兄。
【解决方案2】:

一种更好/更简单的方法来做到这一点,而无需操纵单个触摸事件。 如果您使用 MapView,这将起作用:

  @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        /**
         * Request all parents to relinquish the touch events
         */
        getParent().requestDisallowInterceptTouchEvent(true);
        return super.dispatchTouchEvent(ev);
    }

全班:

public class CustomMapView extends MapView {

    public CustomMapView(Context context) {
        super(context);
    }

    public CustomMapView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomMapView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public CustomMapView(Context context, GoogleMapOptions options) {
        super(context, options);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        /**
         * Request all parents to relinquish the touch events
         */
        getParent().requestDisallowInterceptTouchEvent(true);
        return super.dispatchTouchEvent(ev);
    }
}

如果您使用的是 MapFragment,那么您可以将片段放在自定义视图中,并在 dispatchTouchEvent() 中进行 requestDisallowInterceptTouchEvent 调用。

【讨论】:

  • 谢谢老板。它非常适合我。
  • 这是最好的答案,谢谢。
  • 很好,虽然requestDisallowInterceptTouchEvent 仅对MotionEvent.ACTION_DOWN 是必需的。
【解决方案3】:

制作您自己的地图并使用它。它完全适合我。

public class CustomMapView extends MapView {

public CustomMapView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
    case MotionEvent.ACTION_UP:
        System.out.println("unlocked");
        this.getParent().requestDisallowInterceptTouchEvent(false);
        break;
    case MotionEvent.ACTION_DOWN:
        System.out.println("locked");
        this.getParent().requestDisallowInterceptTouchEvent(true);
        break;
    }
    return super.dispatchTouchEvent(ev);
}} 

在您的布局 xml 中,

<com.yourpackage.xxxx.utils.CustomMapView
                android:id="@+id/customMap"
                android:layout_width="match_parent"
                android:layout_height="400dp"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                />

【讨论】:

    【解决方案4】:

    对于那些想要完整工作代码的人。这里是

    自定义地图视图类

    public class CustomMapView extends MapView {
    
    private ViewParent mViewParent;
    public CustomMapView(Context context) {
        super(context);
    }
    
    public CustomMapView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    public CustomMapView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    
    public CustomMapView(Context context, GoogleMapOptions options) {
        super(context, options);
    }
    
    public void setViewParent(@Nullable final ViewParent viewParent) { //any ViewGroup
        mViewParent = viewParent;
    }
    
    @Override
    public boolean onInterceptTouchEvent(final MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (null == mViewParent) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                } else {
                    mViewParent.requestDisallowInterceptTouchEvent(true);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (null == mViewParent) {
                    getParent().requestDisallowInterceptTouchEvent(false);
                } else {
                    mViewParent.requestDisallowInterceptTouchEvent(false);
                }
                break;
            default:
                break;
        }
    
        return super.onInterceptTouchEvent(event);
      }
    }
    

    活动布局 xml

      <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <location.to.your.CustomMapView
            android:id="@+id/mapView"
            android:layout_width="match_parent"
            android:layout_height="250dp"
             />
    
    </ScrollView>
    

    在您的活动或片段中实例化自定义地图类

           CustomMapView mapView = (CustomMapView) findViewById(R.id.mapView);
    

    这就是享受

    【讨论】:

    • 其他解决方案对我不起作用,这个解决了!非常感谢!
    【解决方案5】:

    您可以像这样创建自定义 MapView:

    public class CustomMapView extends MapView {
    
        private MapFragment.ControlLock mCallbackControl;
    
        public CustomMapView(Context context) {
            this(context, null);
        }
    
        public CustomMapView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public CustomMapView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        public CustomMapView(Context context, GoogleMapOptions options) {
            super(context, options);
        }
    
        public void setCallback(MapFragment.ControlLock callbackControl) {
            this.mCallbackControl = callbackControl;
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
    
            switch (event.getAction()) {
                case MotionEvent.ACTION_UP:
                    System.out.println("unlocked");
                    mCallbackControl.unlock(); /* Interface */
                    break;
                case MotionEvent.ACTION_DOWN:
                    System.out.println("locked");
                    mCallbackControl.lock(); /* Interface */
                    break;
            }
    
            return super.dispatchTouchEvent(event);
        }
    }
    

    【讨论】:

    • 拯救了我的一天。也适用于 osmdroid mapview。很棒。
    【解决方案6】:

    我尝试过覆盖 MapView.onTouchEvent(...),但它对我不起作用。 这是运行良好的代码(覆盖 MapView.onInterceptTouchEvent(...)):

    public class MyMapView extends MapView {
        private ViewParent mViewParent;
    
    //add constructors here
    
        public void setViewParent(@Nullable final ViewParent viewParent) { //any ViewGroup
                mViewParent = viewParent;
        }
    
        @Override
            public boolean onInterceptTouchEvent(final MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        if (null == mViewParent) {
                            getParent().requestDisallowInterceptTouchEvent(true);
                        } else {
                            mViewParent.requestDisallowInterceptTouchEvent(true);
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        if (null == mViewParent) {
                            getParent().requestDisallowInterceptTouchEvent(false);
                        } else {
                            mViewParent.requestDisallowInterceptTouchEvent(false);
                        }
                        break;
                    default:
                        break;
                }
    
                return super.onInterceptTouchEvent(event);
            }
    }
    

    【讨论】:

    • 因为我有很多嵌套的视图组,所以这个解决方案对我来说效果很好。
    • 覆盖onInterceptTouchEvent() 也对我有用,而onTouchEvent() 没有。但我不需要 mViewParent,似乎 requestDisallowInterceptTouchEvent() 向上传播了视图层次结构。
    【解决方案7】:

    您可以简单地将 MapView 放入 Layout 本身并覆盖 onTouch 或设置 Click-Listener - 对我来说最简单的方法,因为我需要在 ScrollView 中触摸整个 MapView。

    【讨论】:

      【解决方案8】:

      如果您在滚动视图中有地图视图,那么您必须明确地向 MapView 提及以下参数:

      mMapView.setClickable(true);
      mMapView.setFocusable(true);
      mMapView.setDuplicateParentStateEnabled(false);
      

      【讨论】:

      • 但是在你指定它之后,地图视图将变得不可滚动
      【解决方案9】:

      如果有人想要 kotlin 中的这个类。
      我使用@rotem 建议的dispatchTouchEvent

      class CustomMapView : MapView {
                 constructor(context: Context):
                  super(context)
          constructor(context: Context, googleMapOptions: GoogleMapOptions):
                  super(context, googleMapOptions)
          constructor(context: Context, attributeSet: AttributeSet):
                  super(context, attributeSet)
          constructor(context: Context, attributeSet: AttributeSet, int: Int):
                  super(context, attributeSet, int)
      
          override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
              Log.d("CustomWebView", "touchevent")
              when(event?.action) {
                  MotionEvent.ACTION_UP -> {
                      Log.d("CustomWebView", "disallow Intercept")
                      parent.requestDisallowInterceptTouchEvent(false)
                  }
                  MotionEvent.ACTION_DOWN -> {
                      Log.d("CustomWebView", "allow Intercept")
                      parent.requestDisallowInterceptTouchEvent(true)
                  }
              }
              return super.dispatchTouchEvent(event)
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-06-27
        • 1970-01-01
        • 1970-01-01
        • 2020-08-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多