2012-11-01 40 views
12

Tôi có một (Sherlock) FragmentActivity với 2 đoạn có tab. Phần bên trái là một GridView hiển thị hình ảnh của một album và phân đoạn bên phải bao gồm một ViewPager được sử dụng để xem các ảnh riêng lẻ. Từ phần bên trái, bạn có thể cuộn qua các ảnh và chọn một ảnh. Tabbing (hoặc swiping) trên các mảnh bên phải sẽ hiển thị hình ảnh và bởi vì nó là một ViewPager bạn có thể swipe để trước hoặc hình ảnh tiếp theo.tắt tính năng vuốt giữa các tab trong FragmentActivity

Tác phẩm này tuyệt vời ngoại trừ FragmentActivity muốn chặn thao tác vuốt sang phải và di chuyển trở lại tab bên trái. Tôi muốn ngăn chặn FragmentActivity chặn các swipes khi tôi ở bên phải tab. Nếu tôi phải tắt tính năng vuốt giữa các tab thì nó sẽ thỏa đáng. Tôi chỉ muốn swiping được dành riêng cho các tab hiện tại và không được sử dụng để di chuyển giữa các tab.

Các hình ảnh sau chỉ ra hành vi hiện tại. Hình ảnh bên phải hiển thị những gì xảy ra khi tôi vuốt sang phải. Như bạn thấy, tab bên trái bắt đầu xuất hiện. Thay vào đó, tôi muốn vuốt để chỉ áp dụng cho tab bên phải để tôi có thể vuốt giữa các hình ảnh mà không xuất hiện tab bên trái.

enter image description here

tôi thấy các giải pháp để kiểm soát trượt trong một ViewPager nhưng vẫn chưa tìm ra giải pháp để kiểm soát vuốt giữa các mảnh vỡ tab.

Đây là xml cho đoạn GridView và đoạn 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> 

Dưới đây là một bản tóm tắt mã của đoạn 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); 
     } 
    } 

} 

Đây 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> 

Trả lời

17

Ok, cuối cùng tôi figured this out. Laurence Dawson đã đi đúng hướng nhưng thay vì áp dụng CustomViewPager cho đoạn nó cần phải được áp dụng cho FragmentActivity. Bạn thấy đấy, chuyển đổi giữa các tab, được quản lý bởi hoạt động, cũng là một bộ điều hợp ViewPager. Như vậy, xml cho hoạt động này là

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

Và tùy chỉnh ViewPager được như đề nghị trừ rằng các nhà xây dựng cho phép nó gây onInterceptTouchEvent để trả về false. Điều này ngăn chặn FragmentActivity hành động trên swipe để nó có thể được dành riêng cho các mảnh!

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

"thay vì áp dụng CustomViewPager cho đoạn mà nó cần phải được áp dụng cho FragmentActivity". Tôi đã không nói rằng bạn cần phải áp dụng điều này cho các mảnh và không liên kết tôi cung cấp. Câu trả lời của bạn chỉ sao chép mã từ liên kết được cung cấp đã giải thích đầy đủ cách ghi đè onInterceptTouchEvent để tắt tính năng vuốt. – Ljdawson

9

Bạn cần ghi đè phương thức onInterceptTouchEvent cho ViewPager của mình, bạn có thể làm điều này bằng cách mở rộng ViewPager hoặc truy cập liên kết này cho một hướng dẫn tuyệt vời về việc bổ sung này:

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

+1

Tôi đã thử mã này và nhận thấy rằng nó chỉ dành cho việc điều khiển vuốt trong phần ViewPager. Nó không ngăn FragmentActivity cố gắng vuốt giữa các tab. Nói cách khác, khi tôi vuốt sang phải không chỉ MyGestureDetector :: onScroll() được gọi mà còn cả tab bên trái sẽ bắt đầu xuất hiện ở phía bên trái cho biết FragmentActivity cũng phát hiện và xử lý thao tác vuốt. – cdavidyoung

+0

Tôi không chắc chắn lý do tại sao bạn thậm chí có một máy dò cử chỉ, ViewPager xử lý tất cả các swiping cho bạn – Ljdawson

+0

Tôi đã làm điều đó để tôi có thể điều chỉnh độ nhạy của swipe. Bây giờ với rất nhỏ swipes tôi có thể ở trong tab bên phải. Tuy nhiên, với thao tác vuốt bình thường, FragmentActivity sẽ phát hiện và chiếm đoạt nó.BTW, tôi đã thử vô hiệu hóa bộ dò cử chỉ của tôi và thậm chí với ViewPager tùy chỉnh mà bạn đã tham chiếu, nó không giúp ích gì. – cdavidyoung

Các vấn đề liên quan