2011-11-30 46 views
27

Tôi đang cố gắng tạo bố cục với ViewFlipper chứa ScrollViews. Ý tưởng là để phát hiện swipes ngang để di chuyển đến trước/tiếp theo ScrollView. Hơn nữa, ScrollView chứa một ViewFlipper khác có chứa ImageView với một máy dò swipe dọc để đi đến ImageView trước đó/tiếp theo. Khi tôi thay thế ScrollView bằng LinearLayout, cả hai thiết bị dò cử chỉ hoạt động bình thường, nhưng với ScrollView, không có công cụ nào (các trình nghe cử chỉ không kích hoạt). Tại sao việc sử dụng ScrollView vô hiệu hóa các trình dò ​​cử chỉ của tôi? Làm thế nào tôi có thể làm cho nó hoạt động?Phát hiện cử chỉ và vấn đề ScrollView

Hoạt động

public class ProduitHome extends Activity{ 

    private Resources res; 
    float density; 

    private int position, parent_id;; 
    private int num_products; 

    private Produit produit; 
    private ImageDownloader mImageLoader; 

    private ViewFlipper product_viewflipper; 
    private ScrollView current_product_layout; 
    Animation next_product_out, next_product_in, previous_product_in, previous_product_out; 

    private GestureDetector galleryGestureDetector; 
    private View.OnTouchListener galleryGestureListener; 

    private GestureDetector productGestureDetector; 
    private View.OnTouchListener productGestureListener; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 

     super.onCreate(savedInstanceState); 
     setContentView(R.layout.produit_home); 

     num_products = GlobalData.map_list_produits.get(parent_id).size(); 

     product_viewflipper = (ViewFlipper) findViewById(R.id.product_viewflipper); 

     LayoutInflater inflater = getLayoutInflater(); 


     // Add num_products view to the viewflipper 

     for(int i=0; i<num_products; i++){ 
      ScrollView product_detail = (ScrollView) inflater.inflate(R.layout.produit_detail, null); 
      product_viewflipper.addView(product_detail); 
     } 


     // Set data and show current product 

     current_product_layout = (ScrollView) product_viewflipper.getChildAt(position); 
     product_viewflipper.setDisplayedChild(position); 

     setProductData(); 


     // Set swipe listener to switch product 

     productGestureDetector = new GestureDetector(new ProductGestureListener()); 
     productGestureListener = new View.OnTouchListener() 
     { 
      public boolean onTouch(View v, MotionEvent event) 
      { 
       if (productGestureDetector.onTouchEvent(event)) 
       { 
        return true; 
       } 
       else{ 
        return false; 
       } 
      } 
     }; 

     product_viewflipper.setOnTouchListener(productGestureListener); 


     // Set switch product animation 

     next_product_out = AnimationUtils.loadAnimation(this, R.anim.next_product_out); 
     next_product_in = AnimationUtils.loadAnimation(this, R.anim.next_product_in); 
     previous_product_in = AnimationUtils.loadAnimation(this, R.anim.previous_product_in); 
     previous_product_out = AnimationUtils.loadAnimation(this, R.anim.previous_product_out); 

    } 


    class VerticalSwipeListener extends SimpleOnGestureListener { 

     @Override 
     public boolean onDown(MotionEvent e) { 
      return true; 
     } 

     @Override 
     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 

      final int SWIPE_MIN_DISTANCE = 80; 
      final int SWIPE_MAX_OFF_PATH = 250; 
      final int SWIPE_THRESHOLD_VELOCITY = 200; 

      try { 
       if (Math.abs(e1.getX() - e2.getX()) > SWIPE_MAX_OFF_PATH) 
        return false;     

       ViewFlipper gallery = (ViewFlipper)current_product_layout.findViewById(R.id.product_gallery); 

       if(e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) { 
        gallery.showNext();      
       } else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) { 
        gallery.showPrevious(); 
       } 
       ((RadioGroup)current_product_layout.findViewById(R.id.gallery_nav)).check(gallery.getDisplayedChild()); 
      } catch (Exception e) { 
      } 
      return false; 
     } 
    } 


    class ProductGestureListener extends SimpleOnGestureListener { 

     @Override 
     public boolean onDown(MotionEvent e) { 
      return true; 
     } 

     @Override 
     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 

      final int SWIPE_MIN_DISTANCE = 120; 
      final int SWIPE_MAX_OFF_PATH = 250; 
      final int SWIPE_THRESHOLD_VELOCITY = 200; 

      if(!Utils.IsOnline(ProduitHome.this)){ 
       SRPDialogs.show(ProduitHome.this, SRPDialogs.NOT_CONNECTED); 
      } 
      else{ 

       try { 
        if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) 
         return false; 
        if(e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 

         // show next product 

        } else if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 

        // show previous product 

        } 
       } catch (Exception e) { 
       } 
      } 
      return false; 
     } 
    } 

    public void setProductData(){ 

     produit = GlobalData.map_produits.get(GlobalData.map_list_produits.get(parent_id).get(position).id); 

     TextView name = (TextView) current_product_layout.findViewById(R.id.name); 
     name.setText(produit.libelle); 

     // Load gallery 

     int nPics = produit.list_url_pic.size(); 

     if(nPics>0){ 

      ViewFlipper gallery = (ViewFlipper) current_product_layout.findViewById(R.id.product_gallery); 
      gallery.removeAllViews();   

      mImageLoader = new ImageDownloader(res, 
        ((BitmapDrawable)res.getDrawable(R.drawable.default_row_pic)).getBitmap(), 1);   

      final ViewFlipper.LayoutParams params_vf = new ViewFlipper.LayoutParams(ViewFlipper.LayoutParams.FILL_PARENT, ViewFlipper.LayoutParams.FILL_PARENT); 

      for(String url : produit.list_url_pic){ 

       // Add images to viewflipper 
       ImageView imageView_p = new ImageView(this); 
       imageView_p.setLayoutParams(params_vf); 
       imageView_p.setScaleType(ImageView.ScaleType.CENTER_CROP); 
       imageView_p.setTag(url); 
       imageView_p.setImageResource(R.drawable.default_row_pic); 
       mImageLoader.download(url, imageView_p); 
       gallery.addView(imageView_p); 
      } 

      // Swipe detector to switch picture in gallery 

      galleryGestureDetector = new GestureDetector(new VerticalSwipeListener()); 
      galleryGestureListener = new View.OnTouchListener() 
      { 
       public boolean onTouch(View v, MotionEvent event) 
       { 
        if (galleryGestureDetector.onTouchEvent(event)) 
        { 
         return true; 
        } 
        else{ 
         return false; 
        } 
       } 
      }; 

     } 
    } 
} 

bố trí Chánh

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/product_home" android:layout_width="fill_parent" 
    android:layout_height="fill_parent" android:orientation="vertical" 
    android:background="@color/grey_bg"> 

    <!-- more stuff --> 

    <ViewFlipper android:id="@+id/product_viewflipper" 
     android:layout_width="fill_parent" android:layout_height="fill_parent" 
     android:layout_below="@id/header_logo" /> 

    <!-- more stuff --> 

</RelativeLayout> 

trẻ em ViewFlipper của bố trí

<?xml version="1.0" encoding="utf-8"?> 
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" android:layout_height="fill_parent" 
    android:background="@color/grey_bg"> 

    <LinearLayout android:layout_width="fill_parent" 
     android:layout_height="wrap_content" android:orientation="vertical" 
     android:gravity="center_horizontal"> 

     <!-- more stuff --> 

     <RelativeLayout android:layout_below="@id/bg_content_top" 
      android:layout_above="@id/bg_content_bottom" 
      android:layout_width="300dp" android:layout_height="fill_parent" 
      android:background="@drawable/bg_content" 
      android:paddingRight="3dp" android:paddingLeft="3dp" 
      android:layout_centerHorizontal="true"> 

      <!-- more stuff --> 

      <RelativeLayout android:id="@+id/content" 
       android:layout_below="@id/title_container" 
       android:layout_above="@id/bg_content_bottom" 
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content" 
       android:paddingLeft="7dp" android:paddingRight="7dp" 
       android:paddingTop="10dp" android:paddingBottom="10dp">    

       <ViewFlipper android:id="@+id/product_gallery" 
        android:clickable="true" android:focusable="false" 
        android:layout_width="100dp" android:layout_height="150dp" 
        android:layout_marginRight="10dp" 
        android:layout_below="@id/title_container" 
        android:layout_toRightOf="@id/gallery_nav" /> 

       <!-- more stuff --> 

      </RelativeLayout> 

     </RelativeLayout> 

     <!-- more stuff --> 

    </LinearLayout> 

</ScrollView> 

Trả lời

53

tôi đã có thêm

@Override 
public boolean dispatchTouchEvent(MotionEvent ev){ 
    super.dispatchTouchEvent(ev);  
    return productGestureDetector.onTouchEvent(ev); 
} 

trong Hoạt động của tôi.

+1

bạn phải thêm nó ở đâu? –

+0

@mirroredAbstraction: Trong hoạt động. – jul

+2

Tôi đang sử dụng Phân đoạn, có cách nào để thực hiện điều này trong Phân đoạn không? –

10

câu trả lời của tôi là sam e là người cuối cùng của tôi ngoại trừ tôi sẽ rõ ràng hơn.

Thay đổi

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" android:layout_height="fill_parent" 
    android:background="@color/grey_bg"> 

để

<your.packagename.CustomScrollView ... etc> 

Tạo một lớp

public class CustomScrollView extends ScrollView { 
    private GestureDetector gestureDetector; 
    View.OnTouchListener gestureListener; 

    public CustomScrollView(Context context, AttributeSet attrs) { 
      super(context, attrs); 
      gestureDetector = new GestureDetector(new YScrollDetector()); 
      setFadingEdgeLength(0); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
     return super.onTouchEvent(ev); 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     //Call super first because it does some hidden motion event handling 
     boolean result = super.onInterceptTouchEvent(ev); 
     //Now see if we are scrolling vertically with the custom gesture detector 
     if (gestureDetector.onTouchEvent(ev)) { 
      return result; 
     } 
     //If not scrolling vertically (more y than x), don't hijack the event. 
     else { 
      return false; 
     } 
    } 

    // Return false if we're scrolling in the x direction 
    class YScrollDetector extends SimpleOnGestureListener { 
     @Override 
     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float  distanceY) { 
     try { 
      if (Math.abs(distanceY) > Math.abs(distanceX)) { 
       return true; 
      } else { 
       return false; 
      } 
     } catch (Exception e) { 
      // nothing 
     } 
     return false; 
    } 
} 

Đó là mã xuất phát từ câu trả lời đầu ở đây: HorizontalScrollView within ScrollView Touch Handling (Vì vậy, đi cho nó một cuộc bỏ phiếu lên nếu câu trả lời hữu ích).

Nếu bạn muốn nhận được sự chỉ đạo vuông góc sau đó thay đổi

if (Math.abs(distanceY) > Math.abs(distanceX)) { 

để

if (Math.abs(distanceY) < Math.abs(distanceX)) { 

Các CustomScrollView sẽ chỉ đánh chặn swipes trong một trục, hoặc theo chiều ngang hoặc theo chiều dọc tùy thuộc 2 dòng mã ở trên . Vì nó chỉ chặn swipes trong một trục phần còn lại của các sự kiện sẽ được thông qua cho con của nó, bây giờ bạn có thể xử lý các sự kiện với người nghe cử chỉ/cảm ứng của bạn trong hoạt động của bạn.

Bạn cũng sẽ cần phải thay đổi bất kỳ tham chiếu/phôi nào thành ScrollView thành tùy chỉnh mới (CustomScrollView).

+1

Khi cuộn, ứng dụng không bao giờ chạy phương pháp onScroll của bạn. – jul

0
parentScrollView.setOnTouchListener(new View.OnTouchListener() { 

       @Override 
       public boolean onTouch(View v, MotionEvent event) { 
        return productGestureDetector.onTouchEvent(event); 
       } 
      }); 

đặt chế độ xem cuộn chính của bạn trên TouchListener và triển khai mã này làm việc cho tôi. Tôi hy vọng sẽ hữu ích cho bạn.

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