说到android的左右滑动效果我们可以说是在每个应用上面都可以看到这样的效果,不管是微博,还是QQ等。

实现左右滑动的方式很多,有ViewPager(不过这个和需要android-support-v4.jar的支持),自定义实现Viewgroup,gallery等都可以达到这种效果。这里主要是做下ViewFliper来实现左右滑动的效果。

ViewFlipper可以实现滑动ImageView、自定义View、动态添加View等,只要ViewPager能实现的功能它也能实现。好了,废话不说了,直接说怎么实现ViewFlipper吧,这里我还加了一个功能,就是当触摸到ViewFlipper是,就让它停止3秒,然后3秒后再自动切换。

使用ViewFlipper的时候我习惯用动态添加View来做,因为这样可以对View的添加和删除都非常方便,而不必去管xml布局文件。下面就来看看怎么做的吧。

一、基本实现

下面先看一下实现的效果:(实现四张图片的自动切换)

1、在XML中的布局:

[html] view
plain
copy

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent" >
  5. <ViewFlipper
  6. android:id="@+id/flipper"
  7. android:layout_width="match_parent"
  8. android:layout_height="wrap_content"
  9. android:layout_alignParentTop="true"
  10. android:layout_marginTop="10dp"
  11. android:flipInterval="2000" >
  12. <ImageView
  13. android:layout_width="fill_parent"
  14. android:layout_height="300dip"
  15. android:scaleType="fitXY"
  16. android:src="@drawable/img_1"/>
  17. <ImageView
  18. android:layout_width="fill_parent"
  19. android:layout_height="300dip"
  20. android:scaleType="fitXY"
  21. android:src="@drawable/img_2"/>
  22. <ImageView
  23. android:layout_width="fill_parent"
  24. android:layout_height="300dip"
  25. android:scaleType="fitXY"
  26. android:src="@drawable/img_3"/>
  27. <ImageView
  28. android:layout_width="fill_parent"
  29. android:layout_height="300dip"
  30. android:scaleType="fitXY"
  31. android:src="@drawable/img_4"/>
  32. </ViewFlipper>
  33. </RelativeLayout>

在ViewFlipper中,加入四个ImageView子控件,其中flipInterval属性是用来设置多少毫秒自动显示下一个视图;

2、JAVA代码:

[java] view
plain
copy

  1. public class MainActivity extends Activity {
  2. ViewFlipper flipper;
  3. @Override
  4. public void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_main);
  7. flipper = (ViewFlipper) findViewById(R.id.flipper);
  8. flipper.startFlipping();//开始切换,注意,如果设置了时间间隔,想让它自动切换,一定要记得加它
  9. }
  10. }

这部分代码非常简单,直接调用ViewFlipper的startFlipping()函数,开始滑动。

可见,ViewFlipper使用起来非常简单,直接在xml中布好以后,直接就能用了。

但我们这里有个问题在于,我们这里的ImageView是写死的,如果要改显示的视图我们就必须该xml布局文件了,这样很不利代码的后期维护了。所以我们在使用中一般是要动态加入ImageView或自定义View的,这就是下面的内容喽。

二、动态添加图片,并加入手势滑动

我们一般要动态加载View,就要用到ViewFlipper::addView方法了。而如果要用手势滑动效果,就需要用ViewFlipper::showNext();//显示下一个视图, ViewFlipper::showPrevious();//显示上一个视图
 的方法了。

先贴xml布局文件吧:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ViewFlipper
        android:id="@+id/vf"
        android:layout_width="match_parent"
        android:layout_height="300dp" >
    </ViewFlipper>

</RelativeLayout>

在布局中我们只添加了一个ViewFlipper控件,将来要动态添加ViewFlipper的子控件的时候,就通过ViewFlipper对象来addView()添加View对象了,这里要添加的View对象怎么来呢?当然就是通过代码来写了,比如要添加ImageView,就通过ImageView mImageView = new ImageView(this);来创建一个对象,然后设置它的一些图片什么的,如果要添加一个自定义View,就可以在layout文件夹下先创建这个自定义的View布局,然后通过LayoutInflater填充器来填充,从而得到一个View对象,就add进去就可以啦。

------------------思考:

如果我们在开发中遇到这种情况怎么办呢?我们要用代码动态添加一个自定义布局View对象,那怎么做呢,答案就是首先创建这个布局的根布局对象,比如用LinearLayout布局,就new
一个LinearLayout对象,然后通过再add其它子控件对象进去,这样纯代码就可以写布局啦!!!

言归正传,再贴java代码吧:

public class MainActivity extends Activity  {
	private ViewFlipper flipper;
	private GestureDetector detector;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		init();
	}
	private void init(){
		flipper = (ViewFlipper) findViewById(R.id.vf);
		flipper.addView(getImageView(R.drawable.aaaa));//在一个根视图中动态添加子视图,可以根据new对象来进行子视图的增加和删减
		flipper.addView(getImageView(R.drawable.aa));
		flipper.addView(getImageView(R.drawable.http_imgload));
        flipper.setInAnimation(inFromRightAnimation());//设置View进入屏幕时候使用的动画
        flipper.setOutAnimation(outToLeftAnimation());  //设置View退出屏幕时候使用的动画
		flipper.setFlipInterval(2000);//设置自动切换的间隔时间
		flipper.startFlipping();//开启切换效果
		flipper.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				return MainActivity.this.detector.onTouchEvent(event);//当有触屏事件作用于ViewFlipper时,把这个触屏事件返回给 GestureDetector手势识别器处理
				//如果想要把整个屏幕上的触屏事件都返回给 GestureDetector手势识别器处理,
				//而不单单是在ViewFlipper上发生触屏事件时就给 GestureDetector处理,
				//那么我们就不必为flipper单独设置onTouchListener()触摸监听器了,就只需要重写Activity中的onTouchEvent()方法,
				//在该方法中讲整个屏幕的触摸事件返回给手势识别器处理就行
			}
		});

		detector = new GestureDetector(this, new OnGestureListener() {//创建手势识别器并监听手势事件

			@Override
			public boolean onSingleTapUp(MotionEvent e) {
				// TODO Auto-generated method stub
				return false;
			}

			@Override
			public void onShowPress(MotionEvent e) {
				// TODO Auto-generated method stub
			}

			@Override
			public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
					float distanceY) {
				// TODO Auto-generated method stub
				return false;
			}

			@Override
			public void onLongPress(MotionEvent e) {
				// TODO Auto-generated method stub
			}
		/*
		     * 用户按下触摸屏、快速移动后松开即触发这个事件
		     * e1:第1个ACTION_DOWN MotionEvent
		     * e2:最后一个ACTION_MOVE MotionEvent
		     * velocityX:X轴上的移动速度,像素/秒
		     * velocityY:Y轴上的移动速度,像素/秒
		     * 触发条件 :
		     * X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒
		     */
			@Override
			public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
					float velocityY) {//滑动事件回调函数

			final float FLING_MIN_DISTANCE = 100;//最小滑动像素
			final float FLING_MIN_VELOCITY = 150;//最小滑动速度
			if(e1.getX() - e2.getX() > FLING_MIN_DISTANCE &&
				Math.abs(velocityX) > FLING_MIN_VELOCITY){//X轴上的移动速度去绝对值进行比较
			//判断x轴坐标如果第一次按下时的坐标减去第二次离开屏幕时的坐标大于我们设置的位移,因为一个控件的原点是在左上角,就说明此时是向左滑动的
			//设置View进入屏幕时候使用的动画
	                flipper.setInAnimation(inFromRightAnimation());
	                //设置View退出屏幕时候使用的动画
	                flipper.setOutAnimation(outToLeftAnimation());
				flipper.showNext();//显示下一个视图  

			}else if(e2.getX() - e1.getX() > FLING_MIN_DISTANCE &&
				Math.abs(velocityX) > FLING_MIN_VELOCITY){
			//判断x轴坐标如果第二次离开屏幕时的坐标减去第一次按下时的坐标大于我们设置的位移,因为一个控件的原点是在左上角,就说明此时是向右滑动的
				flipper.setInAnimation(inFromLeftAnimation());
	                flipper.setOutAnimation(outToRightAnimation());
				flipper.showPrevious();//显示上一个视图
			}
				return true;
			}

			@Override
			public boolean onDown(MotionEvent e) {//手指按下屏幕时触发
				flipper.stopFlipping();//当触摸到ViewFlipper时,就让它停止自动滑动,如果要触摸到整个屏幕的任意一处就让它停止滑动,就按上面那个方法,不用设置ViewFlipper的触摸事件监听了
				new Handler().postDelayed(new Runnable() {//在当前线程(也即主线程中)开启一个消息处理器,并在3秒后发送flipper.startFlipping();这个消息给主线程,再让它自动滑动,从而来更新UI
					@Override
					public void run() {
						flipper.startFlipping();//3秒后执行,让它又开始滑动
					}
				}, 3000);
				return true;
			}
		});
	}
	//创建一个ImageView对象
	private ImageView getImageView(int id){
        ImageView imageView = new ImageView(this);
        imageView.setImageResource(id);
        return imageView;
	}
	/**
     * 定义从右侧进入的动画效果
     * @return
     */
    protected Animation inFromRightAnimation() {
        Animation inFromRight = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT, +1.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f);
        inFromRight.setDuration(200);
        inFromRight.setInterpolator(new AccelerateInterpolator());
        return inFromRight;
    }  

    /**
     * 定义从左侧退出的动画效果
     * @return
     */
    protected Animation outToLeftAnimation() {
        Animation outtoLeft = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, -1.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f);
        outtoLeft.setDuration(200);
        outtoLeft.setInterpolator(new AccelerateInterpolator());
        return outtoLeft;
    }  

    /**
     * 定义从左侧进入的动画效果
     * @return
     */
    protected Animation inFromLeftAnimation() {
        Animation inFromLeft = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT, -1.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f);
        inFromLeft.setDuration(200);
        inFromLeft.setInterpolator(new AccelerateInterpolator());
        return inFromLeft;
    }  

    /**
     * 定义从右侧退出时的动画效果
     * @return
     */
    protected Animation outToRightAnimation() {
        Animation outtoRight = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, +1.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f);
        outtoRight.setDuration(200);
        outtoRight.setInterpolator(new AccelerateInterpolator());
        return outtoRight;
    }  

}

好了,代码上的注释已经很明显了,还有那个动画Animation,这里就不再说了,自己去查下。

再贴张图吧,自己画的。

最后,再总结一下ViewFlipper的使用步骤吧:

1、首先在xml布局中创建ViewFlipper控件

2、在java文件中实例化ViewFlipper控件

3、动态为ViewFlipper添加View子控件,并设置响应的动画效果或者自动切换时间,并开启自动切换

4、设置ViewFlipper的onTouchListener()触摸事件,(如果要实现只触摸ViewFlipper时对手势滑动事件有效就设置ViewFlipper的onTouchListener,并返回触摸事件给手势识别器处理。如果对整个屏幕触摸有效,就不必设置这个了,直接重写activity中的onTouchEvent()方法,在这个方法中拦截触摸事件交给手势识别器处理)

5、创建手势识别器GestureDetector并监听,重写它的onFling()方法。

流程就是这样的!!!

源码上传至http://download.csdn.net/detail/u010687392/8458475

请大家尊重原创者版权,转载请标明出处-------------谢谢

Android中ViewFlipper的使用详解的更多相关文章

  1. Android中Service的使用详解和注意点(LocalService)

    Android中Service的使用详解和注意点(LocalService) 原文地址 开始,先稍稍讲一点android中Service的概念和用途吧~ Service分为本地服务(LocalServ ...

  2. Android中SurfaceView的使用详解

    Android中SurfaceView的使用详解 http://blog.csdn.net/listening_music/article/details/6860786 Android NDK开发 ...

  3. Android中的windowSoftInputMode属性详解

    这篇文章主要介绍了Android中的windowSoftInputMode属性详解,本文对windowSoftInputMode的9个属性做了详细总结,需要的朋友可以参考下     在前面的一篇文章中 ...

  4. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  5. Android中Application类的详解:

    Android中Application类的详解: 我们在平时的开发中,有时候可能会须要一些全局数据.来让应用中的全部Activity和View都能訪问到.大家在遇到这样的情况时,可能首先会想到自定义一 ...

  6. Android 中的消息传递,详解广播机制

    --------------------------------------广播机制简介--------------------------------------------- Android中的广 ...

  7. Android中的sharedUserId属性详解

    在Android里面每个app都有一个唯一的linux user ID,则这样权限就被设置成该应用程序的文件只对该用户可见,只对该应用程序自身可见,而我们可以使他们对其他的应用程序可见,这会使我们用到 ...

  8. Android中Activity启动模式详解

    在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. An ...

  9. Android中数据库的操作流程详解

    Android中数据库的操作方法: 1.Android平台提供了一个数据库辅助类来创建或打开数据库. 这个辅助类继承自SQLiteOpenHelper类.继承和扩展SQLiteOpenHelper类主 ...

随机推荐

  1. Random Forest vs GradientBoostingDecisionTree

    相同 随机森林和GBDT都属于集成算法,base model都是决策树. 不同 随机森林 随机森林是决策树的bagging. bagging通过重复对原训练数据集上进行有放回地采样生成的数据集用bas ...

  2. ●洛谷P1291 [SHOI2002]百事世界杯之旅

    题链: https://www.luogu.org/recordnew/show/5861351题解: dp,期望 定义dp[i]表示还剩下i个盖子没收集时,期望还需要多少次才能手机完. 初始值:dp ...

  3. hdu 1043(经典搜索)

    题意: 给你一个初始的图,然后每次输入一个图,要求移动x最小的步数达到和初始图一样,输出路径 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6 7 8 5 6 7 ...

  4. [bzoj4922]Karp-de-Chant Number

    来自FallDream的博客,未经允许,请勿转载,谢谢. 卡常数被称为计算机算法竞赛之中最神奇的一类数字,主要特点集中于令人捉摸不透,有时候会让水平很高的选手迷之超时. 普遍认为卡常数是埃及人Qa'a ...

  5. Python3 中 random模块

    Python中的random模块用于生成随机数. 下面具体介绍random模块的功能: 1.random.random() #用于生成一个0到1的 随机浮点数:0<= n < 1.0 im ...

  6. Django中Form的基本使用

    from django import forms from django.forms import fields class UserInfo(forms.Form): username = fiel ...

  7. c语言第四次作业

    (一)改错题 输出三角形的面积和周长,输入三角形的三条边a.b.c,如果能构成一个三角形,输出面积area和周长perimeter(保留2位小数):否则,输出"These sides do ...

  8. TensorFlow Serving-TensorFlow 服务

    TensorFlow服务是一个用于服务机器学习模型的开源软件库.它处理机器学习的推断方面,在培训和管理他们的生命周期后采取模型,通过高性能,引用计数的查找表为客户端提供版本化访问. 可以同时提供多个模 ...

  9. Elasticsearch 学习(一):入门

    一.概念 Elasticsearch 是一个实时分布式搜索和分析引擎.它用于全文搜索.结构化搜索.分析以及将这三者混合使用. 维基百科.英国卫报.StackOverflow.Github 等公司都在使 ...

  10. 数据结构之并查集Union-Find Sets

    1.  概述 并查集(Disjoint set或者Union-find set)是一种树型的数据结构,常用于处理一些不相交集合(Disjoint Sets)的合并及查询问题. 2.  基本操作 并查集 ...