복붙노트

[SCALA] 있는 ScrollView 내부 Google지도 API v2로 SupportMapFragment - 사용자가 수직으로지도를 스크롤 할 수 없습니다

SCALA

있는 ScrollView 내부 Google지도 API v2로 SupportMapFragment - 사용자가 수직으로지도를 스크롤 할 수 없습니다

나는 사용자가 다른 내용을 아래로 스크롤 할 수 있도록지도를보기 위해 스크롤 뷰 내부에 구글 맵을 넣어하려합니다. 문제는이 스크롤 뷰의 모든 수직 감동 이벤트를 먹는 것을, 그래서지도의 UI 경험은 매우 이상한된다.

나는 구글 맵의 V1, 당신은 MotionEvent.ACTION_DOWN에 requestDisallowInterceptTouchEvent 전화를 onTouch를 오버라이드 (override), 또는 setOnTouchListener 수 있다는 것을 알고있다. 나는 아무 소용 V2와 유사한 트릭을 구현하기 위해 노력했다.

지금까지 나는 시도했다 :

이 중 어느 것도 스크롤 문제를 해결할 없습니다. 내가 여기서 뭔가를 놓치고 있습니까? 사람이보기를 스크롤 내부지도의 작업 예제가있는 경우, 제발 친절 코드 예제를 공유 할 수 있을까?

해결법

  1. ==============================

    1.맵뷰 MapView 조각을 통해 투명한 이미지를 적용합니다.

    맵뷰 MapView 조각을 통해 투명한 이미지를 적용합니다.

    <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>   
    

    그런 다음 주있는 ScrollView에 대해 (사실) requestDisallowInterceptTouchEvent을 설정합니다. 사용자가 투명 이미지를 접촉 및 이동 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;
            }   
        }
    });
    

    이것은 나를 위해 일했다. 당신을 도움이되기를 바랍니다 ..

  2. ==============================

    2.나는 비슷한 문제가 발생에서 호 이순신을 기반으로보다 일반적인 작업 솔루션을 함께 와서 Данаил Димитров 위의 대답.

    나는 비슷한 문제가 발생에서 호 이순신을 기반으로보다 일반적인 작업 솔루션을 함께 와서 Данаил Димитров 위의 대답.

    public class CustomScrollView extends ScrollView {
    
        List<View> mInterceptScrollViews = new ArrayList<View>();
    
        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);
        }
    
        public void addInterceptScrollView(View view) {
            mInterceptScrollViews.add(view);
        }
    
        public void removeInterceptScrollView(View view) {
            mInterceptScrollViews.remove(view);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent event) {
    
            // check if we have any views that should use their own scrolling
            if (mInterceptScrollViews.size() > 0) {
                int x = (int) event.getX();
                int y = (int) event.getY();
                Rect bounds = new Rect();
    
                for (View view : mInterceptScrollViews) {
                    view.getHitRect(bounds);
                    if (bounds.contains(x, y + scrollY)) {
                        //were touching a view that should intercept scrolling
                        return false;
                    }
                }
            }
    
            return super.onInterceptTouchEvent(event);
        }
    }
    
  3. ==============================

    3.제안을 주셔서 감사합니다,

    제안을 주셔서 감사합니다,

    후 많은 시도 착오는 내 머리카락을 당겨 모니터를 맹세하고 불쌍한 내 안드로이드 테스트 전화, 내가있는 ScrollView를 사용자 정의 할 경우 이벤트 상관없이지도보기에 없을 때, 우리는 false를 반환하는 onInterceptTouchEvent를 오버라이드 (override)하는 것을 냈어요 예상대로 다음지도에 스크롤 무엇을, 어떻게 않습니다.

    class MyScrollView(c:Context, a:AttributeSet) extends ScrollView(c,a) {
      val parent = c.asInstanceOf[MyActivity]
      override def onInterceptTouchEvent(ev:MotionEvent):Boolean = {
        var bound:Rect = new Rect()
        parent.mMap.getHitRect(bound)
        if(bound.contains(ev.getX.toInt,ev.getY.toInt))
          false
        else
          super.onInterceptTouchEvent(ev)
      }
    }
    

    이 코드는 스칼라에 있지만 당신은 아이디어를 얻을.

    (mapdemoRawMapViewDemoActivity.java \ 예 \ \ 엑스트라 \ 구글 \ google_play_services 샘플 맵을 \ \ \ SRC \ COM 안드로이드 SDK를 참조) 나는 원시지도보기를 사용하여 종료 한 참고. 당신은 조각과 거의 같은 일을 할 수있는 추측, 난 그냥 처음부터 조각을 좋아 한 적이.

    나는 구글이 나에게 사과를 빚지고있다 생각합니다.

  4. ==============================

    4.그래서 여기에 내가 사람이 그것을 필요로 단지의 경우 자바 코드와 솔루션을 사용하는 방법입니다, 같은 문제가 있었다. 당신은 그것을 사용할 때지도보기 필드를 설정해야합니다.

    그래서 여기에 내가 사람이 그것을 필요로 단지의 경우 자바 코드와 솔루션을 사용하는 방법입니다, 같은 문제가 있었다. 당신은 그것을 사용할 때지도보기 필드를 설정해야합니다.

    import com.google.android.gms.maps.MapView;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.ScrollView;
    
    public class ScrollViewWithMap extends ScrollView
    {
        public MapView mapView;
    
        public ScrollViewWithMap(Context context, AttributeSet attrs)
        {
            super(context, attrs);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev)
        {
            if (mapView == null)
                return super.onInterceptTouchEvent(ev);
    
            if (inRegion(ev.getRawX(), ev.getRawY(), mapView))
                return false;
    
            return super.onInterceptTouchEvent(ev);
        }
    
        private boolean inRegion(float x, float y, View v)
        {
            int[] mCoordBuffer = new int[]
            { 0, 0 };
    
            v.getLocationOnScreen(mCoordBuffer);
    
            return mCoordBuffer[0] + v.getWidth() > x && // right edge
                    mCoordBuffer[1] + v.getHeight() > y && // bottom edge
                    mCoordBuffer[0] < x && // left edge
                    mCoordBuffer[1] < y; // top edge
        }
    }
    
  5. ==============================

    5.허용 된 대답은 내 경우에는 작동하지 않았다. 게스트의 대답은 (하지만 거의)도 않았다. 이것은 다른 사람 게스트의 대답이 편집 된 버전을 시도하기위한 경우라면.

    허용 된 대답은 내 경우에는 작동하지 않았다. 게스트의 대답은 (하지만 거의)도 않았다. 이것은 다른 사람 게스트의 대답이 편집 된 버전을 시도하기위한 경우라면.

    hitbox에서을 계산할 때 누군가가 그것을 사용할 필요가있는 경우 나 작업 표시 줄의 높이를 주석있다.

    public class InterceptableScrollView extends ScrollView {
    
        List<View> mInterceptScrollViews = new ArrayList<View>();
    
        public InterceptableScrollView(Context context) {
            super(context);
        }
    
        public InterceptableScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public InterceptableScrollView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        public void addInterceptScrollView(View view) {
            mInterceptScrollViews.add(view);
        }
    
        public void removeInterceptScrollView(View view) {
            mInterceptScrollViews.remove(view);
        }
    
        private int getRelativeTop(View myView) {
            if (myView.getParent() == this)
                return myView.getTop();
            else
                return myView.getTop() + getRelativeTop((View) myView.getParent());
        }
        private int getRelativeLeft(View myView) {
            if (myView.getParent() == this)
                return myView.getLeft();
            else
                return myView.getLeft() + getRelativeLeft((View) myView.getParent());
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent event) {
    
            // check if we have any views that should use their own scrolling
            if (mInterceptScrollViews.size() > 0) {
                int x = (int) event.getX();
                int y = (int) event.getY();
    
    
                /*
                int actionBarHeight = 0;
    
                TypedValue tv = new TypedValue();
                if (getContext().getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
                {
                    actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
                }
                */
    
                int viewLocationY = 0;
                int viewLocationX = 0;
                int relativeTop = 0;
                int relativeLeft = 0;
    
                for (View view : mInterceptScrollViews) {
    
                    relativeTop = getRelativeTop((View) view.getParent());
                    relativeLeft = getRelativeLeft((View) view.getParent());
                    viewLocationY = relativeTop - getScrollY();
                    viewLocationX = relativeLeft - getScrollX();
    
                    if (view.getHeight() + viewLocationY > y && y > viewLocationY && view.getWidth() + viewLocationX > x && x > viewLocationX)
                    {
                        return false;
                    }
                }
            }
    
            return super.onInterceptTouchEvent(event);
        }
    }
    
  6. ==============================

    6.코드를 개선하면 투명 이미지를 다시 필요하지 않은 경우 :

    코드를 개선하면 투명 이미지를 다시 필요하지 않은 경우 :

    // gmap hack for touch and scrollview
            final ScrollView mainScrollView = (ScrollView) rootView.findViewById(R.id.scrollView);
            (rootView.findViewById(R.id.fixTouchMap)).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;
                    }
                }
            });
    
  7. ==============================

    7.위에 나열된 대부분의 옵션은 나를 위해 작동하지 않았다하지만 나를 위해 문제에 대한 좋은 해결책이 될 입증 다음 :

    위에 나열된 대부분의 옵션은 나를 위해 작동하지 않았다하지만 나를 위해 문제에 대한 좋은 해결책이 될 입증 다음 :

    치즈 바론 솔루션

    나는 또한 상황이 조금 더 복잡하지만, 작업을 쉽게 얻을 만든 조각에지도를 사용하고 같은, 내 구현을위한 약간 다르게이다 구현했다.

  8. ==============================

    8.당신의 XML에 정의 구글지도 조각을 사용합니다.

    당신의 XML에 정의 구글지도 조각을 사용합니다.

    여기에 나를 위해 일한 전체 코드입니다. 너희들이 어떤 질문이 있으면 알려 주시기 바랍니다.

    XML 파일에서지도 조각으로 다음을 추가

    <fragment
            android:id="@+id/map_with_scroll_fix"
            android:name="com.myapplication.maputil.GoogleMapWithScrollFix"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    

    다음지도에 대한 사용자 정의 클래스입니다

    package com.myapplication.maputil;
    
    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;
        public class GoogleMapWithScrollFix extends SupportMapFragment {
            private OnTouchListener mListener;
    
            @Override
            public View onCreateView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle savedInstance) {
                View layout = super.onCreateView(layoutInflater, viewGroup, savedInstance);
    
                TouchableWrapper touchableWrapper = new TouchableWrapper(getActivity());
    
                touchableWrapper.setBackgroundColor(getResources().getColor(android.R.color.transparent));
    
                ((ViewGroup) layout).addView(touchableWrapper,
                        new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    
                return layout;
            }
    
            public void setListener(OnTouchListener listener) {
                mListener = listener;
            }
    
            public interface OnTouchListener {
                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);
                }
            }
        }
    

    지도보기를 초기화, 활동 클래스에 다음을 추가합니다. 이게 다예요. 타다 :)

    ((GoogleMapWithScrollFix) getSupportFragmentManager()
                    .findFragmentById(R.id.map_with_scroll_fix)).getMapAsync(new OnMapReadyCallback() {
                @Override
                public void onMapReady(GoogleMap googleMap) {
                    ScrollView mScrollView = findViewById(R.id.scrollview); //parent scrollview in xml, give your scrollview id value
                    ((GoogleMapWithScrollFix) getSupportFragmentManager()
                            .findFragmentById(R.id.map_with_scroll_fix)).setListener(new GoogleMapWithScrollFix.OnTouchListener() {
                        @Override
                        public void onTouch() {
                            //Here is the magic happens.
                            //we disable scrolling of outside scroll view here
                            mScrollView.requestDisallowInterceptTouchEvent(true);
                        }
                    });
                }
            });
    
  9. from https://stackoverflow.com/questions/16974983/google-maps-api-v2-supportmapfragment-inside-scrollview-users-cannot-scroll-th by cc-by-sa and MIT license