可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to integrate Google Maps Android API v2 into my Android Application. I'm placing the Google Map in the middle of my layout. It works great when the layout is able to fit on the screen, but when the layout is too big to fit, and the user scrolls down to see the rest of the content, the rest of the layout is blacked out by the Google Map. See the following screenshot:
(Note: All the map gestures are disabled to allow the user to scroll.)
My layout 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>
My map setup in my Activity:
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));
}
My hunch is the maps fragment does not like the ScrollView since the layout if fine if the entire layout fits on the screen and scrolling isn't required. The map itself appears to be the correct size. The blackout is the exact size of the remaining items in the view. Does anyone have any ideas how I can get rid of the blackout below the map so I can see the TextView below it? Everything I've tried until now hasn't worked.
回答1:
I was able to work around the issue with a hack. I extended ScrollView so I could get notified on scroll events. I used the ObservableScrollView implementation from Synchronise ScrollView scroll positions - android.
I added to my onCreate():
ObservableScrollView sv = (ObservableScrollView) findViewById(R.id.scroll);
sv.setScrollViewListener(this);
Then, when I receive a scroll changed event, I toggle the visibility of the whole view, which forces a re-layout, which prevents the black box from appearing.
public void onScrollChanged(ObservableScrollView sv, int x, int y, int oldx, int oldy) {
sv.setVisibility(View.GONE);
sv.setVisibility(View.VISIBLE);
}
I tried to invalidate() the map view, and toggling the visibility of just the map view, but neither worked. Thankfully toggling the visibility of the whole view doesn't cause any flicker or other strange behavior.
There probably is a better solution, but at this point, this is the only thing I've found that seems to work.
回答2:
My workaround: make use of the new snapshot interface from GoogleMap and display a snapshot of the map while scrolling the page.
Here is my code to setting the snapshot (it's in the same fragment as map, called 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;
}
}
Where "mapFragment" is my SupportedMapFragment and "iv" is an ImageView (make it match_parent).
And here I am controlling the scroll:
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) {}
});
My fragment with map (FragmentMap) is on position 1, so I need to controll the scroll from position 0 to 1 and from position 1 to 2 (the first if-clause). "getRegisteredFragment()" is a function in my custom FragmentPagerAdapter, in which I have a SparseArray(Fragment) called "registeredFragments".
So, whenever you scroll to or from your map, you always see a snapshot of it. This works very well for me.
回答3:
I was able to adapt the above for the same issue in a Viewpager by overriding onPageScrolled
in the 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);
}
}
}
Where position 0
in the Viewpager is a Fragment holding a MapFragment and position 1
is the Fragment getting blacked out after the scroll.
回答4:
My guess is the MapFragment's height is 0 during the Activity's initialization . Try with
<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:
This should fix it by making the surface view transparent
https://github.com/NyxDigital/NiceSupportMapFragment
回答6:
Another possibility is to use the new GoogleMap.snapshot() function and using a screenshot of the map instead as described here.
回答7:
You can use this library,
https://github.com/NyxDigital/NiceSupportMapFragment/
This work fine for me.
回答8:
Just an experiment, but have you tried adding the TextView to the screen programmatically in setupMap() after the Map has already been initialized?
// 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)