API Android Google Maps V2, отменяющий часть макета

Я пытаюсь интегрировать Google Maps Android API v2 в свое приложение для Android. Я размещаю карту Google в середине моего макета. Он отлично работает, когда макет может поместиться на экране, но когда макет слишком большой, чтобы соответствовать, и пользователь прокручивает вниз, чтобы увидеть остальную часть содержимого, остальная часть макета затемняется Google Map. См. Следующий снимок экрана:

Screenshot of the issue

(Примечание. Все жесты карты отключены, чтобы позволить пользователю прокручивать.)

Мой макет XML:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:fillViewport="true" >

<RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="20sp" >

    <TextView
        android:id="@+id/race_num"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="14sp"
        android:textSize="@dimen/DetailsTop"
        android:layout_alignParentLeft="true"
        android:layout_toLeftOf="@+id/race_in_chase" />
    <TextView
        android:id="@id/race_in_chase"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/in_the_chase"
        android:textSize="@dimen/DetailsTop"
        android:background="@drawable/inthechase"
        android:paddingLeft="20sp"
        android:paddingRight="20sp"
        android:visibility="gone"
        android:layout_alignParentRight="true" />

    <TextView
        android:id="@+id/race_name"
        style="@style/RaceDetailsName"
        android:layout_below="@id/race_num" />
    <TextView
        android:id="@+id/race_track"
        style="@style/RaceDetailsText"
        android:paddingBottom="20sp"
        android:layout_below="@id/race_name" />

    <TextView
        android:id="@+id/race_time"
        style="@style/RaceDetailsText"
        android:layout_below="@id/race_track" />
    <TextView
        android:id="@+id/race_tv"
        style="@style/RaceDetailsText"
        android:layout_below="@id/race_time" />

    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="380dp"
        android:layout_marginTop="20sp"
        android:layout_marginBottom="20sp"
        class="com.google.android.gms.maps.SupportMapFragment"
        android:layout_below="@id/race_tv" />

    <TextView
        android:id="@+id/race_track_size"
        style="@style/RaceDetailsText"
        android:layout_below="@id/map" />

</RelativeLayout>

</ScrollView>

Моя настройка карты в моей деятельности:

private void setUpMapIfNeeded() {
    if (mMap == null) {
        mMap = ((SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map)).getMap();
        if (mMap != null) {
            setUpMap();
        }
    }
}

private static final LatLng CHICAGOLAND = new LatLng(41.474856, -88.056928);

private void setUpMap() {
    mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
    mMap.getUiSettings().setZoomControlsEnabled(false);
    mMap.getUiSettings().setAllGesturesEnabled(false);
    CameraPosition cameraPosition = new CameraPosition.Builder()
        .target(CHICAGOLAND)
        .zoom(14.5f)
        .bearing(53)
        .build();
    mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}

Моя догадка - это фрагмент карты, который не нравится ScrollView, поскольку макет, если он прекрасно, если весь макет подходит на экране, и прокрутка не требуется. Сама карта кажется правильным. Точечный размер точного размера остальных элементов в представлении. У кого-нибудь есть идеи, как я могу избавиться от затемнения под картой, чтобы я мог видеть TextView под ним? Все, что я пробовал до сих пор, не сработало.

Ответ 1

Я смог обойти проблему с помощью взлома. Я расширил ScrollView, чтобы получать уведомления о событиях прокрутки. Я использовал реализацию ObservableScrollView из Синхронизировать позиции прокрутки ScrollView - андроид.

Я добавил в свой onCreate():

ObservableScrollView sv = (ObservableScrollView) findViewById(R.id.scroll);
sv.setScrollViewListener(this);

Затем, когда я получаю событие с изменением прокрутки, я переключаю видимость всего представления, что заставляет повторную компоновку, которая препятствует появлению черного ящика.

public void onScrollChanged(ObservableScrollView sv, int x, int y, int oldx, int oldy) {
    sv.setVisibility(View.GONE);
    sv.setVisibility(View.VISIBLE);
}

Я попытался сделать недействительным() отображение карты и переключить видимость только вида карты, но не работал. К счастью, просмотр видимости всего представления не вызывает какого-либо мерцания или другого странного поведения.

Вероятно, это лучшее решение, но на данный момент это единственное, что я нашел, который, похоже, работает.

Ответ 2

Мне удалось адаптировать вышеуказанное для той же проблемы в Viewpager, переопределив onPageScrolled в FragmentPagerAdapter:

@Override
public void onPageScrolled(int position, float positionOffset, 
                           int positionOffsetPixels) {
    if ((position == 0 && positionOffsetPixels > 0) ||
        (position == 1 && positionOffsetPixels == 0)) {
        MyFragment blackedOutFragment = (MyFragment) getSupportFragmentManager()
                .findFragmentByTag("android:switcher:" + R.id.pager + ":1");
        if (blackedOutFragment != null) {
            blackedOutFragment.getView().setVisibility(View.GONE);
            blackedOutFragment.getView().setVisibility(View.VISIBLE);
        }
    }
}

Где позиция 0 в Viewpager - это фрагмент, содержащий MapFragment, а позиция 1 - это фрагмент, который затемняется после прокрутки.

Ответ 3

Мое обходное решение: используйте новый интерфейс моментального снимка из GoogleMap и отобразите снимок карты при прокрутке страницы.

Вот мой код для установки моментального снимка (он в том же фрагменте, что и карта, называемый FragmentMap.java):

public void setSnapshot(int visibility) {
    switch(visibility) {
    case View.GONE:
        if(mapFragment.getView().getVisibility() == View.VISIBLE) {
            getMap().snapshot(new SnapshotReadyCallback() {
                @Override
                public void onSnapshotReady(Bitmap arg0) {
                    iv.setImageBitmap(arg0);
                }
            });
            iv.setVisibility(View.VISIBLE);
            mapFragment.getView().setVisibility(View.GONE);
        }
        break;
    case View.VISIBLE:
        if(mapFragment.getView().getVisibility() == View.GONE) {
            mapFragment.getView().setVisibility(View.VISIBLE);
            iv.setVisibility(View.GONE);
        }
        break;
    }
}

Где "mapFragment" - это мой SupportedMapFragment, а "iv" - это ImageView (сделать его match_parent).

И вот я контролирую свиток:

pager.setOnPageChangeListener(new OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if(position == 0 && positionOffsetPixels > 0 || position == 1 && positionOffsetPixels > 0) {
                ((FragmentMap)adapter.getRegisteredFragment(1)).setSnapshot(View.GONE);
            } else if(position == 1 && positionOffsetPixels == 0) {
                ((FragmentMap)adapter.getRegisteredFragment(1)).setSnapshot(View.VISIBLE);
            }
        }
        @Override
        public void onPageScrollStateChanged(int arg0) {}
        @Override
        public void onPageSelected(int arg0) {}
    });

Мой фрагмент с картой (FragmentMap) находится в позиции 1, поэтому мне нужно управлять прокруткой с позиции 0 до 1 и с позиции 1 на 2 (первое if-предложение). "getRegisteredFragment()" - это функция в моем пользовательском FragmentPagerAdapter, в котором у меня есть SparseArray (фрагмент), называемый зарегистрированными фрагментами.

Итак, всякий раз, когда вы переходите на или с вашей карты, вы всегда видите ее снимок. Это очень хорошо для меня.

Ответ 4

Я предполагаю, что высота MapFragment равна 0 во время инициализации Activity. Попробуйте

<RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:padding="20sp" >

....

      <TextView
            android:id="@+id/race_track_size"
            style="@style/RaceDetailsText"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="2dp"/>

</RelativeLayout>

Ответ 5

Просто эксперимент, но вы пытались добавить TextView на экран программно в setupMap() после того, как Карта уже была инициализирована?

// First, get a handle on the parent RelativeLayout, 
// call it parentRelativeLayout, then…                  

TextView textView = new TextView(getActivity());
RelativeLayout.LayoutParams textLayout = new RelativeLayout.LayoutParams(
    RelativeLayout.MATCH_PARENT, 
    RelativeLayout.MATCH_PARENT
);
textLayout.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, -1);
textView.setLayoutParams(textLayout);

parentRelativeLayout.addView(textView)

Ответ 7

Другая возможность - использовать новую функцию GoogleMap.snapshot() и вместо этого использовать скриншот карты, как описано здесь.