关于使用ViewFlipper实现手势滑动切换及其与ScrollView冲突的解决办法
Posted on 2013-03-08 19:28 永夜的极光 阅读(1583) 评论(0) 编辑 收藏 举报昨天想做一个Android小应用,需要实现左右滑动手势进行界面内容的切换功能。经过网上的一番搜索,决定采用ViewFlipper控件。一番折腾后,终于完美实现。自己做了个小Demo,记录一下实现过程,以及遇到的一些问题。不说了,直接看代码。
这是JAVA文件主要代码:
1 package com.test_viewflipper; 2 3 import android.os.Bundle; 4 import android.util.Log; 5 import android.view.GestureDetector; 6 import android.view.GestureDetector.OnGestureListener; 7 import android.view.MotionEvent; 8 import android.view.View; 9 import android.view.animation.AnimationUtils; 10 import android.widget.TextView; 11 import android.widget.ViewFlipper; 12 import android.app.Activity; 13 14 public class Activity01 extends Activity implements OnGestureListener{ 15 16 public String[] teStrings = {"第一首诗","第二首诗"}; //这是想分别显示两个不同界面标题 17 public String[] poemStrings = {"君不见黄河之水天上来,\n奔流到海不复回;" + 18 "\n君不见高堂明镜悲白发,\n朝如青丝暮成雪。" + 19 "\n人生得意须尽欢,\n莫使金樽空对月。" + 20 "\n天生我材必有用,\n千金散尽还复来。" + 21 "\n烹羊宰牛且为乐,\n会须一饮三百杯。" + 22 "\n岑夫子,丹丘生,\n将进酒,君莫停。" + 23 "\n\n与君歌一曲,\n请君为我侧耳听。" + 24 "\n钟鼓馔玉不足贵,\n但愿长醉不愿醒。" + 25 "\n古来圣贤皆寂寞,\n惟有饮者留其名。" + 26 "\n陈王昔时宴平乐,\n斗酒十千恣欢谑。" + 27 "\n主人何为言少钱,\n径须沽取对君酌。" + 28 "\n五花马,千金裘,\n呼儿将出换美酒," + "\n与尔同消万古愁。", 29 "渡远荆门外,来从楚国游。" + 30 "\n山随平野尽,江入大荒流。" + 31 "\n月下飞天镜,云生结海楼。" + 32 "\n仍怜故乡水,万里送行舟。"}; //这是想分别显示两个不同界面内容 33 34 private ViewFlipper viewFlipper; 35 private GestureDetector gestureDetector; //手势侦测对象,用来侦测不同手势的,在下面的代码中可以看到 36 37 @Override 38 public void onCreate(Bundle savedInstanceState) { 39 super.onCreate(savedInstanceState); 40 //首先需要使用一个仅有ViewFlipper对象的布局文件,从中获取ViewFlipper。详情见下面布局文件代码 41 viewFlipper = (ViewFlipper) getLayoutInflater().inflate(R.layout.main, null); 42 43 // 生成GestureDetector对象,用于检测手势事件 44 gestureDetector = new GestureDetector(this); 45 //由于ViewFlipper是实现View对象之间的切换,因此需要把每个显示界面的内容均是作为View对象,并让其在ViewFlipper对象中进行载入 46 //对于多个类似的View对象,此时可以用View对象数组进行循环载入。 47 View view[] = new View[2]; 48 49 for (int i = 0; i < 2; i++) 50 { 51 //我采用的是较为简便的方法,对每个View对象都使用xml布局文件来进行界面布局,因此需要用inflate方法来对每个View载入布局文件 52 view[i] = getLayoutInflater().inflate(R.layout.activity01, null); 53 //所有的View均使用同一个activity01布局文件 54 55 viewFlipper.addView(view[i]); //添加每个View对象 56 57 TextView titleTextView = (TextView)view[i].findViewById(R.id.Poem_title); 58 TextView poemTextView = (TextView)view[i].findViewById(R.id.Poem); 59 titleTextView.setText(teStrings[i]); 60 Log.v("报告!", "设置标题成功!"); 61 poemTextView.setText(poemStrings[i]); 62 Log.v("报告!", "设置内容成功!"); 63 64 } 65 setContentView(viewFlipper); 66 } 67 @Override 68 public boolean onDown(MotionEvent e) { 69 // TODO Auto-generated method stub 70 return false; 71 } 72 @Override 73 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 74 float velocityY) { 75 //e1参数是手指离开时的MotionEvent,e2参数是手指接触时的MotionEvent 76 //对手指滑动的距离进行了计算,如果滑动距离大于50像素,就做切换动作,否则不做任何切换动作。 77 // 从左向右滑动 78 if (e1.getX() - e2.getX() > 50) 79 { 80 // 添加动画 81 this.viewFlipper.setInAnimation(AnimationUtils.loadAnimation(this, 82 R.anim.push_left_in)); 83 this.viewFlipper.setOutAnimation(AnimationUtils.loadAnimation(this, 84 R.anim.push_left_out)); 85 this.viewFlipper.showNext(); 86 Log.v("从左向右滑动", "成功"); 87 return true; 88 }// 从右向左滑动 89 else if (e1.getX() - e2.getX() < -50) 90 { 91 this.viewFlipper.setInAnimation(AnimationUtils.loadAnimation(this, 92 R.anim.push_right_in)); 93 this.viewFlipper.setOutAnimation(AnimationUtils.loadAnimation(this, 94 R.anim.push_right_out)); 95 this.viewFlipper.showPrevious(); 96 Log.v("从右往左滑动", "成功"); 97 return true; 98 } 99 return true; 100 } 101 @Override 102 public void onLongPress(MotionEvent e) { 103 // TODO Auto-generated method stub 104 105 } 106 @Override 107 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, 108 float distanceY) { 109 // TODO Auto-generated method stub 110 return false; 111 } 112 @Override 113 public void onShowPress(MotionEvent e) { 114 // TODO Auto-generated method stub 115 116 } 117 @Override 118 public boolean onSingleTapUp(MotionEvent e) { 119 // TODO Auto-generated method stub 120 return false; 121 } 122 @Override 123 public boolean onTouchEvent(MotionEvent event) { 124 // TODO Auto-generated method stub 125 return this.gestureDetector.onTouchEvent(event); //将当前的手势返回到当前的手势监听器中,以触发相应手势处理事件 126 } 127 @Override 128 public boolean dispatchTouchEvent(MotionEvent ev) { 129 // TODO Auto-generated method stub 130 gestureDetector.onTouchEvent(ev); 131 return super.dispatchTouchEvent(ev); 132 } 133 134 135 136 }
main.xml布局文件:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <ViewFlipper 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:id="@+id/viewflipper" 5 android:layout_width="fill_parent" 6 android:layout_height="fill_parent"></ViewFlipper>
每个显示的View对象所需要的Active01.xml布局文件:
1 <ScrollView 2 xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="fill_parent" 5 android:layout_height="fill_parent" 6 android:scrollbars="vertical"> 7 <RelativeLayout 8 android:layout_width="match_parent" 9 android:layout_height="wrap_content" > 10 11 <TextView 12 android:id="@+id/Poem_title" 13 android:layout_width="wrap_content" 14 android:layout_height="wrap_content" 15 android:textSize="28dp" 16 android:textStyle="bold" 17 android:layout_marginTop="20dp" 18 android:gravity="center_horizontal" 19 android:layout_centerHorizontal="true"/> 20 21 <TextView 22 android:id="@+id/libai_athor" 23 android:layout_width="wrap_content" 24 android:layout_height="wrap_content" 25 android:text="李白" 26 android:layout_below="@+id/Poem_title" 27 android:layout_centerHorizontal="true" 28 android:textSize="20dp" 29 android:layout_marginTop="20dp"/> 30 31 <TextView 32 android:id="@+id/Poem" 33 android:layout_width="wrap_content" 34 android:layout_height="wrap_content" 35 android:layout_below="@+id/libai_athor" 36 android:layout_centerHorizontal="true" 37 android:textSize="25dp" 38 android:gravity="center_horizontal" 39 android:layout_marginTop="20dp" 40 android:layout_marginBottom="10dp"/> 41 42 <TextView 43 android:layout_width="fill_parent" 44 android:layout_height="20dp" 45 android:layout_below="@+id/Poem" 46 android:layout_centerHorizontal="true"/> 47 </RelativeLayout> 48 </ScrollView>
在上述代码的编写过程中,发现了一个问题。应用中使用了ViewFlipper,而有些View对象所要显示的内容较多而采用ScrollView。这时,两者的手势响应事件产生了冲突,使得左右滑动切换功能失效,只具有上下拖动的功能。最终解决办法是在Activity中重写dispatchTouchEvent。具体代码如下:
1 @Override 2 public boolean dispatchTouchEvent(MotionEvent ev) { 3 // TODO Auto-generated method stub 4 gestureDetector.onTouchEvent(ev); 5 return super.dispatchTouchEvent(ev); 6 }
最终测试成功。Java代码中使用李白的长诗就是用来检测ScrollView的上下滑动效果和ViewFlipper的左右切换是否会冲突的。呵呵……
努力了两天,终于解决了这一问题。上述过程是自己的解决办法,如有错误,希望大家能够及时指正。