ViewPager avec l'API Google Maps v2: vue noire mystérieuse


95

J'ai intégré le nouveau fragment api v2 de google maps dans un pager de vue. Lors du défilement à partir du fragment de carte, une vue noire chevauche les fragments adjacents. Quelqu'un a résolu?

Edit: capture d'écran

entrez la description de l'image ici

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

Cela arrive-t-il à plus d'un appareil? Peut-être que quelques lignes de code de votre ViewPager et de l'implémentation de la carte pourraient vous aider à mieux comprendre votre problème.
Adinia

Oui, cela arrive sur tous les appareils que j'ai essayés: samsung, htc, android 4.0, 2.3, etc. J'ai intégré la carte dans mon application, et dans une petite application propre avec seulement le pager et la carte, avec le même résultat.
Pepe

@Pepe, pourriez-vous s'il vous plaît dire, comment obtenez-vous un GoogleMapobjet du ViewPager? Collé dessus pendant des semaines. Si vous n'avez pas bien compris la question, recherchez ma question, vous trouverez mon message. Répondez, s'il vous plaît.
azizbekian

Je veux ajouter que lorsque vous faites un, screen recordle problème ne semble pas se produire.
theblang

Réponses:


115

J'ai pu empêcher la surface noire d'être laissée après la transition en plaçant une autre vue avec un fond transparent au-dessus de l' ViewPagerintérieur 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
Génial! Ce n'est pas parfait, car parfois, pendant le déplacement du téléavertisseur, il apparaît une partie de la vue noire. Mais maintenant il ne reste plus à l'écran. Merci! (avez-vous une explication pour ce hack?)
Pepe

7
Pas vraiment. Je viens de remarquer où les commandes de zoom et de localisation se trouvaient au-dessus de la surface de la carte, le sentier noir n'apparaissait pas, j'ai donc placé une vue en haut pour couvrir toute la carte et cela a fonctionné. Je suis d'accord que ce n'est pas parfait - le fond noir semble faire partie de la fenêtre GLSurfaceView code.google.com/p/gmaps-api-issues/issues/detail?id=4639
Jeff Gilfelt

5
On dirait que cela a résolu mon problème ViewPager. Merci, mais il semble que j'ai un problème similaire avec un SlideMenu (menu de gauche comme G + / Yahoo), faire la même chose. Des pensées sur la correction d'une implémentation de SlideMenu?
Chrispix

@Chrispix n'anime pas le conteneur, n'utilise l'animation que dans le menu latéral, il l'a corrigé pour moi.
meh

1
J'ai fait cela et la solution programmatique ci-dessous, ils fonctionnent pendant que l'application est au premier plan, mais lorsque l'application est fermée et toujours en cours d'exécution et que vous y retournez, la carte reste toujours en haut ..
L7ColWinters

43

Eu le même problème avec SlidingMenu et ViewPager. J'ai remarqué que les boutons de contrôle dans le fragment de carte ne sont pas noirs dans l'artefact laissé derrière. J'ai résolu le problème en remplaçant la onCreateView()méthode deMapFragment (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;
}

Je l'utilise aussi pour SlidingMenu. Mais j'ai le problème de scintillement (avec l'animation glissante) et c'est inacceptable, ça a l'air horrible. L'avez-vous aussi? J'ai testé sur HTC One S. Ce qui est intéressant, je n'ai que ce problème avec l'animation d'ouverture et non lors de la fermeture de SlidingMenu
Michał K

Aucun des correctifs n'a fonctionné pour moi. J'ai pratiquement le même problème que Michal K. Utiliser SlidingMenu et ouvrir ou fermer lentement à une vitesse continue et il n'y a pas de problème. Ouvrez ou appuyez pour fermer la fenêtre et il semble que la carte est un peu en retard, laissant un espace vide jusqu'à ce que la diapositive se termine là où la carte revient à sa position correcte.
qubz

@qubz: À propos du «menu coulissant», essayez d'animer le menu et non la carte. Cela a résolu le problème pour moi, si la carte ne bouge pas.
meh

@meh: La carte peut bouger pendant que j'ouvre / ferme le SlidingMenu. Par déplacement, je veux dire CameraUpdate. Je vais voir si je peux mettre en pause l'animation, même si cela va gêner l'UX.
qubz

@Lubos Horacek: Pourriez-vous s'il vous plaît poster un exemple de code.J'obtiens une erreur d'exception de pointeur Null ..
avinash

7

Google a publié un correctif pour cela, mais seulement pour 4.1+ (vous n'avez pas besoin de télécharger une nouvelle version de PlayServices, ils ont utilisé un indicateur côté serveur)

Voici ce que j'utilise pour contourner le problème - S'assure que vous ne perdez aucun cycle de processeur sur les appareils> = 4.1

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

Je suppose que vous faites référence à la classe comme suit: FixMapFragment mapFragment = (FixMapFragment) fragmentManager.findFragmentById(R.id.map);et dans le fichier de mise en page: <fragment android:id="@+id/map" android:name="com.example.fragments.FixMapFragment" .... Cependant, la carte scintille toujours pour autant que je sache (Android 4.0.4).
JJD

@JJD J'ai une carte qui scintille, y a-t-il un moyen de résoudre ce problème?
Rat-a-tat-a-tat Ratatouille

@ Rat-a-tat-a-tatRatatouille Il n'y a pas de solution de contournement fiable pour éviter le scintillement de la vue de la carte pour autant que je sache.
JJD

Je ne sais pas si ce que j'ai fait pour le moment est correct ou non, mais cela fonctionne. J'ai réglé la visibilité de la vue de la carte sur invisible, puis après quelques secondes, la visibilité de la vue de la carte est redevenue visible. réduit le scintillement.
Rat-a-tat-a-tat Ratatouille

6

Ma solution de contournement: utilisez la nouvelle interface d'instantané de GoogleMap et affichez un instantané de la carte tout en faisant défiler la page.

Voici mon code pour définir l'instantané (il est dans le même fragment que la carte, appelé 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;
    }
}

Où "mapFragment" est mon SupportedMapFragment et "iv" est un ImageView (faites-le match_parent).

Et ici je contrôle le parchemin:

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

Mon fragment avec map (FragmentMap) est en position 1, donc je dois contrôler le défilement de la position 0 à 1 et de la position 1 à 2 (la première clause if). "getRegisteredFragment ()" est une fonction de mon FragmentPagerAdapter personnalisé, dans lequel j'ai un SparseArray (Fragment) appelé "registeredFragments".

Ainsi, chaque fois que vous faites défiler vers ou depuis votre carte, vous en voyez toujours un instantané. Cela fonctionne très bien pour moi.


Les autres réponses n'ont pas fonctionné pour moi - c'est la seule qui a fonctionné. Merci!
alice_silver_man

4

J'ai eu le même problème d'écran noir lors du défilement de la vue de liste, j'utilisais un fragment de carte avec une vue de liste dans le même écran.J'ai résolu ce problème avec l'utilisation de la propriété magique en xml où je parle de la vue de la liste, nous devons simplement mettre Android: scrollingCache = "false". Mon problème est résolu. Essayez cette propriété pour arrêter le décalage et le scintillement dans vos cartes.


2

Vous n'avez pas donné beaucoup de détails, donc je ne peux que suggérer beaucoup de choses. J'ai eu un problème similaire: l'écran scintillait entre les vues du téléavertisseur. Il s'est avéré que la mapView se gonflait lors du premier échange entre les pages.

Pour être clair, j'avais 3 pages dans mon pager et ma carte était la dernière page.

Pour résoudre ce problème, j'ai trouvé que définir le nombre de pages hors écran sur 2 (cela a fonctionné dans le cas ci-dessus) que lorsque mon fragment a commencé, il a chargé toutes les vues à la fois.

Voir http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit (int)


Merci, mais pas travaillé. Le problème est que la partie de l'écran couverte par la carte, lors du passage à un autre fragment, reste noire, couvrant la vue de cet autre fragment.
Pepe

hmmm intéressant. J'y réfléchirai.
Graham Smith

Je ne trouve pas setOffscreenPageLimit sur cette page à laquelle vous
êtes

0

Il existe une autre solution à ce problème. Je montre MapFragment dans un autre fragment. Le MapFragment est ajouté dynamiquement dans un FrameLayout.

La solution consiste à utiliser frameLayout.setVisibility (View.Visible) et frameLayout.setVisibility (View.Gone) sur les événements d'ouverture et de fermeture du menu glissant. Il nécessite l'ajout d'une vue supplémentaire. Et la zone noire a complètement disparu.

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

Aucune des méthodes ci-dessus n'a fonctionné pour moi, pas même d'autres que j'ai trouvées ailleurs. Enfin, j'ai choisi une solution partielle. J'écoute les changements de page via le onPageChangeListener du ViewPager, et je cache la carte lorsque sa page commence à défiler, et je la montre également à nouveau lorsqu'elle cesse de défiler. J'ai également ajouté une vue blanche à afficher lors du défilement.


Il peut être étendu pour capturer l'image actuelle de la vue en un bitmap, puis l'afficher sur une imageView pendant que le pagineur défile. De cette façon, les utilisateurs ne remarqueraient pas le piratage derrière cela. Cependant, j'ai trouvé ce calcul un peu trop cher car il ralentirait la réponse de l'interface utilisateur au balayage.
azyoot

-2

Copiez simplement mon fragment de carte personnalisé dans votre projet. Et si vous avez des lignes noires avec ScrollView en haut et en bas sur votre Android ScrollView: 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();
}

}

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.