Подтвердить что ты не робот

Как установить фрагмент карты google внутри прокрутки

Я хочу установить фрагмент карты Google внутри вертикального ScrollView, когда я не масштабирую карту по вертикали, как я могу переопределить прослушиватель событий касания на MapView над слушателем ScrollView?

Это мой xml-код:

  <ScrollView  android:layout_height="wrap_content"
    android:layout_width="fill_parent"
     android:layout_above="@id/footer"
    android:layout_below="@id/title_horizontalScrollView">

   ///other things



<fragment 
    android:id="@+id/map"
    android:layout_width="fill_parent"
    android:layout_height="300dp"
    class="com.google.android.gms.maps.SupportMapFragment"
    />

  //other things
4b9b3361

Ответ 1

Создайте собственный SupportMapFragmet, чтобы мы могли переопределить его событие касания:

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);
        }
    }
}

В этом классе мы перехватываем событие touch, используя класс TouchableWrapper, который расширяет FrameLayout. Существует также пользовательский прослушиватель OnTouchListener для отправки события касания к основной активности MyMapActivity, которая обрабатывает карту. Когда произойдет событие касания, будет вызван dispatchTouchEvent, и обработчик-слушатель обработает его.

Затем замените класс фрагмента в xml этим class="packagename.WorkaroundMapFragment" вместо com.google.android.gms.maps.SupportMapFragment

Затем в вашей деятельности инициализируйте карту следующим образом:

private GoogleMap mMap;

внутри onCreate сделать это:

  // 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);
                                }
                            });
                    }
        });
    }

Обновление: ответ обновлен до getMapAsync на основе ответа @javacoder123

Ответ 2

Просто сделайте CustomScrollView.class,

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

Затем в xml

<com.app.ui.views.CustomScrollView
     android:id="@+id/scrollView"
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fillViewport="true"
     android:orientation="vertical">
</com.app.ui.views.CustomScrollView>

Если xml beffore не работает, измените это...

<com.myproyect.myapp.CustomScrollView
        android:id="@+id/idScrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        android:descendantFocusability="beforeDescendants"
        >
</com.myproyect.myapp.CustomScrollView>

как использовать программный файл

CustomScrollView myScrollView = (CustomScrollView) findViewById(R.id.idScrollView);

Ответ 3

Мое предложение - использовать более легкую версию карты google при работе с этой ситуацией. это разрешило мою проблему.

добавить этот атрибут в фрагмент.

 map:liteMode="true"

и моя проблема решена. Я также добавил customScrollView в дополнение к этому. но после размещения свойства liteMode моя проблема решена.

Ответ 4

Пожалуйста, обратитесь к этому ответу: fooobar.com/questions/117234/...

Он создает прозрачное представление с таким же размером mapFragment, в той же позиции, что и mapFragment, а затем вызывает requestDisallowInterceptTouchEvent (true), не позволяя его предкам перехватывать события касания.

Добавьте прозрачный вид фрагмента mapview :

<ScrollView>
    ...
         <FrameLayout
             android:layout_width="match_parent"
             android:layout_height="300dp">
             <FrameLayout
                 android:id="@+id/fl_google_map"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent" />
             <!-- workaround to make google map scrollable -->
             <View
                 android:id="@+id/transparent_touch_panel"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent" />
         </FrameLayout>
</ScrollView>

Настройте сенсорный слушатель для этого прозрачного вида:

    var transparentTouchPanel = view.FindViewById (Resource.Id.transparent_touch_panel);
    transparentTouchPanel.SetOnTouchListener (this);

....

public bool OnTouch (View v, MotionEvent e) {
    switch (e.Action) {
    case MotionEventActions.Up:
        v.Parent.RequestDisallowInterceptTouchEvent (false);
        break;
    default:
        v.Parent.RequestDisallowInterceptTouchEvent (true);
        break;
    }

    return false;
}

Я думал, что RequestDisallowInterceptTouchEvent может работать с вызовом только один раз, но, очевидно, его нужно вызывать для КАЖДОГО события касания, поэтому его нужно поместить в onTouchEvent. И родитель передаст этот запрос родительскому родителю.

Я попытался установить прослушиватель событий касания для fl_google_map или для mapFragment.getView(). Ни один из них не сработал, поэтому создание прозрачного представления о сестре - приемлемый обходной путь для меня.

Я пробовал, это решение работает отлично. Проверьте комментарии под оригинальным сообщением, если вы мне не верите. Я предпочитаю этот способ, потому что не нужно создавать пользовательские SupportMapFragmet.

Ответ 5

Обновить

Ответ Алока Наира очень хорош, однако метод.getMap() больше не работает с android 9.2 и далее. Измените метод getMap на.getMapAsync и добавьте код в метод onMapReady

Обновленное решение, которое работает во фрагментах

if (gMap == null)
        {
          getChildFragmentManager().findFragmentById(R.id.map);
            SupportMapFragment mapFragment = (WorkaroundMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
            mapFragment.getMapAsync(new OnMapReadyCallback()
            {
                @Override
                public void onMapReady(GoogleMap googleMap)
                {
                    gMap = googleMap;
                    gMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                    gMap.getUiSettings().setZoomControlsEnabled(true);

                    mScrollView = mView.findViewById(R.id.advertScrollView); //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);
                                }
                            });
                }
            });
        }

Ответ 6

Как Android Document,
Вы можете добавить так:

<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="3"
        android:orientation="horizontal" >
<fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</LinearLayout>
</ScrollView>