Gallery
首先看下API结构:
public class Gallery extends AbsSpinner implements GestureDetector.OnGestureListener
java.lang.Object | |||||
↳ | android.view.View | ||||
↳ | android.view.ViewGroup | ||||
↳ | android.widget.AdapterView<T extendsandroid.widget.Adapter> | ||||
↳ | android.widget.AbsSpinner | ||||
↳ | android.widget.Gallery |
这里说下:AbsSpinenr 和 AbsListView一样都是继承自AdapteView, AbsSpinner的直接之类还包括Spinner, 而AbsListView的直接之类为GridView和ListView。
Gallery用来显示图片还是方便的,但是当显示图片的第一张和最后一张时,左右两边的黑块很是让人不舒服,于是让gallery左右循环拖动就成为必要了,其实现方法也算简单:
1) 在自己定义的adapter类里面的getCount()方法尽量返回一个较大的值(可以设为Intger.MAX_VALUE),这样可以让向右滑动的操作一直持续。
public int getCount() {
return Integer.MAX_VALUE;
}
2) 在getView()方法中的设置获取图片的实际下标为当前下标对图片总数的取余。
position = position % imgList.size(); //imgList为要待显示的图片数组(length属性)或集合(size()方法)。
3)设置好1,2后图片就可以向右无限滑动了,但向左还是无法循环,这就要设置方法setSelector(int)了,该方法是用于设置当前显示图片的下标,如果设置一个较大的值,就可以给用户造成一种可以无限循环的假象,因为用户不可能像做较多次数的向左滑动,这样我们的目地也就达到了。
ViewFlipper
看下API结构:
public class ViewFlipper extends ViewAnimator
java.lang.Object | |||||
↳ | android.view.View | ||||
↳ | android.view.ViewGroup | ||||
↳ | android.widget.FrameLayout | ||||
↳ | android.widget.ViewAnimator | ||||
↳ | android.widget.ViewFlipper |
常用的方法:
- setOutAnimation: 设置View退出屏幕时候使用的动画,参数setInAnimation函数一样。
- showNext: 调用该函数来显示FrameLayout里面的下一个View。
- showPrevious:调用该函数来显示FrameLayout里面的上一个View。
- isFlipping: 用来判断View切换是否正在进行
- setFilpInterval:设置View之间切换的时间间隔
- startFlipping:使用上面设置的时间间隔来开始切换所有的View,切换会循环进行
- stopFlipping: 停止View切换
ViewFlipper是继承至FrameLayout的,所以它是一个Layout里面可以放置多个View:
- <?xml
version="1.0" encoding="utf-8"?> - <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ViewFlipper android:id="@+id/details" android:layout_width="fill_parent" android:layout_height="fill_parent" android:persistentDrawingCache="animation" android:flipInterval="1000" android:inAnimation="@anim/push_left_in" - android:outAnimation="@anim/push_left_out"
- >
<LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:text="Next" android:id="@+id/Button_next1" android:layout_width="fill_parent" android:layout_height="wrap_content"> </Button> <ImageView android:id="@+id/image1" android:src="@drawable/dell1" android:layout_width="fill_parent" android:layout_height="wrap_content"> </ImageView> </LinearLayout> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:text="Next" android:id="@+id/Button_next2" android:layout_width="fill_parent" android:layout_height="wrap_content"> </Button> <ImageView android:id="@+id/image2" android:src="@drawable/lg" android:layout_width="fill_parent" android:layout_height="wrap_content"> </ImageView> </LinearLayout> ................................. </ViewFlipper> - </LinearLayout>
通过 android.view.GestureDetector类可以检测各种手势事件,该类有两个回调接口分别用来通知具体的事件:GestureDetector.OnDoubleTapListener:用来通知 DoubleTap事件,类似于鼠标的双击事件,该接口有如下三个回调函数:1.onDoubleTap(MotionEvent e):通知 DoubleTap手势, 2.onDoubleTapEvent(MotionEvent e):通知 DoubleTap手势中的事件,包含down、up和move事件(这里指的是在双击之间发生的事件,例如在同一个地方双击会产生DoubleTap手势,而在DoubleTap手势里面还会发生down和up事件,这两个事件由该函数通知); 3.onSingleTapConfirmed(MotionEvent e):用来判定该次点击是 SingleTap而不是DoubleTap,如果连续点击两次就是DoubleTap手势,如果只点击一次,OPhone系统等待一段时间后没有收到第二次点击则判定该次点击为SingleTap而不是DoubleTap,然后触发SingleTapConfirmed事件。 GestureDetector.OnGestureListener:用来通知普通的手势事件,该接口有如下六个回调函数:1.onDown(MotionEvent e): down事件; 2.onSingleTapUp(MotionEvent e):一次点击 up事件; 3.onShowPress(MotionEvent e): down事件发生而move或则up还没发生前触发该事件; 4.onLongPress(MotionEvent e):长按事件; 5.onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY):滑动手势事件; 6.onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY):在屏幕上拖动事件。 这些事件有些定义的不太容易理解,在示例项目中实现了所有的回调函数,在每个函数中输出相关的日志,对这些事件不理解的可以运行项目,通过不同的操作来触发事件,然后观看 logcat输出日志可有助于对这些事件的理解。在上述事件中,如果在程序中处理的该事件就返回 true否则返回false,在GestureDetector中也定义了一个SimpleOnGestureListener类,这是个助手类,实现了上述的所有函数并且都返回false。如果在项目中只需要监听某个事件继承这个类可以少些几个空回调函数。要走上面的程序中添加滑动手势来实现屏幕切换的话,首先需要定义一个GestureDetector:private GestureDetector mGestureDetector;并在onCreate函数中初始化:mGesture = new GestureDetector( this);并实现方法:@Override
public boolean onTouchEvent(MotionEvent event) {
return mGesture.onTouchEvent(event);
}参数是OnGestureListener,然后让TestActivity实现 OnGestureListener 和OnDoubleTapListener接口:这里实现的功能是从右往左滑动则切换到上一个View,从左往右滑动则切换到下一个View,并且使用不同的in、out 动画使切换效果看起来统一一些。然后在onDoubleTap中实现双击自动切换的效果,再次双击则停止- public
boolean onDoubleTap(MotionEvent e) { Log.d(tag, "...onDoubleTap..."); if(mViewFlipper.isFlipping()) { mViewFlipper.stopFlipping(); }else { mViewFlipper.startFlipping(); } return true; }
到这里手势代码就完成了,现在可以通过左右滑动切换View并且双击可以自动切换View。细心的读者这里可能会发现一个问题,上面在创建mGestureDetector 的时候使用的是如下代码:mGestureDetector = new GestureDetector( this);这里的参数为OnGestureListener,而且GestureDetector有个函数setOnDoubleTapListener来设置OnDoubleTapListener,在上面的代码中并没有设置OnDoubleTapListener,那么onDoubleTap事件是如何调用的呢?这里的玄机就要去探探 GestureDetector(OnGestureListener l)这个构造函数的源代码了:public GestureDetector(OnGestureListener listener) { this(null, listener, null); - }
调用了另外一个构造函数:- public
GestureDetector(Context context, OnGestureListener listener, Handler handler) { if (handler != null) { mHandler = new GestureHandler(handler); } else { mHandler = new GestureHandler(); } mListener = listener; if (listener instanceof OnDoubleTapListener) { setOnDoubleTapListener((OnDoubleTapListener) listener); } init(context);
注意到listener instanceof OnDoubleTapListener没有?现在明白了吧。 - <?xml