web-dev-qa-db-fra.com

Déterminer si une vue est à l'écran - Android

Je suis un peu coincé avec celui-ci - d'abord et avant tout, le lien suivant a été utile, mais j'ai trouvé un problème de visibilité:

Le lien: Vérifier la visibilité de la vue

J'ai une vue de défilement (parent) et un certain nombre de sous-vues (LinearLayout -> TableLayout) etc. Il y a un certain nombre d'éléments que j'ai définis sur View.GONE Dans le XML (Android:visibility="gone").

J'ai un code simple pour déterminer s'il est visible ou non en utilisant getVisibility() cependant quand je mets l'élément à View.VISIBLE Et j'essaye immédiatement getDrawingRect() j'obtiens un Rect avec des zéros à tous les niveaux. Tout clic supplémentaire obtient les coordonnées correctes.

Maintenant, cela pourrait être dû au fait que la vue n'a jamais été dessinée (telle que définie dans le XML), ce qui ne renvoie aucune coordonnée, mais je définis View.VISIBLE Avant d'essayer de déterminer la visibilité de l'écran. Serait-il possible que j'aie besoin d'une sorte de rappel de la part de onDraw ()? ou peut-être définir la visibilité des éléments cachés dans le code. Un peu ennuyeux; (

Du code:

Rect scrollBounds = new Rect();
scroll.getHitRect(scrollBounds);

Rect viewBounds = new Rect();

if (view.getVisibility() == View.GONE) {
    view.setVisibility(View.VISBLE)


    viewBounds.getDrawingRect(viewBounds);
    if (!Rect.intersects(scrollBounds, viewBounds) {
        // do somthing
    } 
}

Zone de disposition comme suit:

  • ScrollView
    • LinearLayout
      • TableLayout
        • Button
        • HiddenView

Bien sûr, il est fort probable que j'agisse complètement dans le mauvais sens - je veux simplement m'assurer que la vue de défilement se positionne de sorte que la vue qui est devenue visible puisse être vue dans son intégralité.

Si d'autres informations sont nécessaires, faites-le moi savoir!

21
Hamz4h_

Ok donc merci à OceanLife de m'avoir pointé dans la bonne direction! Il y avait en effet un rappel requis et ViewTreeObserver.OnGlobalLayoutListener() a fait l'affaire. J'ai fini par implémenter l'écouteur par rapport à ma classe de fragments et je l'ai récupéré là où j'en avais besoin. Merci aussi pour l'avertissement concernant les appels multiples, j'ai résolu cela en utilisant la méthode removeOnGlobalLayoutListener() - fonctionne à merveille.

Code:

...

// vto initialised in my onCreateView() method

vto = getView().getViewTreeObserver();
vto.addOnGlobalLayoutListener(this);

...

@Override
    public void onGlobalLayout() {

        final int i[] = new int[2];
        final Rect scrollBounds = new Rect();

        sView.getHitRect(scrollBounds);
        tempView.getLocationOnScreen(i);

        if (i[1] >= scrollBounds.bottom) {
            sView.post(new Runnable() {
                @Override
                public void run() {
                    sView.smoothScrollTo(0, sView.getScrollY() + (i[1] - scrollBounds.bottom));
                }
            });
        }

        vto.removeOnGlobalLayoutListener(this);
    }

Je dois juste faire un peu de nettoyage maintenant ...

19
Hamz4h_

Donc, si je lis bien, le problème que vous rencontrez est que vous voulez connaître les dimensions d'une vue dans votre mise en page pour savoir si vous avez une intersection avec le parent ScrollView.

Ce que je pense que vous voyez (comme vous y avez fait allusion) est l'instruction de dessiner la vue en cours d'envoi, puis dans une sorte de condition de concurrence, le moteur de rendu résout les mesures pour la mise en page et le rendu réel où les objets de vue obtiennent des tailles réelles. Une façon de déterminer le type de dimensions d'une vue à l'écran consiste à utiliser l'arborescence de mise en page. Nous utilisons cet observateur pour résoudre les dimensions d'un écran lors de l'utilisation de l'API Google Charts, qui nécessite de définir une largeur et une hauteur de pixel ... ce qui bien sûr sur Android est probablement le plus gros problème auquel sont confrontés les développeurs Donc, observez (jeu de mots voulu);

final ViewTreeObserver vto = chart.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

  /**
   * @see Android.view.ViewTreeObserver.OnGlobalLayoutListener#onGlobalLayout()
   */
  @SuppressWarnings("deprecation")
  @Override
  public void onGlobalLayout() {
    if (view.getVisibility() == View.GONE) {
      view.setVisibility(View.VISBLE)
      viewBounds.getDrawingRect(viewBounds);
      if (!Rect.intersects(scrollBounds, viewBounds) {
        // do something
      } 
    }
  }
});

Mot d'avertissement: onGlobalLayout sera appelé plusieurs fois à mesure que le moteur de rendu se rapproche de la solution finale. Le dernier appel est celui que nous prenons.

Cela vous fournira un mécanisme pour effectuer des actions sur une vue dessinée, comme obtenir la largeur et la hauteur d'un composant de vue. J'espère que cela vous aide.

À part: Les gars intelligents de Square ont conçu une bibliothèque FEST Hamcrest qui vous permettra d'écrire un test à côté de Robotium. Vérifiez-le .

11
OceanLife