MyException - 我的异常网
当前位置:我的异常网» 移动开发 » ViewFlipper的施用

ViewFlipper的施用

www.myexceptions.net  网友分享于:2013-07-02  浏览:32次
ViewFlipper的使用
通过查看API文档可以发现,有个android.widget.ViewAnimator类继承至FrameLayout,ViewAnimator类的作用是为FrameLayout里面的View切换提供动画效果。该类有如下几个和动画相关的函数:
l setInAnimation:设置View进入屏幕时候使用的动画,该函数有两个版本,一个接受单个参数,类型为android.view.animation.Animation;一个接受两个参数,类型为Context和int,分别为Context对象和定义Animation的resourceID。

setOutAnimation: 设置View退出屏幕时候使用的动画,参数setInAnimation函数一样。
showNext: 调用该函数来显示FrameLayout里面的下一个View。
showPrevious: 调用该函数来显示FrameLayout里面的上一个View。

一般不直接使用ViewAnimator而是使用它的两个子类ViewFlipper和ViewSwitcher。ViewFlipper可以用来指定FrameLayout内多个View之间的切换效果,可以一次指定也可以每次切换的时候都指定单独的效果。该类额外提供了如下几个函数:

isFlipping: 用来判断View切换是否正在进行
setFilpInterval:设置View之间切换的时间间隔
startFlipping:使用上面设置的时间间隔来开始切换所有的View,切换会循环进行
stopFlipping: 停止View切换
ViewSwitcher 顾名思义Switcher特指在两个View之间切换。可以通过该类指定一个ViewSwitcher.ViewFactory 工程类来创建这两个View。该类也具有两个子类ImageSwitcher、TextSwitcher分别用于图片和文本切换。


ViewFlipper示例
记住,ViewFlipper是继承至FrameLayout的,所以它是一个Layout里面可以放置多个View。在示例中定义一个ViewFlipper,里面包含三个ViewGroup作为示例的三个屏幕,每个ViewGroup中包含一个按钮和一张图片,点击按钮则显示下一个屏幕。代码如下(res\layout\main.xml):
view plaincopy to clipboardprint?
<?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>   
          
       <LinearLayout   
           android:orientation="vertical"  
           android:layout_width="fill_parent"    
           android:layout_height="fill_parent">   
           <Button   
              android:text="Next"    
              android:id="@+id/Button_next3"  
              android:layout_width="fill_parent"    
              android:layout_height="wrap_content">   
           </Button>   
           <ImageView   
              android:id="@+id/image3"    
              android:src="@drawable/lenovo"  
              android:layout_width="fill_parent"  
              android:layout_height="wrap_content">   
           </ImageView>   
       </LinearLayout>   
    
    </ViewFlipper>   
    
</LinearLayout>  

很简单,在Layout定义中指定动画的相关属性就可以了,通过persistentDrawingCache指定缓存策略;flipInterval指定每个View动画之间的时间间隔;inAnimation和outAnimation分别指定View进出使用的动画效果。动画效果定义如下:
view plaincopy to clipboardprint?
res\anim\push_left_in.xml   
<?xml version="1.0" encoding="utf-8"?>   
<set xmlns:android="http://schemas.android.com/apk/res/android">   
    <translate   
    android:fromXDelta="100%p"    
    android:toXDelta="0"    
    android:duration="500"/>   
    <alpha   
    android:fromAlpha="0.0"    
    android:toAlpha="1.0"  
    android:duration="500" />   
</set>   
res\anim\push_left_out.xml   
<?xml version="1.0" encoding="utf-8"?>   
<set xmlns:android="http://schemas.android.com/apk/res/android">   
    <translate   
    android:fromXDelta="0"    
    android:toXDelta="-100%p"    
    android:duration="500"/>   
    <alpha   
    android:fromAlpha="1.0"    
    android:toAlpha="0.0"    
    android:duration="500" />   
</set>  


Activity代码如下(src\cc\c\TestActivity.java):
view plaincopy to clipboardprint?
public class TestActivity extends Activity {   
    private ViewFlipper mViewFlipper;   
    @Override  
    public void onCreate(Bundle savedInstanceState) {   
        super.onCreate(savedInstanceState);   
        setContentView(R.layout.main);   
           
        Button buttonNext1 = (Button) findViewById(R.id.Button_next1);   
        mViewFlipper = (ViewFlipper) findViewById(R.id.flipper);   
        buttonNext1.setOnClickListener(new View.OnClickListener() {   
            public void onClick(View view) {   
                //在layout中定义的属性,也可以在代码中指定   
//             mViewFlipper.setInAnimation(getApplicationContext(), R.anim.push_left_in);   
//             mViewFlipper.setOutAnimation(getApplicationContext(), R.anim.push_left_out);   
//             mViewFlipper.setPersistentDrawingCache(ViewGroup.PERSISTENT_ALL_CACHES);   
//             mViewFlipper.setFlipInterval(1000);   
                mViewFlipper.showNext();   
                //调用下面的函数将会循环显示mViewFlipper内的所有View。   
//             mViewFlipper.startFlipping();   
        }   
        });   
    
        Button buttonNext2 = (Button) findViewById(R.id.Button_next2);   
        buttonNext2.setOnClickListener(new View.OnClickListener() {   
            public void onClick(View view) {   
                mViewFlipper.showNext();   
        }   
    
        });      
        Button buttonNext3 = (Button) findViewById(R.id.Button_next3);   
        buttonNext3.setOnClickListener(new View.OnClickListener() {   
            public void onClick(View view) {   
                mViewFlipper.showNext();   
        }   
    
        });   
    
    }   
    }  
通过手势移动屏幕
上面是通过屏幕上的按钮来在屏幕间切换的,这看起来多少有点不符合OPhone的风格,如果要是能通过手势的左右滑动来实现屏幕的切换就比较优雅了。
通过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函数中初始化:
mGestureDetector = new GestureDetector(this);

参数是OnGestureListener,然后让TestActivity实现 OnGestureListener 和OnDoubleTapListener接口:


view plaincopy to clipboardprint?
class TestActivity extends Activity implements OnGestureListener , OnDoubleTapListener  
然后在onFling函数中实现切换屏幕的功能:
view plaincopy to clipboardprint?
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,   
           float velocityY) {   
       Log.d(tag, "...onFling...");   
       if(e1.getX() > e2.getX()) {//move to left   
           mViewFlipper.showNext();   
       }else if(e1.getX() < e2.getX()) {   
           mViewFlipper.setInAnimation(getApplicationContext(), R.anim.push_right_in);   
           mViewFlipper.setOutAnimation(getApplicationContext(), R.anim.push_right_out);   
           mViewFlipper.showPrevious();   
           mViewFlipper.setInAnimation(getApplicationContext(), R.anim.push_left_in);   
           mViewFlipper.setOutAnimation(getApplicationContext(), R.anim.push_left_out);   
       }else {   
           return false;   
       }   
       return true;   
    }  

这里实现的功能是从右往左滑动则切换到上一个View,从左往右滑动则切换到下一个View,并且使用不同的in、out 动画使切换效果看起来统一一些。
然后在onDoubleTap中实现双击自动切换的效果,再次双击则停止:
   
view plaincopy to clipboardprint?
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)这个构造函数的源代码了:
view plaincopy to clipboardprint?
    public GestureDetector(OnGestureListener listener) {   
        this(null, listener, null);   
}  

调用了另外一个构造函数:
  
view plaincopy to clipboardprint?
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没有?现在明白了吧。


[功能]
1. ViewFlipper 可以包含多个View 且View之间的切换有Animation  比如:渐变效果


[代码]
1. 创建包含ViewFlipper 的main.xml 还包含2个Button 用于各个View切换
1.<?xml version="1.0" encoding="utf-8"?> 
2.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
3.    android:orientation="vertical" 
4.    android:layout_width="fill_parent" 
5.    android:layout_height="fill_parent" 
6.    > 
7.    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
8.    android:orientation="horizontal" 
9.    android:layout_width="wrap_content" 
10.    android:layout_height="wrap_content" 
11.    > 
12.    <Button 
13.    android:id="@+id/previousButton"   
14.    android:layout_width="wrap_content"  
15.    android:layout_height="wrap_content"  
16.    android:text="Previous" 
17.    /> 
18.    <Button 
19.    android:id="@+id/nextButton"   
20.    android:layout_width="wrap_content"  
21.    android:layout_height="wrap_content"  
22.    android:text="Next" 
23.    /> 
24.    </LinearLayout> 
25.<ViewFlipper   
26.    android:id="@+id/flipper" 
27.    android:layout_width="fill_parent"  
28.    android:layout_height="fill_parent"  
29.    android:gravity="center" 
30.    > 
31.</ViewFlipper> 
32.</LinearLayout> 
<?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"
    >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >
<Button
android:id="@+id/previousButton" 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Previous"
    />
    <Button
android:id="@+id/nextButton" 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Next"
    />
    </LinearLayout>
<ViewFlipper 
android:id="@+id/flipper"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    >
</ViewFlipper>
</LinearLayout>



2. 设定 Animation 效果
1.flipper = (ViewFlipper) findViewById(R.id.flipper); 
2.flipper.setInAnimation(AnimationUtils.loadAnimation(this, 
3.                android.R.anim.fade_in)); 
4.flipper.setOutAnimation(AnimationUtils.loadAnimation(this, 
5.                android.R.anim.fade_out)); 
flipper = (ViewFlipper) findViewById(R.id.flipper);
flipper.setInAnimation(AnimationUtils.loadAnimation(this,
                android.R.anim.fade_in));
flipper.setOutAnimation(AnimationUtils.loadAnimation(this,
                android.R.anim.fade_out));

3. 在 ViewFlipper  里面增加各种View
1.flipper.addView(addTextByText("HelloAndroid")); 
2.        flipper.addView(addImageById(R.drawable.beijing_003_mb5ucom)); 
3.        flipper.addView(addTextByText("eoe.Android")); 
4.        flipper.addView(addImageById(R.drawable.beijing_004_mb5ucom)); 
5.        flipper.addView(addTextByText("Gryphone")); 
6. 
7.ublic View addTextByText(String text){ 
8.            TextView tv = new TextView(this); 
9.            tv.setText(text); 
10.            tv.setGravity(1); 
11.            return tv; 
12.    } 
13.     
14.    public View addImageById(int id){ 
15.        ImageView iv = new ImageView(this); 
16.        iv.setImageResource(id); 
17.         
18.        return iv; 
19.    } 
flipper.addView(addTextByText("HelloAndroid"));
        flipper.addView(addImageById(R.drawable.beijing_003_mb5ucom));
        flipper.addView(addTextByText("eoe.Android"));
        flipper.addView(addImageById(R.drawable.beijing_004_mb5ucom));
        flipper.addView(addTextByText("Gryphone"));

ublic View addTextByText(String text){
    TextView tv = new TextView(this);
    tv.setText(text);
    tv.setGravity(1);
    return tv;
    }
   
    public View addImageById(int id){
ImageView iv = new ImageView(this);
iv.setImageResource(id);

return iv;
    }


4. View 切换
* 下一个View
1.flipper.showNext(); 
flipper.showNext();

* 上一个View
1.flipper.showPrevious(); 

文章评论

老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
旅行,写作,编程
旅行,写作,编程
每天工作4小时的程序员
每天工作4小时的程序员
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
10个调试和排错的小建议
10个调试和排错的小建议
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
Java程序员必看电影
Java程序员必看电影
为什么程序员都是夜猫子
为什么程序员都是夜猫子
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
中美印日四国程序员比较
中美印日四国程序员比较
总结2014中国互联网十大段子
总结2014中国互联网十大段子
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
 程序员的样子
程序员的样子
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
程序员都该阅读的书
程序员都该阅读的书
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
我是如何打败拖延症的
我是如何打败拖延症的
鲜为人知的编程真相
鲜为人知的编程真相
程序员必看的十大电影
程序员必看的十大电影
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
老程序员的下场
老程序员的下场
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
我的丈夫是个程序员
我的丈夫是个程序员
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
程序员的鄙视链
程序员的鄙视链
那些争议最大的编程观点
那些争议最大的编程观点
程序员应该关注的一些事儿
程序员应该关注的一些事儿
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
一个程序员的时间管理
一个程序员的时间管理
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
程序员和编码员之间的区别
程序员和编码员之间的区别
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有