Android中ViewFlipper的使用详解
说到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中的布局:
- <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" >
- <ViewFlipper
- android:id="@+id/flipper"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_marginTop="10dp"
- android:flipInterval="2000" >
- <ImageView
- android:layout_width="fill_parent"
- android:layout_height="300dip"
- android:scaleType="fitXY"
- android:src="@drawable/img_1"/>
- <ImageView
- android:layout_width="fill_parent"
- android:layout_height="300dip"
- android:scaleType="fitXY"
- android:src="@drawable/img_2"/>
- <ImageView
- android:layout_width="fill_parent"
- android:layout_height="300dip"
- android:scaleType="fitXY"
- android:src="@drawable/img_3"/>
- <ImageView
- android:layout_width="fill_parent"
- android:layout_height="300dip"
- android:scaleType="fitXY"
- android:src="@drawable/img_4"/>
- </ViewFlipper>
- </RelativeLayout>
在ViewFlipper中,加入四个ImageView子控件,其中flipInterval属性是用来设置多少毫秒自动显示下一个视图;
2、JAVA代码:
- public class MainActivity extends Activity {
- ViewFlipper flipper;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- flipper = (ViewFlipper) findViewById(R.id.flipper);
- flipper.startFlipping();//开始切换,注意,如果设置了时间间隔,想让它自动切换,一定要记得加它
- }
- }
这部分代码非常简单,直接调用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的使用详解的更多相关文章
- Android中Service的使用详解和注意点(LocalService)
Android中Service的使用详解和注意点(LocalService) 原文地址 开始,先稍稍讲一点android中Service的概念和用途吧~ Service分为本地服务(LocalServ ...
- Android中SurfaceView的使用详解
Android中SurfaceView的使用详解 http://blog.csdn.net/listening_music/article/details/6860786 Android NDK开发 ...
- Android中的windowSoftInputMode属性详解
这篇文章主要介绍了Android中的windowSoftInputMode属性详解,本文对windowSoftInputMode的9个属性做了详细总结,需要的朋友可以参考下 在前面的一篇文章中 ...
- Android中Canvas绘图基础详解(附源码下载) (转)
Android中Canvas绘图基础详解(附源码下载) 原文链接 http://blog.csdn.net/iispring/article/details/49770651 AndroidCa ...
- Android中Application类的详解:
Android中Application类的详解: 我们在平时的开发中,有时候可能会须要一些全局数据.来让应用中的全部Activity和View都能訪问到.大家在遇到这样的情况时,可能首先会想到自定义一 ...
- Android 中的消息传递,详解广播机制
--------------------------------------广播机制简介--------------------------------------------- Android中的广 ...
- Android中的sharedUserId属性详解
在Android里面每个app都有一个唯一的linux user ID,则这样权限就被设置成该应用程序的文件只对该用户可见,只对该应用程序自身可见,而我们可以使他们对其他的应用程序可见,这会使我们用到 ...
- Android中Activity启动模式详解
在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. An ...
- Android中数据库的操作流程详解
Android中数据库的操作方法: 1.Android平台提供了一个数据库辅助类来创建或打开数据库. 这个辅助类继承自SQLiteOpenHelper类.继承和扩展SQLiteOpenHelper类主 ...
随机推荐
- shell编程-邮件发送设置
在linux 运维过程中,经常会写一些脚本监控一些服务器的状态,如监控redis 主从切换,redis 宕机等,当事件发生时,应该发送邮件通知到相对应的管理员,因此就需要搭建邮件服务,使linux 能 ...
- [Jsoi2011]分特产
Description JYY 带队参加了若干场ACM/ICPC 比赛,带回了许多土特产,要分给实验室的同学们. JYY 想知道,把这些特产分给N 个同学,一共有多少种不同的分法?当然,JYY 不希望 ...
- bzoj 3751: [NOIP2014]解方程
Description 已知多项式方程: a0+a1x+a2x^2+...+an*x^n=0 求这个方程在[1,m]内的整数解(n和m均为正整数). 解题报告: 这题比较诡,看到高精度做不了,就要想到 ...
- poj 2417 && poj3243(Baby-Step Giant-Step)
Discrete Logging Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4624 Accepted: 2113 ...
- bzoj1044[HAOI2008]木棍分割 单调队列优化dp
1044: [HAOI2008]木棍分割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4314 Solved: 1664[Submit][Stat ...
- WebStorm配置node.js调试
最近因为工作关系,一直在做node.js的开发,学习了koa框架,orm框架sequelize,以及swagger文档的配置.但是,最近因为swagger文档使用了es6的修饰器那么个东西(在java ...
- PTA 邻接矩阵存储图的深度优先遍历
6-1 邻接矩阵存储图的深度优先遍历(20 分) 试实现邻接矩阵存储图的深度优先遍历. 函数接口定义: void DFS( MGraph Graph, Vertex V, void (*Visit)( ...
- avalon,xmp
- hibernate实体对象的三种状态:自由状态,持久状态,游离状态.
自由态与游离态的区别: 当一个持久化对象,脱离开Hibernate的缓存管理后,它就处于游离状态,游离对象和自由对象的最大区别在于,游离对象在数据库中可能还存在一条与它 对应的记录,只是现在这个游离对 ...
- 动态SQL中不同变量的写法总结
.一般变量的写法: if (str_kind is not null) then l_str_kind := str_kind; v_wheresql := v_wheresql || ' and k ...