2011-10-08 15 views
47

EDIT: Vedere la mia risposta per una facile soluzioneAndroid - scorrimento orizzontale di più elementi visualizzabili

IMPORTANTE: Bounty è offerto per modo chiaro per modificare ViewPager per soddisfare lo scenario descritto di seguito. Si prega di non offrire HorizontalScrollView - ho bisogno di piena scenario Frammento del ciclo di vita coperto

ho bisogno di attuare lo scorrimento orizzontale di Fragments vista basati in cui un prodotto è in centro e gli elementi a destra/sinistra sono parzialmente o completamente visibile. ViewPager non è adatto per l'attività poiché si concentra sulla visualizzazione di un elemento in ogni momento.

Per semplificare la comprensione è uno schizzo veloce in cui gli elementi 1, 5 e 6 sono al di fuori dell'area visualizzabile. E voglio rendere questo numero visibile configurabile così, per esempio in vista verticale, mostrerò solo 2 (o forse solo uno) elementi.

Non sto cercando di adattarmi per dire 3 elementi sullo schermo, purché l'elemento centrale sia mostrato, altri possono essere ritagliati. Sul piccolo schermo è OK avere 1 oggetto centrale e come schermo cresce in dimensioni multiple (ritagliate va bene) gli articoli dovrebbero essere mostrati

Capisco che questa sembra una galleria ma ancora una volta gli elementi non sono semplici immagini ma Fragments con un elenco verticalmente scorrevole in ogni frammento

PS Trovato questo blogpost da @Commonsware che è list 3 different approaches. Per il mio bisogno mi piace # 3

enter image description here

+2

Questo link vi aiuterà a [HorizontalListView] (http://www.dev-smart.com/archives/34) – surendra

+0

ho bisogno di avere di scorrimento orizzontale di frammenti con ognuno con ListView verticale – Bostone

+0

Ho un'esigenza molto simile. Stavo usando Gallery fino a quando non ho iniziato a filtrare oggetti ovunque, dopo aver aggiunto un oggetto ListView alle viste degli elementi della galleria. Attualmente sto pensando di correggere la Gallery dal momento che è più facile che provare a correggere ViewPager. –

risposta

24

Questo ha una risposta sorprendentemente facile, non sono nemmeno sicuro del motivo per cui non è stato pubblicato subito. Tutto quello che dovevo fare per ottenere l'effetto esatto era di sostituire il metodo PagerAdapter#getPageWidth. Di default restituisce 1, ma se lo imposti a 0.5 otterrai 2 pagine, 0,33 ne darai 3, ecc. A seconda della larghezza del separatore tra gli oggetti del cercapersone potresti dover diminuire leggermente il valore.

vedere il seguente frammento di codice:

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

Mi vengono in mente due modi per implementare questa possibilmente.

  1. Da un ViewSwitcher. Ecco un eccellente YouTube video che mostra come funziona con uno onGestureListener. Tuttavia, non sono sicuro che questo funzionerà con più visualizzazioni come mostra la tua foto.

  2. In alternativa, è possibile utilizzare uno HorizontalScrollView. Tuttavia, questo spesso causa problemi se si ha uno ScrollView all'interno di un altro, ma potrebbe valerne la pena!

Fammi sapere come va, Buona fortuna!

+0

Si prega di leggere la nota di taglie – Bostone

0

Oltre alla seconda risposta di MrZander un'occhiata a questo https://stackoverflow.com/a/2655740/935075

+0

Non chiudere nemmeno. Non ho bisogno di "snap-to-place" o rilevamento di gesti orizzontali. Tutto ciò è curato da ViewPager. Si prega di leggere una nota di taglie – Bostone

0

Check out this blog post su come scrivere una vista di scorrimento orizzontale su misura per ottenere qualcosa di simile. L'esempio ha solo una schermata visibile alla volta, ma dovresti essere in grado di modificarla facilmente per le tue esigenze.

+0

Ho un'implementazione basata su ViewPager che fa uno schermo alla volta. Richiedo specificamente viste multiple/parziali nella taglia – Bostone

+0

Destra, il codice in quell'esempio non farà esattamente quello che vuoi così com'è, ma è un ottimo punto di partenza. Nell'esempio, le viste interne hanno la stessa larghezza della vista esterna (la vista di scorrimento orizzontale), quindi, naturalmente, solo una di esse è visibile alla volta. È possibile modificare il codice in modo che le viste interne siano più ristrette rispetto alla vista di scorrimento esterna. Ciò consentirà a più di uno di essere visibile allo stesso tempo.Se si esegue questa operazione, sarà inoltre necessario modificare il valore "scrollTo" in modo che la vista centrale sia centrata correttamente quando si verifica lo "snap". – Joel

+0

Sto cercando di fare lo stesso con ViewPager. Non voglio percorrere la rotta HorizontalScrollView da allora mi mancherà un sacco di funzionalità relative ai frammenti di ViewPager – Bostone

2

Una volta ho scritto qualcosa di simile come modello. Nel mio esempio posso scorrere con i pulsanti su e giù e lateralmente. Potresti modificarlo un po 'per soddisfare le tue esigenze.Nel mio esempio ho 4 Visualizzazioni disposte in questo modo:


Ecco come si presenta. Nella foto ho scorrere da vista 1 verso destra per visualizzare 2:

Android View Scrolling

Il codice costituita dal presente 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> 

e questo codice 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; 
//   } 
//  }); 
    } 
} 

I grandi numeri su ogni schermo sono immagini di sfondo nere con quei numeri dipinti su di esso. (Non l'ho postato qui perché probabilmente modificherete il codice comunque).

+0

No, non posso percorrere questa rotta. Ho una configurazione molto più complicata in cui utilizzo ViewPager e FragmentStatePagerAdapter per occuparmi del ciclo di vita di Fragments. A questo punto mi viene quasi l'idea di modificare ViewPager e cercare suggerimenti su quale parte devo modificare/estendere – Bostone

0

Se si desidera estendere ViewPager, basta sovrascrivere il metodo di disegno e impostareOffSpyPageLimit (limite int). Ma, mi raccomando di usare FragmentPageAdapter se i frammenti stessi sono un po 'complessi.

È possibile controllare il codice sorgente here o se si desidera controllare quello del pacchetto di supporto lo si può fare here.

+0

Sto usando FragmentStatePagerAdapter ma che si occupa di un singolo frammento e ho bisogno di ristrutturare in modo la lista è posizionata sullo schermo con più Frammenti in vista. Sono a conoscenza della sorgente del codice, grazie – Bostone

+0

Se i frammenti a parte quello principale non devono essere attivi, basta ridurre quello centrale con uno zoom e aggiungere un'immagine su entrambi i lati che rappresenta il componente/frammento. Crea l'immagine una volta, quindi disegnale mentre scorri su quella zona. –

+0

Lo fa. Soprattutto se sei nel tablet e i frammenti laterali sono completamente visibili – Bostone

1

Stiamo facendo qualcosa esattamente come si sta descrivendo utilizzando uno Gallery con Fragments e un adattatore di galleria che estende il BaseAdapter. Consiglierei di andare con una galleria per raggiungere il tuo obiettivo (usiamo anche un ViewPager per la vista in cui non abbiamo bisogno di vedere gli altri frammenti).

Problemi correlati