说到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. [NOI2015]品酒大会

    题目描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战 两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒师 Rainb ...

  2. bzoj 5290: [Hnoi2018]道路

    Description Solution PJDP毁青春 注意到性质:到根的道路不超过 \(40\) 条 所以我们只关系一个点上面的道路的情况就行了 设 \(f[x][i][j]\) 表示一个点 \( ...

  3. 【网络流】【BZOJ1070】【SCOI2007】修车

    原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1070 题意:问你如何分配老司机使得每部车的等待时间之和最短. 解题思路:本题不易正做,考虑 ...

  4. 2015 多校联赛 ——HDU5353(构造)

    Each soda has some candies in their hand. And they want to make the number of candies the same by do ...

  5. poj 2065 高斯消元(取模的方程组)

    SETI Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 1735   Accepted: 1085 Description ...

  6. [luoguP3729]曼哈顿计划EX

    来自FallDream的博客,未经允许,请勿转载,谢谢. 艾登拥有一个计算机网络,每一台计算机都至少有着Intel Xeon E50 v40 + 40路GTX10800Titan的恐怖配置,并由无线网 ...

  7. Servlet技术 Cookie与Session

    会话过程:用户打开浏览器,点击链接访问资源,最后到关闭浏览器的整个过程称之为会话. 会话使用:与服务器进行会话的过程中产生数据,数据被保存下来,服务器根据数据对客户进行辨别,做出个性化的响应. 介绍两 ...

  8. 643. Maximum Average Subarray

    Given an array consisting of \(n\) integers, find the contiguous subarray of given length \(k\) that ...

  9. Luogu P1919 【模板】A*B Problem升级版(FFT快速傅里叶_FFT

    这其实就是一道裸的FFT 核心思想:把两个数拆成两个多项式用FFT相乘,再反序输出 py解法如下: input() print(int(input())*int(input())) 皮一下hihi f ...

  10. EF Core 2.0使用MsSql/Mysql实现DB First和Code First

    参考地址 EF官网 ASP.NET Core MVC 和 EF Core - 教程系列 环境 Visual Studio 2017 最新版本的.NET Core 2.0 SDK 最新版本的 Windo ...