2012-11-01 13 views
12

Ich habe eine (Sherlock) FragmentAktivität mit 2 Tabbed Fragmenten. Das linke Fragment ist eine GridView, die Bilder eines Albums anzeigt und das rechte Fragment besteht aus einem ViewPager, mit dem einzelne Bilder angezeigt werden. Vom linken Fragment können Sie durch die Bilder blättern und eines auswählen. Mit der Tab-Taste (oder Wischen) über das rechte Fragment wird das Bild angezeigt, und da es sich um einen ViewPager handelt, können Sie zum vorherigen oder nächsten Bild wischen.Disable wischen zwischen Registerkarten in FragmentActivity

Dies funktioniert gut, außer dass die FragmentActivity will das Recht Swipe und bewegt zurück auf die linken Registerkarte abzufangen. Ich möchte verhindern, dass die FragmentActivity die Swipes abfängt, wenn ich auf der rechten Registerkarte bin. Wenn ich das Wischen zwischen den Tabs deaktivieren müsste, wäre das zufriedenstellend. Ich möchte nur, dass das Wischen dem aktuellen Tab zugewiesen wird und nicht zum Wechseln zwischen Tabs verwendet wird.

Die folgenden Bilder zeigen das aktuelle Verhalten. Das rechte Bild zeigt, was passiert, wenn ich nach rechts wische. Wie Sie sehen können, erscheint die linke Registerkarte. Ich möchte, dass der Swipe nur auf die rechte Registerkarte angewendet wird, sodass ich zwischen den Bildern wischen kann, ohne dass die linke Registerkarte angezeigt wird.

enter image description here

Ich sehe Lösungen innerhalb eines ViewPager klauen zu kontrollieren, aber haben noch eine Lösung finden zwischen Registerkarten Fragmente zu steuern klauen.

Hier ist der XML-Code für das Gridview-Fragment und dem ViewPager Fragment:

<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> 

Hier ein Code Zusammenfassung des ViewPager Fragment:

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); 
     } 
    } 

} 

Dies ist 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> 

Antwort

17

Ok, ich das endlich herausgefunden. Laurence Dawson war auf dem richtigen Weg, aber anstatt den CustomViewPager auf das Fragment anzuwenden, muss er auf die FragmentActivity angewendet werden. Sie sehen, dass der Wechsel zwischen den Registerkarten, der von der Aktivität verwaltet wird, auch ein ViewPager-Adapter ist. So xml für die Aktivität ist

<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> 

Und der Brauch ViewPager als Ausnahme, dass vorgeschlagen, dass der Konstruktor ermöglicht es onInterceptTouchEvent zu verursachen false zurück. Dadurch wird verhindert, dass die FragmentActivity auf den Swipe wirkt, sodass sie dem Fragment zugewiesen werden kann!

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

"anstatt den CustomViewPager auf das Fragment anzuwenden, muss es auf die FragmentActivity angewendet werden". Ich habe nicht gesagt, dass Sie dies auf das Fragment anwenden müssen und auch nicht den Link, den ich zur Verfügung gestellt habe. Ihre Antwort kopiert nur den Code aus dem angegebenen Link, der bereits erklärt, wie Sie das onInterceptTouchEvent überschreiben können, um den Swiping zu deaktivieren. – Ljdawson

9

Sie benötigen die onInterceptTouchEvent Methode für Ihre ViewPager außer Kraft zu setzen, Sie können dies tun, durch die Erweiterung ViewPager oder diesen Link für ein großes Tutorial besuchen diese auf und fügte hinzu:

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

+1

Ich habe diesen Code ausprobiert und festgestellt, dass er nur für das Swiping innerhalb des ViewPager-Fragments verwendet wird. Es verhindert nicht, dass die FragmentActivity versucht, zwischen den Registerkarten zu wechseln. Mit anderen Worten, wenn ich nach rechts wische, wird nicht nur MyGestureDetector :: onScroll() aufgerufen, sondern auch die linke Registerkarte wird auf der linken Seite erscheinen und zeigt an, dass FragmentActivity auch den Swipe erkennt und verarbeitet. – cdavidyoung

+0

Ich bin nicht sicher, warum Sie sogar einen Gesten-Detektor haben, der ViewPager behandelt alle Wischen für Sie – Ljdawson

+0

Ich tat das, so dass ich die Empfindlichkeit der Swipe anpassen konnte. Jetzt mit sehr kleinen Swipes kann ich innerhalb der richtigen Registerkarte bleiben. Bei einem normalen Swipe erkennt die FragmentActivity dies und übernimmt sie.Übrigens, ich habe versucht, meinen Gesten-Detektor zu deaktivieren, und selbst mit dem benutzerdefinierten ViewPager, auf den Sie verwiesen haben, hilft das nicht. – cdavidyoung

Verwandte Themen