55

新しいAndroidGoogleMaps API(v2)を実装しようとしています。ただし、 SlidingMenuではうまくいかないようです。ご存知かもしれませんが、MapFragment実装はに基づいていSurfaceViewます。問題は、SurfaceViewそれを移動するのが好きではないということです-つまり、移動可能なビューに配置することを意味します:

動かすと、元々ピクセルがあった場所にブラックホールが残ります。こんな感じです

SurfaceViewこの問題は、または上に透明な背景を指定するか、その上に透明な背景を配置することで部分的に解決できますView。自分だけでは結果が受け入れられないのか、それとも別の問題が発生してどのように見えるのかがわかりません。

それがどのように見えるかを見るには、このビデオを見てください。

(品質は申し訳ありませんが、とにかく問題は簡単にわかります)

開いているときに通常のリストビュー(オレンジ色の画面)を引き離すSlidingMenuと、アニメーションがスムーズできれいになります。しかし、が表示されるとすぐMapFragmentに、マップ上に奇妙な更新/ちらつき/同期の問題が発生します。

HTCOneSおよびSamsungGalaxyACEでテスト済み。


それを解決するという私の超狂気のアイデア:オープニングアニメーションが開始するたびに、MapFragment(SurfaceViewで可能であるはずの)スクリーンショットを撮り、アニメーションの期間中それを重ねます。しかし、私は本当にそれを行う方法を知りません... 地図のスクリーンショットを撮ることは不可能ですが、誰かがこれに触発されるかもしれません。

あるいは、他の方法で地図の再描画を無効にするかもしれませんが、わかりません。


アップデート:

これを見つけまし

これらの制限を取り除くために、SurfaceViewをTextureViewに変更できるようです。しかし、MapFragmentはSurfaceViewに基づいているため、それを実現できるかどうかはわかりません。

別の更新 この問題はデバイス4.1以降で解決されたようです。彼らはTextureViewを使用しました。ただし、下位バージョンでは、回避策を使用する必要があります。

4

16 に答える 16

4

これはクレイジーなアイデアです。MapView を移動しないでください ;-)

つまり、FrameLayout でアプリの背後に全画面幅の MapView を作成します。次に、ビューを上に置き、MapView を表示する必要がある位置に穴を開けます。移動するときは、同期を維持するためにマップの位置を更新する必要があります。これにより、ユーザーはマップの同じセクションを見続けることができますが、サーフェス ビューを移動するよりも適切に更新されるはずです。

于 2013-01-21T23:05:00.313 に答える
3

Dianne Hackborn (Android フレームワーク エンジニア) の言葉を引用します。

表面ビューは実際には窓の後ろにあり、それを見るために窓に穴が開けられています。このように、ウィンドウ内で物をその上に置くことはできますが、ウィンドウ内の何も後ろに表示することはできません。 元の投稿

このアーキテクチャは、これらのちらつきが見られる理由の一部です。

ダブル バッファが原因でちらつきが発生することがあります。Android のコーディング ブログで詳しく説明しています。

をサブクラス化しSurfaceViewて、背景を別の方法で描画することもできます。z-index を一番上のものに変更しない例は見たことがありません。このSO投稿をチェックしてください

それ以外の場合は、ビューがフォーカスされた後にのみ取得しSurfaceHolder(それまで一時的なビューを作成してみてください)SurfaceView、フォーカスされていない画面上で を削除することをお勧めします。

于 2013-01-28T21:56:50.797 に答える
2

私のシナリオでは、最初のフラグメントがあり、ボタンをクリックすると、その中に MapFragment がある 2 番目のフラグメントにスワップされました。このちらつきは、フラグメントを初めてスワップするときにのみ発生することに気付きました。バックスタックをポップし、同じタイプの別のフラグメントをスワップしてもちらつきは発生しませんでした。

そのため、最初の SurfaceView をウィンドウに追加することと関係があると考えて、メイン ビューの背後にある、最初に読み込まれたフラグメントに SurfaceView の空のインスタンスを追加しようとしました。そしてビンゴ、次のフラグメントでアニメーション化するときのちらつきはもうありません!

それが最もクリーンなソリューションではないことはわかっていますが、機能します。未使用の SurfaceView が前のフラグメントにあるため、Google MapFragment (または私の場合は SupportMapFragment) は引き続き正常に動作します。

v2 API を使用していることを付け加えておきます。

@VenomVendor を更新

空の SurfaceView を表示する最初のフラグメントに追加します。インデックス 0 はメイン ビューの後ろです。私の場合、ホーム フラグメントは、Google マップ フラグメントを含むフラグメントの前のフラグメントですが、それが重要かどうかはわかりません。

import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class HomeFragment extends FragmentBase {
private SurfaceView sview;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_home, container, false);

    //this fixes google maps surface view black screen animation issue
    sview = new SurfaceView(getActivity());
    sview.setZOrderOnTop(true);    // necessary
    SurfaceHolder holder = sview.getHolder();
    holder.setFormat(PixelFormat.TRANSPARENT);

    container.addView(sview, 0);
    ...
}
于 2013-07-17T16:55:22.350 に答える
1

MapView (実際には SurfaceView です) がブラック ホールを作成するのを防ぐために、MapView がブラック ホールを生成するのを防ぐことができるように、MapView 全体を覆う透明な背景色の空のビューを追加します。それはあなたの状況でうまくいくかもしれません。

于 2013-03-07T06:37:12.587 に答える
1

追加してみてください..

getHolder().setFormat(PixelFormat.TRANSLUCENT);

あなたのSurfaceViewのコンストラクタに。TextureView も機能するはずですが、サブ API 14 デバイスのサポートを削除する必要があります。

于 2014-06-24T11:09:55.257 に答える
1

別の代替ソリューションは、新しいGoogleMap.snapshot()関数を使用し、代わりにマップのスクリーンショットを使用することです。ここで説明されているように。

于 2013-08-13T15:02:24.420 に答える
0

私が見つけた最善の解決策は、これを介してサポートマップをインスタンス化することでした。驚くべきこと

SupportMapFragment mapFragment = SupportMapFragment.newInstance(new GoogleMapOptions().zOrderOnTop(true));
于 2014-02-21T13:20:25.737 に答える
0

リストビューのスクロール時に黒い画面が表示されるという同じ問題がありました。同じ画面でリストビューでマップフラグメントを使用していました.xmlで魔法のプロパティを使用してこの問題を解決しました。 scrollingCache="false" .私の問題は修正されました。このプロパティを試して、マップの遅延やちらつきを止めてください。

于 2013-04-22T09:54:32.430 に答える
0

可能であれば FrameLayout を RelativeLayout に変更する

于 2014-11-09T20:26:15.670 に答える
0

同じ問題があり、「可視性」の変更に基づく回避策を使用しました。

private GoogleMap mMap;
private SupportMapFragment mMapFragment;

mMapFragment = ((SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.mapFragment));
mMap = mMapFragment.getMap();

//Change the visibility to 'INVISIBLE' before the animation to go to another fragment.
mMapFragment.getView().setVisibility(View.INVISIBLE);

//Change the visibility to 'VISIBLE' after coming back to the original fragment that has map fragment.
mMapFragment.getView().setVisibility(View.VISIBLE);
于 2014-12-04T04:13:15.930 に答える
-1

これは、ViewPagerの点滅を取り除くために使用した非常に簡単な回避策です。Fragmentやその他の動的に追加されたMapViewについても同じことが当てはまると思います。

問題は実際にはMapView自体ではないようですが、MapViewを実行するために必要なリソースです。これらのリソースは、アクティビティでMapViewを初めて起動したときにのみ読み込まれ、予想どおり、後続の各MapViewで再利用されます。このリソースのロードにより、画面が点滅します。

したがって、点滅を削除するために、アクティビティのレイアウトに別のMapViewを含めました(アクティビティ内の場所は関係ありません)。アクティビティが読み込まれるとすぐに、追加のMapViewの表示をGONEに設定します。これは、MapViewsを使用してフラグメントを起動するときに、MapViewに必要なすべてのリソースが、ラグ、点滅、すべての幸福なしに準備ができていることを意味します。

これはもちろん回避策であり、根本的な問題に対する実際の「解決策」ではありませんが、副作用は解決されます。

したがって、完全を期すために使用されるコードを隠すために:

ランダムに(ただしきれいに)アクティビティレイアウトに配置されます:

<com.google.android.gms.maps.MapView
        android:id="@+id/flash_map"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

それから私のアクティビティクラスで

private MapView flashMap;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

            // Code omitted

    try {
        MapsInitializer.initialize(this);
    } catch (GooglePlayServicesNotAvailableException e) {
        e.printStackTrace();
    }
    flashMap = (MapView)findViewById(R.id.flash_map);
    flashMap.onCreate(savedInstanceState);
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
        flashMap.onSaveInstanceState(outState);
}

@Override
public void onResume() {
    super.onResume();
    flashMap.onResume();
    flashMap.setVisibility(View.GONE); // Just like it was never there...
}

@Override
public void onPause() {
    flashMap.onPause();
    super.onPause();
}

@Override
public void onDestroy() {
    flashMap.onDestroy();
    super.onDestroy();
}

@Override
public void onLowMemory() {
    super.onLowMemory();
    flashMap.onLowMemory();
}
于 2013-01-30T04:42:48.620 に答える