web-dev-qa-db-fra.com

Android - défilement horizontal de plusieurs éléments visibles

EDIT: Voir ma propre réponse pour une solution facile

IMPORTANT: Bounty est offert comme moyen clair de modifier ViewPager afin de respecter le scénario décrit ci-dessous. Veuillez ne pas offrir HorizontalScrollView - le scénario de cycle de vie des fragments doit être entièrement couvert}

Je dois implémenter le défilement horizontal des vues Fragments- dans lesquelles un élément est au centre et les éléments situés à droite/à gauche sont partiellement ou totalement visibles. ViewPager est mal adapté à la tâche car il est centré sur l'affichage d'un élément à la fois.

Pour faciliter la compréhension, vous trouverez ci-dessous un rapide croquis dans lequel les éléments 1, 5 et 6 sont en dehors de la zone visible. Et et si vous voulez que ce nombre visualisable soit configurable, par exemple, en vue portrait, je ne montrerai que 2 éléments (ou éventuellement un seul).

Je n'essaie pas d'ajuster, disons, 3 éléments à l'écran, tant que l'élément central est affiché, les autres peuvent être recadrés. Sur le petit écran, il est correct d’avoir un élément central. À mesure que l’écran grandit, plusieurs éléments (le rognage est OK) doit être affiché.

Je comprends que cela ressemble à une galerie, mais là encore, les éléments ne sont pas de simples images mais Fragments avec une liste à défilement vertical dans chaque fragment

P.S. Trouvé ce blog par @Commonsware qui liste 3 approches différentes . Pour mon besoin j'aime # 3

enter image description here

47
Bostone

Celui-ci a une réponse étonnamment facile, je ne sais même pas pourquoi il n'a pas été posté tout de suite. Tout ce que je devais faire pour obtenir l'effet exact était de remplacer la méthode PagerAdapter#getPageWidth. Par défaut, il renvoie 1, mais si vous le définissez sur 0.5, vous obtiendrez 2 pages, 0.33, 3, etc. Selon la largeur du séparateur, vous devrez peut-être réduire légèrement la valeur.

Voir l'extrait suivant:

    @Override
    public float getPageWidth(final int position) {
        // this will have 3 pages in a single view
        return 0.32f;
    }
24
Bostone

Une fois, j'ai écrit quelque chose de similaire en tant que modèle. Dans mon exemple, je peux faire défiler avec les boutons de haut en bas et de côté. Vous pouvez le modifier un peu pour répondre à vos exigences. Dans mon exemple, j'ai 4 vues arrangées comme ceci: 

1 2
3 4

Ça ressemble à ça. Sur la photo, je fais défiler la vue 1 à droite pour voir 2:

Android View Scrolling

Le code se compose de ce xml: 

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:orientation="vertical"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent"
    >
      <LinearLayout
        Android:layout_height="350sp"
        Android:layout_width="320sp">
        <LinearLayout
            Android:id="@+id/viewContainer"
            Android:background="#CCCCCC"
            Android:layout_width="640sp"
            Android:layout_height="700sp">
        </LinearLayout>
     </LinearLayout>
      <TableLayout
            Android:id="@+id/tableLayout"
            Android:layout_width="320sp"
            Android:layout_height="fill_parent"
            Android:stretchColumns="1"
            Android:gravity="bottom"
            Android:layout_alignParentBottom="true">
            <TableRow
            Android:background="#333333"
            Android:gravity="bottom">       
            <Button
                Android:id="@+id/btnUp"
                Android:layout_width="60sp"
                Android:layout_height="50sp"
                Android:text="Lift U"
                />
            <Button
                Android:layout_width="60sp"
                Android:layout_height="50sp"
                Android:visibility="invisible"
            />
            <Button
                Android:layout_width="60sp"
                Android:layout_height="50sp"
                Android:visibility="invisible"
            />
            <Button
                Android:id="@+id/btnScreenUp"
                Android:layout_width="60sp"
                Android:layout_height="50sp"
                Android:layout_gravity="right"
                Android:text="Scrn U"
                />
            </TableRow>
            <TableRow
              Android:background="#444444"
              Android:layout_gravity="right">
              <Button
                Android:id="@+id/btnDown"
                Android:layout_width="60sp"
                Android:layout_height="50sp"
                Android:text="Lift D"
                />
              <Button
                Android:id="@+id/btnEnter"
                Android:layout_width="60sp"
                Android:layout_height="50sp"
                Android:text="Enter"
                />
               <Button
                Android:id="@+id/btnScreenLeft"
                Android:layout_width="60sp"
                Android:layout_height="50sp"
                Android:layout_gravity="right"
                Android:text="Scrn L"
                />
               <Button
                Android:id="@+id/btnScreenDown"
                Android:layout_width="60sp"
                Android:layout_height="50sp"
                Android:layout_gravity="right"
                Android:text="Scrn D"
                />
               <Button
                Android:id="@+id/btnScreenRight"
                Android:layout_width="60sp"
                Android:layout_height="50sp"
                Android:layout_gravity="right"
                Android:text="Scrn R"
                />
            </TableRow>
    </TableLayout>
</FrameLayout>

et ce code Java: 

import Android.app.Activity;
import Android.os.Bundle;
import Android.util.DisplayMetrics;
import Android.view.Gravity;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.view.Window;
import Android.widget.Button;
import Android.widget.LinearLayout;
import Android.widget.TextView;

public class ViewSwitcherTest extends Activity {

    private TextView view1, view2, view3, view4;
    private Button btnUp, btnEnter, btnDown, btnScreenDown, btnScreenUp, btnScreenLeft, btnScreenRight;
    private LinearLayout viewContainer;
//  private TableLayout tableLayout;
    private LinearLayout.LayoutParams layoutParams;
    private DisplayMetrics metrics = new DisplayMetrics();
    private int top = 0, left = 0;
    private float density = 1.0f;
//  private ViewSwitcher switcher;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        density = metrics.density;
        setContentView(R.layout.main);
//      Buttons
        btnEnter = (Button)findViewById(R.id.btnEnter);
        btnUp = (Button)findViewById(R.id.btnUp);
        btnDown = (Button)findViewById(R.id.btnDown);
        btnScreenDown = (Button)findViewById(R.id.btnScreenDown);
        btnScreenUp = (Button)findViewById(R.id.btnScreenUp);
        btnScreenLeft = (Button)findViewById(R.id.btnScreenLeft);
        btnScreenRight = (Button)findViewById(R.id.btnScreenRight);
//      --------
//      tableLayout = (TableLayout)findViewById(R.id.tableLayout);
        view1 = new TextView(this);
        view1.setBackgroundResource(R.drawable.view1);
        view1.setHeight((int)(350*density));
        view1.setWidth((int)(320*density));
        view1.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL);
        layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.setMargins(left, top, 0, 0);   
        viewContainer = (LinearLayout)findViewById(R.id.viewContainer);
        viewContainer.addView(view1, layoutParams);
        //Add 2nd view
        view2 = new TextView(this);
        view2.setBackgroundResource(R.drawable.view2);
        view2.setHeight((int)(350*density));
        view2.setWidth((int)(320*density));
        view2.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL);
        layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.setMargins(left, top, 0, 0);
        viewContainer.addView(view2, layoutParams); 
        //Add 3rd view
        view3 = new TextView(this);
        view3.setBackgroundResource(R.drawable.view3);
        view3.setHeight((int)(350*density));
        view3.setWidth((int)(320*density));
        view3.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL);
        top += 350*density;
        left += 640*density*(-1);
        layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.setMargins(left, top, 0, 0);
        viewContainer.addView(view3, layoutParams);     
        //add 4th view
        view4 = new TextView(this);
        view4.setBackgroundResource(R.drawable.view4);
        view4.setHeight((int)(350*density));
        view4.setWidth((int)(320*density));
        view4.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL);
        top += 0;
        left += 640*density;
        layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.setMargins(left, top, 0, 0);
        viewContainer.addView(view4, layoutParams);     
        btnEnter.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // Quit the application for now
                finish();
            }
        });
        btnScreenLeft.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                viewContainer.scrollBy(-10,0);
            }
        });
        btnScreenRight.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                viewContainer.scrollBy(10,0);
            }
        });
        btnScreenUp.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                viewContainer.scrollBy(0,-10);
            }
        });
        btnScreenDown.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                viewContainer.scrollBy(0,10);
            }
        });
//      view1.setOnKeyListener(new OnKeyListener() {            
//          @Override
//          public boolean onKey(View v, int keyCode, KeyEvent event) {
//              if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN)
//                  viewContainer.scrollBy(0,10);
//              return true;
//          }
//      });
    }
}

Les gros chiffres sur chaque écran sont des images de fond noir sur lesquelles sont peints ces chiffres. (Je ne l'ai pas posté ici parce que vous allez probablement modifier le code de toute façon).

2
Bevor

Nous faisons exactement ce que vous décrivez en utilisant un Gallery avec Fragments et un adaptateur de galerie étendant le BaseAdapter. Je recommanderais d’aller avec une galerie pour atteindre votre objectif (nous utilisons également un ViewPager pour la vue où nous n’avons pas besoin de voir les autres fragments).

1
Wryday

Si vous souhaitez étendre ViewPager, substituez simplement la méthode de dessin et setOffscreenPageLimit (int limit). Mais, je recommande d’utiliser FragmentPageAdapter si vos fragments eux-mêmes sont plutôt complexes.

Vous pouvez vérifier le code source ici ou si vous souhaitez vérifier celui du support, vous pouvez le faire ici.

0
Cris Stringfellow

En plus de la deuxième réponse de MrZander, jetez un coup d'œil à ceci https://stackoverflow.com/a/2655740/935075

0
sebataz

Découvrez cet article de blog sur la façon d'écrire une vue de défilement horizontal personnalisée pour obtenir quelque chose de similaire. L'exemple n'a qu'un seul écran visible à la fois, mais vous devriez pouvoir le modifier facilement pour répondre à vos besoins.

0
Joel

Je peux penser à deux manières possibles de mettre cela en œuvre.

  1. Par un ViewSwitcher . Voici une excellente vidéo YouTube montrant son fonctionnement avec un onGestureListener . Cependant, je ne sais pas si cela fonctionnera avec plusieurs vues, comme le montre votre photo.

  2. Au lieu de cela, vous pouvez utiliser HorizontalScrollView . Cependant, cela pose souvent problème si vous avez un ScrollView dans un autre, mais cela peut valoir le coup!

Faites-moi savoir comment ça se passe, Bonne chance!

0
MrZander