2012-08-17 15 views
9

Sto scrivendo un'applicazione che utilizza ViewPager per ospitare Fragment s.Lo scorrimento uniforme non funziona in ViewPager (libreria di supporto)

Quando cambio frammento a livello di codice, la funzione di scorrimento uniforme non funziona. Uso il metodo ViewPager.setCurrentItem (int item, boolean smoothScroll) `.

Forse qualcuno conosce una soluzione a questo bug? Forse con le animazioni?

MODIFICA: Sto utilizzando il pacchetto di supporto. E il problema è che se io uso ViewPager.setCurrentItem(2, true) o ViewPager.setCurrentItem(2, false) il risultato è lo stesso. La visualizzazione cambia molto velocemente (non senza intoppi).

+0

Prima di tutto, SOLO il viewpager esiste sul pacchetto di supporto. Ora la domanda sarebbe: qual è il problema che stai affrontando? se fai setCurrentItem (2, false) cosa fa invece? puoi modificare la tua domanda per essere un po 'più specifica? –

+0

Quindi metto mPager.setCurrentItem (1, true); in un postrunnable per dare un suggerimento all'utente che l'oggetto è un viewpager. Il problema è che non c'è animazione quando la metto nel postrunnable che uccide il punto. C'è un altro modo per farlo? – MinceMan

risposta

-1

Ciò che ha funzionato per me era chiamare mPager.setCurrentItem dopo mPagerAdapter.notifyDataSetChanged() e non come eseguibile pubblicato.

Ecco un esempio (in MonoDroid):

public void UpdateDetialsView(string type) 
    { 
     string typeName4 = Java.Lang.Class.FromType(typeof(ParcelRecordComplaintDetailsView)).Name; 

     if (_fragments.Count > 3) 
     { 
      _fragments.RemoveAt(_fragments.Count - 1); 

      //////////////////////////////////////////////////////////// 
      // Called here it wasn't working for me (Posted or not) 

      //_viewPager.Post(new Action(() => { _viewPager.SetCurrentItem(3, true); })); 
     } 

     _fragments.Add(Fragment.Instantiate(Activity, typeName4)); 

     _pagerAdapter.NotifyDataSetChanged(); 

     //////////////////////////////////////////////////////////// 
     // Called here it works as expected 

     _viewPager.SetCurrentItem(3, true); 
    } 

dove

protected MyAdapter _pagerAdapter; 
    protected ViewPager _viewPager; 
    private List<Android.App.Fragment> _fragments; 

e

public class MyAdapter : Android.Support.V13.App.FragmentStatePagerAdapter 
    { 
     private List<Fragment> _fragments; 

     public override Java.Lang.Object InstantiateItem(View p0, int p1) 
     { 
      return base.InstantiateItem(p0, p1); 
     } 

     public MyAdapter(Android.App.FragmentManager fm) : base(fm) 
     { 

     } 

     public MyAdapter(Android.App.FragmentManager fm, List<Android.App.Fragment> fragments) : base(fm) 
     { 
      _fragments = fragments; 
     } 

     public override int Count 
     { 
      //get { return FRAG_PAGES; } 
      get { return _fragments.Count; } 
     } 

     public override Android.App.Fragment GetItem(int p0) 
     { 
      return _fragments[p0]; 
     } 

     public override float GetPageWidth(int p0) 
     { 
      //return base.GetPageWidth(p0); 

      return (float) (0.5f); 
     } 

     public override int GetItemPosition(Java.Lang.Object p0) 
     { 
      //return base.GetItemPosition(p0); 
      return PagerAdapter.PositionNone; 
     } 
    } 
+0

Interessante. Stai cambiando i frammenti, è corretto? Non cambio i frammenti stessi solo cercando di passare da uno all'altro. Proverò qualcosa con questa idea di NotifyDataSetChanged(). Grazie! – Tautvydas

+0

Sì, li sto cambiando dinamicamente. Ho 4 pannelli di mezzo schermo che sono implementati come frammenti e ospitati all'interno di un ViewPager. Ogni pannello mostra i dettagli di un oggetto dal pannello alla sua sinistra (ed è il motivo per cui li sto aggiornando dinamicamente). Non penso che NotifyDataSetChanged dovrebbe ferire qualsiasi cosa, se la chiami senza aver prima cambiato nulla, anche se non sono sicuro che sarà d'aiuto (se così non fosse, forse potresti cambiare qualcosa in un frammento molto minore, cambiarlo indietro, quindi chiamare NotifyDataSetChanged, per forzarlo?). – samosaris

17

Ho risolto questo con la creazione di un MyViewPager che sostituisce il ViewPager. mScroller usando la riflessione.

public class MyViewPager extends ViewPager 
{ 
    public MyViewPager(Context context, AttributeSet attrs) 
    { 
    super(context, attrs); 
    setMyScroller(); 
    } 
    private void setMyScroller() 
    { 
    try 
    { 
      Class<?> viewpager = ViewPager.class; 
      Field scroller = viewpager.getDeclaredField("mScroller"); 
      scroller.setAccessible(true); 
      scroller.set(this, new MyScroller(getContext())); 
    } catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
    } 

    public class MyScroller extends Scroller 
    { 
    public MyScroller(Context context) 
    { 
     super(context, new DecelerateInterpolator()); 
    } 

    @Override 
    public void startScroll(int startX, int startY, int dx, int dy, int duration) 
    { 
     super.startScroll(startX, startY, dx, dy, 1000 /*1 secs*/); 
    } 
    } 
} 
+0

Questa soluzione è brutta, ma dovrebbe funzionare! Grazie, proverò ad attuare il tuo suggerimento. – Tautvydas

+0

Concordo sul fatto che si tratti di un bug di ViewPager (IMO) –

+5

Se si utilizza questa soluzione alternativa e ProGuard, è necessario aggiungerlo alla configurazione di ProGuard: '-keepclassmembers class android.support.v4.view. ViewPager { \t private android.widget.Scroller mScroller; } ' – Iftah

Problemi correlati