导航

昨天想做一个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的左右切换是否会冲突的。呵呵……

 努力了两天,终于解决了这一问题。上述过程是自己的解决办法,如有错误,希望大家能够及时指正。