Google Maps API v2を備えたViewPager:神秘的な黒いビュー


95

新しいgoogle maps api v2フラグメントをビューページャーに統合しました。マップフラグメントからスクロールすると、黒いビューが隣接するフラグメントに重なります。誰かが解決しましたか?

編集:スクリーンショット

ここに画像の説明を入力してください

public static class PagerAdapter extends FragmentPagerAdapter{

    public PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return NUM_ITEMS;
    }

    @Override
    public Fragment getItem(int position) {

        Fragment pageFragment;

        switch (position) {
        case 0:
            pageFragment = new TabAFragment();
            break;

        case 1:
            pageFragment = new TabBFragment();
            break;

        case 2:
            pageFragment = SupportMapFragment.newInstance();
            break;

        default:
            pageFragment = null;
            break;
        }

        return pageFragment;
    }
}

複数のデバイスで発生しますか?ViewPagerとマップの実装からの数行のコードが問題の理解に役立つ場合があります。
Adinia

はい、試したすべてのデバイスで発生します:samsung、htc、android 4.0、2.3など。アプリにマップを統合しました。ページャーとマップのみを含むクリーンなアプリで、同じ結果が得られました。
Pepe

@ペペ、どのようにGoogleMapオブジェクトを取得するのViewPagerですか?何週間もこれにこだわっています。あなたがよく質問を理解していない場合は、私の質問を調べてください、あなたは私の投稿を見つけるでしょう。返信してください。
アジズベキアン

screen record問題が発生しないように思われる場合は、追加したいと思います。
theblang 2014

回答:


115

ViewPager内側の上に透明な背景を持つ別のビューを配置することで、移行後に黒い表面が残されるのを防ぐことができましたFrameLayout

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <android.support.v4.view.ViewPager
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </android.support.v4.view.ViewPager>

    <!-- hack to fix ugly black artefact with maps v2 -->
    <FrameLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent" 
        android:background="@android:color/transparent" />

</FrameLayout>

1
すごい!ときどきページャーを移動しているときに黒いビューの一部が表示されるため、これは完璧ではありません。しかし、現在は画面に残っていません。ありがとう!(このハックについて何か説明はありますか?)
Pepe

7
あんまり。ズームと位置のコントロールが地図の表面のどこにあるのか、黒い軌跡が表示されないことに気付いたので、地図全体を覆うようにビューを上に配置しました。私はそれが完璧ではないことに同意します-黒い背景はGLSurfaceViewウィンドウの一部のようですcode.google.com/p/gmaps-api-issues/issues/detail?id=4639
Jeff Gilfelt

5
それは私のViewPagerの問題を修正したようです。ありがとうございます。SlideMenu(G + / Yahooのような左側のメニュー)で同様の問題が発生し、同じことを行っているようです。SlideMenuの実装を修正することについて何か考えはありますか?
Chrispix

@Chrispixはコンテナをアニメーション化せず、サイドメニューでのみアニメーションを使用します。これで修正されました。
まあまあ

1
このアプリがフォアグラウンドである間が、アプリを閉じて、まだ実行されている場合、あなたはまだそれに戻ってトップに地図滞在を行くプログラムによるソリューションの下に、彼らは仕事..行わアイブ
L7ColWinters

43

SlidingMenuとViewPagerにも同じ問題がありました。マップフラグメントのコントロールボタンがアーティファクトの左側にある黒ではないことに気付きました。私はonCreateView()メソッドをオーバーライドすることで問題を解決しましたMapFragment (SupportMapFragment)

@Override
public View onCreateView(LayoutInflater inflater, 
                         ViewGroup view, 
                         Bundle savedInstance) {

    View layout = super.onCreateView(inflater, view, savedInstance);
    FrameLayout frameLayout = new FrameLayout(getActivity());
    frameLayout.setBackgroundColor(
        getResources().getColor(android.R.color.transparent));
    ((ViewGroup) layout).addView(frameLayout,
        new ViewGroup.LayoutParams(
            LayoutParams.FILL_PARENT, 
            LayoutParams.FILL_PARENT
        )
    );
    return layout;
}

SlidingMenuにも使用します。しかし、私は(スライドアニメーションで)ちらつきの問題があり、それは容認できません。あなたも持っていますか?SlidingMenu閉じるときに私はHTCワンS.上でテスト面白いです何を、私はオープニングアニメーションで、この問題を持っていない
のMichałK

どの修正もうまくいきませんでした。私はMichal Kと実質的に同じ問題を抱えています。SlidingMenuを使用し、連続的な速度でゆっくり開閉すると問題はありません。軽くたたくか、押してウィンドウを閉じます。スライドが終了してマップが適切な位置に戻るまで、マップが少し遅れて空白スペースが残っているように見えます。
qubz 2013年

@qubz:「スライドメニュー」については、マップではなくメニューをアニメーション化してみてください。マップが動いていない場合、問題は解決しました。
2013年

@meh:SlidingMenuを開いたり閉じたりしている間、マップが動いている可能性があります。移動するとは、CameraUpdateを意味します。アニメーションを一時停止できるかどうか確認しますが、これはUXの妨げになります。
qubz 2013年

@Lubos Horacek:あなたはcode.IがNullポインタ例外エラーを取得していますサンプル..投稿してくださいでした
のAvinash

7

Googleはこの修正をリリースしましたが、4.1以降のみです(PlayServicesの新しいバージョンをダウンロードする必要はありません。サーバー側のフラグを使用していました)。

これは問題を回避するために使用しているものです-4.1以上のデバイスでCPUサイクルを無駄にしないようにします> =

public class FixMapFragment extends SupportMapFragment {

    @Override
    public View onCreateView(LayoutInflater inflater, 
                             ViewGroup container, 
                             Bundle savedInstanceState) {

        View view = super.onCreateView(inflater, container, savedInstanceState);

        // Fix for black background on devices < 4.1
        if (android.os.Build.VERSION.SDK_INT < 
            android.os.Build.VERSION_CODES.JELLY_BEAN) {
            setMapTransparent((ViewGroup) view);
        }
        return view;
    }

    private void setMapTransparent(ViewGroup group) {
        int childCount = group.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = group.getChildAt(i);
            if (child instanceof ViewGroup) {
                setMapTransparent((ViewGroup) child);
            } else if (child instanceof SurfaceView) {
                child.setBackgroundColor(0x00000000);
            }
        }
    }
}

:私はあなたが以下のようにクラスを参照推測FixMapFragment mapFragment = (FixMapFragment) fragmentManager.findFragmentById(R.id.map);し、レイアウトファイルに:<fragment android:id="@+id/map" android:name="com.example.fragments.FixMapFragment" ...。しかし、私が知る限り(Android 4.0.4)、マップはまだちらつきます。
JJD 2013年

@JJD私はちらつくマップビューを持っています、それを解決する方法はありますか?
Rat-a-tat-a-tat Ratatouille

@ Rat-a-tat-a-tatRatatouille私が知る限り、マップビューのちらつきを回避するための信頼できる回避策はありません。
JJD 2014年

私が今やったことが正しいかどうかはわかりませんが、うまくいきます。マップビューの可視性を非表示に設定し、数秒後にマップビューの可視性を可視に設定します。ちらつきを減らします。
Rat-a-tat-a-tat Ratatouille 2014年

6

私の回避策: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の関数で、「registeredFragments」というSparseArray(Fragment)があります。

そのため、マップにスクロールしたり、マップからスクロールしたりすると、常にマップのスナップショットが表示されます。これは私にとって非常にうまく機能します。


他の答えは私にとってうまくいきませんでした-これがうまくいった唯一の答えです。ありがとう!
alice_silver_man 2014

4

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


2

詳細についてはあまり触れていないので、提案できることは限られています。ページャーのビュー間で画面がちらつくという同様の問題がありました。最初にページ間を交換するときに、mapViewが膨張していることがわかりました。

はっきりさせると、ページャーに3ページあり、私の地図が最後のページでした。

これを解決するために、画面外のページ数を2に設定すると(これは上記のケースで機能しました)、フラグメントが開始すると、すべてのビューが一度に読み込まれることがわかりました。

http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit(int)を参照してください


ありがとう、でもうまくいきませんでした。問題は、マップで覆われている画面の一部が、他のフラグメントに変更されたときに、黒いままになり、この他のフラグメントのビューをカバーすることです。
Pepe

面白いね。私はこれについて考えます。
グラハムスミス

私は湯がにリンクされ、そのページにsetOffscreenPageLimitを見つけることができません
mplungjan

0

この問題にはもう1つの解決策があります。別のフラグメント内にMapFragmentを表示しています。MapFragmentは、FrameLayoutに動的に追加されます。

解決策は、スライドメニューのオープンイベントとクローズイベントでframeLayout.setVisibility(View.Visible)とframeLayout.setVisibility(View.Gone)を使用することです。追加するために追加のビューが必要です。そして黒い部分は完全になくなっています。

getSlidingMenu().setOnOpenListener(
        new OnOpenListener() {
            @Override
            public void onOpen() {
                frameLayout.setVisibility(View.GONE);
            }
        });

getSlidingMenu().setOnClosedListener(
        new OnClosedListener() {

            @Override
            public void onClosed() {
                frameLayout.setVisibility(View.VISIBLE);
            }
        });

0

上記の方法はどれも私にとってはうまくいきませんでした。他の場所で見つけた他の方法でもうまくいきませんでした。最後に、部分的なソリューションを選択しました。私はViewPagerのonPageChangeListenerを介してページの変更をリッスンし、ページがスクロールを開始したときにマップを非表示にし、同様にスクロールが停止したときに再び表示します。スクロール時に表示される白いビューも追加しました。


これをさらに拡張して、ビューの現在の画像をビットマップにキャプチャし、ページャーのスクロール中にImageViewに表示できます。そうすれば、ユーザーはその背後にあるハッキングに気付かないでしょう。ただし、スワイプに対するUIの応答が遅くなるため、この計算は少し高すぎることがわかりました。
azyoot 2013年

-2

カスタムマップフラグメントをプロジェクトにコピーするだけです。そして、上下にScrollViewがあり、ScrollViewに設定された黒い線がある場合android:fadingEdge = "none"

public class CustomMapFragment extends SupportMapFragment {
private OnActivityCreatedListener onActivityCreatedListener;

public CustomMapFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup view, Bundle savedInstance) {
    View layout = super.onCreateView(inflater, view, savedInstance);

    FrameLayout frameLayout = new FrameLayout(getActivity());
    frameLayout.setBackgroundColor(getResources().getColor(android.R.color.transparent));
    ((ViewGroup) layout).addView(frameLayout,
            new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    return layout;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (getOnActivityCreatedListener() != null)
        getOnActivityCreatedListener().onCreated();
}

public OnActivityCreatedListener getOnActivityCreatedListener() {
    return onActivityCreatedListener;
}

public void setOnActivityCreatedListener(
        OnActivityCreatedListener onActivityCreatedListener) {
    this.onActivityCreatedListener = onActivityCreatedListener;
}

public interface OnActivityCreatedListener {
    void onCreated();
}

}

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.