2012-11-01 5 views
12

Possiedo un (Sherlock) FragmentActivity con 2 frammenti a schede. Il frammento di sinistra è un GridView che mostra le immagini di un album e il frammento di destra è costituito da un ViewPager che viene utilizzato per visualizzare le singole immagini. Dal frammento di sinistra è possibile scorrere le immagini e selezionarne una. L'operazione di tabulazione (o scorrimento) sul frammento di destra mostrerà l'immagine e poiché si tratta di un ViewPager, è possibile scorrere l'immagine precedente o successiva.disabilita il passaggio da una scheda all'altra tra FragmentActivity

Questo funziona benissimo eccetto per il fatto che FragmentActivity vuole intercettare il tasto destro del mouse e tornare alla scheda sinistra. Vorrei impedire a FragmentActivity di intercettare gli swipes quando sono nella scheda di destra. Se dovessi disabilitare il passaggio da una scheda all'altra, sarebbe soddisfacente. Voglio solo che lo swiping sia dedicato alla scheda corrente e non essere utilizzato per spostarsi tra le schede.

Le seguenti immagini indicano il comportamento corrente. L'immagine giusta mostra cosa succede quando faccio un passaggio a destra. Come puoi vedere, la scheda a sinistra inizia a comparire. Voglio che lo scorrimento si applichi solo alla scheda destra solo in modo che sia possibile scorrere le immagini senza che venga visualizzata la scheda sinistra.

enter image description here

vedo soluzioni per il controllo strisciare all'interno di un ViewPager ma devono ancora trovare una soluzione per il controllo scorrendo tra i frammenti a schede.

Ecco l'XML per il frammento GridView e il frammento ViewPager:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:layout_width="fill_parent" 
       android:layout_height="fill_parent" 
       android:orientation="vertical"> 
    <FrameLayout android:id="@android:id/tabcontent" 
       android:layout_width="fill_parent" 
       android:layout_height="fill_parent"> 
    <GridView xmlns:android="http://schemas.android.com/apk/res/android" 
       android:id="@+id/gridview" 
       android:layout_width="fill_parent" 
       android:layout_height="fill_parent" 
       android:columnWidth="100dip" 
       android:gravity="center" 
       android:horizontalSpacing="4dip" 
       android:numColumns="auto_fit" 
       android:stretchMode="columnWidth" 
       android:verticalSpacing="4dip" /> 
    </FrameLayout> 
</LinearLayout> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:layout_width="fill_parent" 
       android:layout_height="fill_parent" 
       android:orientation="vertical"> 

    <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" 
            android:id="@+id/pager" 
            android:layout_width="fill_parent" 
            android:layout_height="0px" 
            android:layout_weight="1"/> 
</LinearLayout> 

Ecco un riepilogo di codice del frammento ViewPager:

public class FragmentFlash extends SherlockFragment { 

    private GestureDetector gestureDetector; 
    View.OnTouchListener gestureListener; 
    private ViewPager pager = null; 
    private int pagerPosition; 

    @Override 
     public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     pagerPosition = 0; 
     // Gesture detection 
     gestureDetector = new GestureDetector(new MyGestureDetector()); 
     gestureListener = new View.OnTouchListener() { 
      public boolean onTouch(View v, MotionEvent event) { 
       return gestureDetector.onTouchEvent(event); 
      } 
     }; 
     } 

    @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
           Bundle savedInstanceState) { 
     View v = inflater.inflate(R.layout.flash, container, false); 
     pager = (ViewPager) v.findViewById(R.id.pager); 
     pager.setOnTouchListener(gestureListener); 
     return v; 
    } 

    class MyGestureDetector extends SimpleOnGestureListener { 
     private static final int SWIPE_MIN_DISTANCE = 10; 
     private static final int SWIPE_MAX_OFF_PATH = 250; 
     private static final int SWIPE_THRESHOLD_VELOCITY = 50; 

     @Override 
     public boolean onDown(MotionEvent e) { 
     return true;//false; make onFling work with fragments 
     } 

     @Override 
     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 
     try { 
      if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) 
       return false; 
      else 
       // right to left swipe 
       if(distanceX > SWIPE_MIN_DISTANCE) { 
        if (pagerPosition < imageUrls.length-1) 
        pager.setCurrentItem(++pagerPosition); 
       // left to right swipe 
       } else if (distanceX < -SWIPE_MIN_DISTANCE) { 
        if (pagerPosition > 0) 
        pager.setCurrentItem(--pagerPosition); 
       } 
      return true; 
     } catch (Exception e) { 
      // nothing 
     } 
     return false; 
     } 
    } 

    private class ImagePagerAdapter extends PagerAdapter { 

     private String[] images; 
     private LayoutInflater inflater; 

     ImagePagerAdapter(String[] images) { 
     this.images = images; 
     inflater = mContext.getLayoutInflater(); 
     } 

     @Override 
     public void destroyItem(View container, int position, Object object) { 
     ((ViewPager) container).removeView((View) object); 
     } 

     @Override 
     public void finishUpdate(View container) { 
     } 

     @Override 
     public int getCount() { 
     return images.length; 
     } 

     @Override 
     public Object instantiateItem(View view, int position) { 
     final View imageLayout = inflater.inflate(R.layout.item_pager_image, null); 
     final ImageView imageView = (ImageView) imageLayout.findViewById(R.id.image); 
     final ProgressBar spinner = (ProgressBar) imageLayout.findViewById(R.id.loading); 

     byte[] image = ;//get byte array from file at images[position]; 
     if (null != image) { 
      Bitmap bitmap = BitmapFactory.decodeByteArray(image, 0, image.length); 
      imageView.setImageBitmap(bitmap); 
     } 
     ((ViewPager) view).addView(imageLayout, 0); 

     return imageLayout; 
     } 

     @Override 
     public boolean isViewFromObject(View view, Object object) { 
     return view.equals(object); 
     } 

     @Override 
     public void restoreState(Parcelable state, ClassLoader loader) { 
     } 

     @Override 
     public Parcelable saveState() { 
     return null; 
     } 

     @Override 
     public void startUpdate(View container) { 
     } 
    } 

    public void pagerPositionSet(int pagerPosition, String[] imageUrls) { 
     Log.i(Flashum.LOG_TAG, "FragmentFlash pagerPositionSet: " + pagerPosition); 
     if (pagerPosition >= 0) 
     this.pagerPosition = pagerPosition; 
     if (pager != null) { 
     pager.setAdapter(new ImagePagerAdapter(imageUrls)); 
     pager.setCurrentItem(this.pagerPosition); 
     } 
    } 

} 

Questa è l'item_pager_image.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:padding="1dip" > 

    <ImageView 
     android:id="@+id/image" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center" 
     android:adjustViewBounds="true" 
     android:contentDescription="@string/descr_image" /> 

    <ProgressBar 
     android:id="@+id/loading" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center" 
     android:visibility="gone" /> 

</FrameLayout> 

risposta

17

Ok, ho finalmente capito questo. Laurence Dawson era sulla strada giusta, ma invece di applicare CustomViewPager al frammento deve essere applicato a FragmentActivity. Vedete, il passaggio da una scheda all'altra, gestita dall'attività, è anche un adattatore ViewPager. Così, XML per l'attività è

<TabHost 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/tabhost" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <LinearLayout 
     android:orientation="vertical" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

     <TabWidget 
      android:id="@android:id/tabs" 
      android:orientation="horizontal" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_weight="0"/> 

     <FrameLayout 
      android:id="@android:id/tabcontent" 
      android:layout_width="0dp" 
      android:layout_height="0dp" 
      android:layout_weight="0"/> 

     <com.Flashum.CustomViewPager 
      android:id="@+id/pager" 
      android:layout_width="match_parent" 
      android:layout_height="0dp" 
      android:layout_weight="1"/> 

    </LinearLayout> 
</TabHost> 

E l'usanza ViewPager è come suggerito solo che che il costruttore permette di causare onInterceptTouchEvent a restituire false. Questo impedisce a FragmentActivity di agire sullo swipe in modo che possa essere dedicato al frammento!

public class CustomViewPager extends ViewPager { 

    private boolean enabled; 

    public CustomViewPager(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     this.enabled = **false**; 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     if (this.enabled) { 
      return super.onTouchEvent(event); 
     } 

     return false; 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent event) { 
     if (this.enabled) { 
      return super.onInterceptTouchEvent(event); 
     } 

     return false; 
    } 

    public void setPagingEnabled(boolean enabled) { 
     this.enabled = enabled; 
    } 
} 
+0

"invece di applicare CustomViewPager al frammento deve essere applicato a FragmentActivity". Non ho dichiarato che è necessario applicare questo al frammento e nemmeno il link che ho fornito. La tua risposta copia semplicemente il codice dal link fornito che spiega già come sovrascrivere onInterceptTouchEvent per disabilitare lo scorrimento. – Ljdawson

9

È necessario eseguire l'override del metodo onInterceptTouchEvent per ViewPager, si può fare questo estendendo ViewPager o visitare questo link per un tutorial su come aggiungere questo:

http://blog.svpino.com/2011/08/disabling-pagingswiping-on-android.html

+1

Ho provato questo codice e ho scoperto che è solo per il controllo dello scorrimento all'interno del frammento ViewPager. Non impedisce a FragmentActivity di provare a scorrere tra le schede. In altre parole, quando scorro verso destra non verrà chiamato solo MyGestureDetector :: onScroll(), ma anche la scheda sinistra inizierà a comparire sul lato sinistro, a indicare che FragmentActivity sta anche rilevando ed elaborando lo scorrimento. – cdavidyoung

+0

Non sono sicuro del motivo per cui hai persino un rilevatore di gesti, il ViewPager gestisce tutto il swiping per te – Ljdawson

+0

Ho fatto in modo che potessi regolare la sensibilità del passaggio. Ora con piccoli swipes posso rimanere nella scheda giusta. Tuttavia, con uno scorrimento normale, FragmentActivity lo rileva e prende il sopravvento.A proposito, ho provato a disattivare il mio rilevatore di gesti e anche con il ViewPager personalizzato a cui si fa riferimento non aiuta. – cdavidyoung