解决ViewFlipper与ScrollView滑动响应事件拦截的问题

最近在做一个简单的展示界面时,遇到了一个比较棘手的问题。由于要展示多项内容,所以使用ViewFlipper作为水平滑动容器;而每项内容中由于许多文本较长,因此需要使用ScrollView作为垂直滑动容器。基本的界面布局大致如下: 

外部文件common_list_view.xml: 
Xml代码   收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout  
  3. xmlns:android="http://schemas.android.com/apk/res/android"  
  4. android:id="@+id/geyan_query_view_layout"  
  5. android:layout_width="fill_parent"  
  6. android:layout_height="fill_parent"  
  7. android:orientation="vertical"  
  8. android:background="@drawable/mid_bg">  
  9. <LinearLayout  
  10. android:layout_width="fill_parent"  
  11. android:layout_height="fill_parent"  
  12. android:layout_marginTop="43dip"  
  13. android:orientation="vertical"  
  14. android:gravity="top"  
  15. android:layout_gravity="top">  
  16. <Gallery  
  17. android:id="@+id/gallery_data"  
  18. android:layout_width="fill_parent"  
  19. android:layout_height="fill_parent"  
  20. android:gravity="top"  
  21. android:layout_gravity="top"  
  22. android:spacing="60dip"  
  23. android:paddingLeft="6dip"  
  24. android:paddingRight="6dip"  
  25. >  
  26. </Gallery>  
  27. </LinearLayout>  
  28. <ImageView  
  29. android:id="@+id/main_background"  
  30. android:layout_width="fill_parent"  
  31. android:layout_height="fill_parent"/>  
  32. <include layout="@layout/common_title_view"  
  33. android:id="@+id/title"/>  
  34. </RelativeLayout>  


内部文件common_info_view.xml: 
Xml代码   收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout  
  3. xmlns:android="http://schemas.android.com/apk/res/android"  
  4. android:layout_width="fill_parent"  
  5. android:layout_height="fill_parent"  
  6. android:orientation="vertical"  
  7. android:id="@+id/linear">  
  8. <TextView  
  9. android:id="@+id/text_title"  
  10. android:layout_width="fill_parent"  
  11. android:layout_height="wrap_content"  
  12. android:padding="5dip"  
  13. android:layout_marginTop="5dip"  
  14. android:gravity="center"  
  15. android:textSize="20sp"  
  16. android:textStyle="bold"  
  17. android:textColor="#181712"  
  18. />  
  19. <ScrollView  
  20. android:id="@+id/scroll"  
  21. android:layout_width="fill_parent"  
  22. android:layout_height="fill_parent"  
  23. android:layout_marginBottom="5dip"  
  24. android:fadeScrollbars="true"  
  25. >  
  26. <TextView  
  27. android:id="@+id/text_detail"  
  28. android:layout_width="fill_parent"  
  29. android:layout_height="wrap_content"  
  30. android:lineSpacingMultiplier="1.3"  
  31. android:textSize="18sp"  
  32. android:textColor="#181712"  
  33. android:singleLine="false"  
  34. />  
  35. </ScrollView>  
  36. </LinearLayout>  


由于ViewFlipper在外,ScrollView在内,因此一般的做法是定义一个手势响应类来处理响应事件,并将响应事件的处理交给内层的ScrollView。大致代码如下: 
Java代码   收藏代码
  1. import android.app.Activity;  
  2. import android.os.Bundle;  
  3. import android.util.Log;  
  4. import android.view.GestureDetector;  
  5. import android.view.GestureDetector.SimpleOnGestureListener;  
  6. import android.view.LayoutInflater;  
  7. import android.view.Menu;  
  8. import android.view.MotionEvent;  
  9. import android.view.View;  
  10. import android.view.Window;  
  11. import android.widget.TextView;  
  12. import android.widget.Toast;  
  13. import android.widget.ViewFlipper;  
  14.    
  15. public class Test1 extends Activity {  
  16.    
  17.     private ViewFlipper viewFlipper;  
  18.    
  19.     private String[] descriptionsArray;  
  20.     private String[] titleArray;  
  21.    
  22.     private int selectedPosition;  
  23.    
  24.     private TextView textViewTitle;  
  25.     private TextView textViewContent;  
  26.     private FriendlyScrollView scroll;  
  27.    
  28.     private LayoutInflater mInflater;  
  29.    
  30.     private GestureDetector gestureDetector;  
  31.    
  32.     @Override  
  33.     protected void onCreate(Bundle savedInstanceState) {  
  34.         // TODO Auto-generated method stub  
  35.    
  36.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  37.         setContentView(R.layout.common_info_list_view);  
  38.    
  39.         InitUI();  
  40.    
  41.         super.onCreate(savedInstanceState);  
  42.    
  43.         Toast.makeText(this, R.string.hello, Toast.LENGTH_SHORT).show();  
  44.     }  
  45.    
  46.     @Override  
  47.     public boolean onCreateOptionsMenu(Menu menu) {  
  48.         // TODO Auto-generated method stub  
  49.         super.onCreateOptionsMenu(menu);  
  50.         return false;  
  51.     }  
  52.    
  53.     @Override  
  54.     public void onBackPressed() {  
  55.         // TODO Auto-generated method stub  
  56.         finish();  
  57.     }  
  58.    
  59.     private void InitUI(){  
  60.    
  61.         viewFlipper = (ViewFlipper) findViewById(R.id.viewflipper_data);  
  62.    
  63.         mInflater = LayoutInflater.from(this);  
  64.    
  65.         fillDate();  
  66.    
  67.         viewFlipper.addView(getContentView());  
  68.     }  
  69.    
  70.     private void fillDate(){  
  71.         selectedPosition = 0;  
  72.    
  73.         titleArray = getResources().getStringArray(R.array.title_array);  
  74.         descriptionsArray = getResources().getStringArray(R.array.description_array);  
  75.    
  76.         gestureDetector = new GestureDetector(new CommonGestureListener());  
  77.     }  
  78.    
  79.     private View getContentView() {  
  80.         View contentView = new View(this);  
  81.         contentView = mInflater.inflate(R.layout.common_info_item_view, null);  
  82.    
  83.         textViewTitle = (TextView) contentView.findViewById(R.id.text_title);  
  84.         textViewContent = (TextView) contentView.findViewById(R.id.text_detail);  
  85.    
  86.         textViewTitle.setText(titleArray[selectedPosition]);  
  87.         textViewTitle.setPadding(100100);  
  88.         textViewContent.setText(descriptionsArray[selectedPosition]);  
  89.         textViewContent.setPadding(105105);  
  90.    
  91.         scroll = (FriendlyScrollView) contentView.findViewById(R.id.scroll);  
  92.         scroll.setOnTouchListener(onTouchListener);  
  93.         scroll.setGestureDetector(gestureDetector);  
  94.    
  95.         return contentView;  
  96.     }  
  97.    
  98.     private View.OnTouchListener onTouchListener = new View.OnTouchListener() {  
  99.    
  100.         public boolean onTouch(View v, MotionEvent event) {  
  101.             // TODO Auto-generated method stub  
  102.             return gestureDetector.onTouchEvent(event);  
  103.         }  
  104.     };  
  105.    
  106.     public class CommonGestureListener extends SimpleOnGestureListener {  
  107.    
  108.         @Override  
  109.         public boolean onDown(MotionEvent e) {  
  110.             // TODO Auto-generated method stub  
  111.             Log.d("QueryViewFlipper""====> Jieqi: do onDown...");  
  112.             return false;  
  113.         }  
  114.    
  115.         @Override  
  116.         public void onShowPress(MotionEvent e) {  
  117.             // TODO Auto-generated method stub  
  118.             Log.d("QueryViewFlipper""====> Jieqi: do onShowPress...");  
  119.             super.onShowPress(e);  
  120.         }  
  121.    
  122.         @Override  
  123.         public void onLongPress(MotionEvent e) {  
  124.             // TODO Auto-generated method stub  
  125.             Log.d("QueryViewFlipper""----> Jieqi: do onLongPress...");  
  126.         }  
  127.    
  128.         @Override  
  129.         public boolean onSingleTapConfirmed(MotionEvent e) {  
  130.             // TODO Auto-generated method stub  
  131.             Log.d("QueryViewFlipper""====> Jieqi: do onSingleTapConfirmed...");  
  132.             return false;  
  133.         }  
  134.    
  135.         @Override  
  136.         public boolean onSingleTapUp(MotionEvent e) {  
  137.             // TODO Auto-generated method stub  
  138.             Log.d("QueryViewFlipper""====> Jieqi: do onSingleTapUp...");  
  139.             return false;  
  140.         }  
  141.    
  142.         @Override  
  143.         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,  
  144.                 float velocityY){  
  145.             // TODO Auto-generated method stub  
  146.             Log.d("QueryViewFlipper""====> Jieqi: do onFling...");  
  147.             if (e1.getX() - e2.getX() > 100 &amp;&amp; Math.abs(velocityX) > 50) {  
  148.                 //向左  
  149.                 selectedPosition = selectedPosition + 1 < titleArray.length ? (selectedPosition + 1) : 0;  
  150.                 viewFlipper.addView(getContentView());  
  151.                 viewFlipper.setInAnimation(AnimationControl.inFromRightAnimation());  
  152.                 viewFlipper.setOutAnimation(AnimationControl.outToLeftAnimation());  
  153.                 viewFlipper.showNext();  
  154.                 viewFlipper.removeViewAt(0);  
  155.             } else if (e2.getX() - e1.getX() > 100 &amp;&amp; Math.abs(velocityX) > 50) {  
  156.                 //向右  
  157.                 selectedPosition = selectedPosition > 0 ? (selectedPosition - 1) : (titleArray.length - 1);  
  158.                 viewFlipper.addView(getContentView());  
  159.                 viewFlipper.setInAnimation(AnimationControl.inFromLeftAnimation());  
  160.                 viewFlipper.setOutAnimation(AnimationControl.outToRightAnimation());  
  161.                 viewFlipper.showNext();  
  162.                 viewFlipper.removeViewAt(0);  
  163.             }  
  164.             return true;  
  165.         }  
  166.    
  167.         @Override  
  168.         public boolean onScroll(MotionEvent e1, MotionEvent e2,  
  169.                 float distanceX, float distanceY) {  
  170.             // TODO Auto-generated method stub  
  171.             Log.d("QueryViewFlipper""====> Jieqi: do onScroll...");  
  172.             return super.onScroll(e1, e2, distanceX, distanceY);  
  173.         }  
  174.    
  175.     }  
  176. }  


这个时候问题出现了,通过Log显示,当ScrollView中内容太短的时候,ScrollView不会触发OnScroll和OnFling事件,导致ViewFlipper左右滑动不响应。(当然后来的另一个测试表明这个问题在ListView上不存在) 

为了解决这一个问题,我重新自定义了一个FriendlyScrollView类,来重写ScrollView的onTouchEvent和dispatchTouchEvent方法,具体如下: 
Java代码   收藏代码
  1. import android.content.Context;  
  2. import android.util.AttributeSet;  
  3. import android.view.GestureDetector;  
  4. import android.view.MotionEvent;  
  5. import android.widget.ScrollView;  
  6.    
  7. public class FriendlyScrollView extends ScrollView {  
  8.    
  9.     GestureDetector gestureDetector;  
  10.    
  11.     public FriendlyScrollView(Context context) {  
  12.         super(context);  
  13.         // TODO Auto-generated constructor stub  
  14.     }  
  15.    
  16.     public FriendlyScrollView(Context context, AttributeSet attrs) {  
  17.         super(context, attrs);  
  18.         // TODO Auto-generated constructor stub  
  19.     }  
  20.    
  21.     public FriendlyScrollView(Context context, AttributeSet attrs, int defStyle) {  
  22.         super(context, attrs, defStyle);  
  23.         // TODO Auto-generated constructor stub  
  24.     }  
  25.    
  26.     public void setGestureDetector(GestureDetector gestureDetector) {  
  27.         this.gestureDetector = gestureDetector;  
  28.     }  
  29.    
  30.     @Override  
  31.     public boolean onTouchEvent(MotionEvent event) {  
  32.         super.onTouchEvent(event);  
  33.         return gestureDetector.onTouchEvent(event);  
  34.     }  
  35.    
  36.     @Override  
  37.     public boolean dispatchTouchEvent(MotionEvent ev){  
  38.         gestureDetector.onTouchEvent(ev);  
  39.         super.dispatchTouchEvent(ev);  
  40.         return true;  
  41.     }   
  42.    
  43. }  

然后将common_info_view.xml和程序中的ScrollView改成FriendlyScrollView,终于解决了这个问题。

你可能感兴趣的:(android,Android开发,imageview,RelativeLayout,界面)