23. 【Android教程】轮播滚动视图:ViewFlipper

简介: 23. 【Android教程】轮播滚动视图:ViewFlipper

轮播视图 ViewFlipper 是 Android 从第一个版本就开始提供的 UI 控件,它能够承载多个 View,但一个时机只会有一个 View 展示在屏幕上。通过 ViewFlipper 我们可以实现很多常见的带有展示类型的功能,类似 Gallery、轮播图、导航栏、广告banner等功能,我们可以通过左右滑动、也可以设置定时自动滚动来切换 View。

1. ViewFlipper 的特性

ViewFlipper 是 FrameLayout 的子类,我们可以向 ViewFlipper 中插入一个或多个 View,而由于它是直接继承自 ViewAnimator,从名字上我们可以猜到,它可以对我们插入的多个 View 做各种动画效果,最常见的效果就是对图片做定时轮播。



2. ViewFlipper 的基本用法

在第 1 小节我们提到过,ViewFlipper 拥有两大特性:可以插入 View 并且支持对插入的 View 添加动画,这两个特性都可以采用布局和代码的形式进行设置,下面分别做介绍。

2.1 ViewFlipper 的常用属性

  • android:inAnimation:
    设置 View 进入屏幕的动画效果,默认采用系统动画。
  • android:outAnimation:
    设置 View 离开屏幕时的动画效果,默认采用系统动画。
  • android:flipInterval:
    设置各个 View 切换的时间间隔。

2.2 ViewFlipper 的常用API

对于 ViewFlipper 如果只是简单的滚动,用属性静态设置是非常方便的。但实际开发中很多场景需要配合一些业务逻辑控制,所以大多数时候我们会用 API 来控制翻滚。

  • setInAnimation:
  • 设置入场动画,类似属性android:inAnimation
  • setOutAnimation:
    设置出场动画,类似属性android:outAnimation
  • showNext:
    展示 ViewFlipper 里的下一个 View。
  • showPrevious:
  • 展示 ViewFlipper 里的上一个 View。
  • setFilpInterval:
  • 设置各个 View 切换的时间间隔。
  • startFlipping:
  • 为 ViewFlipping 的所有子 View 启动一个定时器控制轮播。
  • stopFlipping:
  • 停止 ViewFlipping 切换。
  • setAutoStart:
    是否自动启动,设置成 true 则会在 ViewFlipping attach 到 Window 的时候自动调用startFlipping启动轮播。

3. ViewFlipper 使用示例

本节我们会实现一个 3 屏轮流滚动的功能,支持 View 之间自动滚动并通过监听 MotionEvent 来支持左右滑动切换。

3.1 布局文件

首先我们来通过 xml 编写布局文件,根据上面的需求要在 ViewFlipper 中放入 3 个布局。我们用一个 RelativeLayout 作为一个 ViewFlipper 的子 View 占满一屏内容,只需要包含三个这样的 RelativeLayout 即可,,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:showIn="@layout/activity_main">
 
    <ViewFlipper
        android:id="@+id/view_flipper"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:inAnimation="@anim/in_from_right"
        android:outAnimation="@anim/out_from_left">
 
        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">
 
            <ImageView
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_gravity="center"
                android:adjustViewBounds="true"
                android:background="@android:color/black"
                android:scaleType="centerCrop" />
 
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:gravity="center"
                android:text="第一屏:好好学Android"
                android:textColor="@android:color/white"
                android:textSize="18dp"
                android:textStyle="bold" />
        </RelativeLayout>
 
        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">
 
            <ImageView
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_gravity="center"
                android:adjustViewBounds="true"
                android:background="@android:color/darker_gray"
                android:scaleType="centerCrop" />
 
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:gravity="center"
                android:text="第二屏:好好学Android"
                android:textSize="18dp"
                android:textStyle="bold" />
        </RelativeLayout>
 
        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">
 
            <ImageView
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_gravity="center"
                android:adjustViewBounds="true"
                android:background="@android:color/holo_green_light"
                android:scaleType="centerCrop" />
 
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:gravity="center"
                android:text="第三屏:好好学Android"
                android:textSize="18dp"
                android:textStyle="bold" />
        </RelativeLayout>
    </ViewFlipper>
</RelativeLayout>

可以看到其实 ViewFlipper 的子 View 和我们平时开发时用到的布局没有什么差别,然后将每一屏的内容作为 ViewFlipper 的子 View 添加进去即可。

3.2 编写入场和出场动画

细心的朋友们应该会注意到,在布局文件的<ViewFlipper/>标签中有这么两个属性:

android:inAnimation="@anim/in_from_right"
android:outAnimation="@anim/out_from_left"

根据 2.1 小节对属性的介绍,我们知道这是用来设置出场和入场动画的,所以接下来我们就来完善这两个动画效果,首先按照以下步骤创建一个动画资源:

右键点击“res”目录,一次选择“New” -> “Android Resource Directory”

在“Resource type”中选择“anim”,点“OK”,创建一个动画资源目录

  1. 此时“res”目录下就有了“anim”文件夹,在里面创建四个动画文件:
  • in_from_left.xml:

表示从左侧进入的动画,代码如下:

其中<translate/>标签表示一个 TranslateAnimation,专门用来实现移动补间动画,具体关于动画的用法在后面的动画专题章节有详细的讲解,这里我们关注 ViewFlipper,对动画只需要做一点了解即可。

其余三个动画都类似:

  • **in_from_right.xml:**表示从右侧进入,代码如下:
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:duration="1400"
        android:fromXDelta="100%"
        android:fromYDelta="0%" />
</set>
  • **out_from_left:**从左侧移出:
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:duration="1400"
        android:fromXDelta="0%"
        android:toXDelta="-100%"/>
</set>
  • **out_from_right:**从右侧移出:
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:duration="1400"
        android:fromXDelta="0%"
        android:fromYDelta="0%"
        android:toXDelta="100%"
        android:toYDelta="0%" />
</set>

3.3 编写 MainActivity

我们要实现 ViewFlipper 的滑动切换,也就是在用户左滑的时候切换到下一页,而右滑切换到上一页。所以在 MainActivity 里面主要做的是获取 ViewFlipper 对象,然后监听用户的滑动手势从而设置相应的出场 / 入场动画,最后调用showNext()或showPrevious()来最终实现上下页切换的效果,整体代码如下:

package com.emercy.myapplication;
 
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.animation.AnimationUtils;
import android.widget.ViewFlipper;
 
 
public class MainActivity extends Activity {
 
    private ViewFlipper mViewFlipper;
    private Context mContext;
    private float initialX;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
        mViewFlipper = findViewById(R.id.view_flipper);
    }
 
    @Override
    public boolean onTouchEvent(MotionEvent touchEvent) {
        switch (touchEvent.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 记录滑动初始坐标
                initialX = touchEvent.getX();
                break;
            case MotionEvent.ACTION_UP:
                // 记录滑动结束坐标
                float finalX = touchEvent.getX();
                if (initialX > finalX) {
                    // 初始坐标大于结束坐标,说明为左滑,则播放下一页
                    if (mViewFlipper.getDisplayedChild() != 2) {
                        mViewFlipper.setInAnimation(mContext, R.anim.in_from_right);
                        mViewFlipper.setOutAnimation(mContext, R.anim.out_from_left);
                        mViewFlipper.showNext();
                    }
                } else {
                    // 初始坐标不大于结束坐标,说明为右滑,则播放上一页
                    if (mViewFlipper.getDisplayedChild() != 0) {
                        mViewFlipper.setInAnimation(mContext, R.anim.in_from_left);
                        mViewFlipper.setOutAnimation(mContext, R.anim.out_from_right);
                        mViewFlipper.showPrevious();
                    }
                }
                break;
        }
        return false;
    }
}

在代码中我们覆写了onTouchEvent,在 Activity 中的 View 被触摸的时候会回调此函数,我们在MotionEvent.ACTION_DOWN的时候记录触摸时的坐标,然后在MotionEvent.ACTION_UP的时候记录抬起时的坐标,根据触摸起始和结束坐标的差值我们能够推断出用户是左滑还是右滑,从而播放下一页或者上一页。

3.4 自动轮播

第 2 小节介绍了一个API:setAutoStart(),它是用来实现自动播放的,所以我们可以给 ViewFlipper 加上自动轮播的功能。

为了控制自动播放和停止,在布局代码中我们加入两个 Button,样式可以直接借用系统播放器的两个资源文件:@android:drawable/ic_media_play和@android:drawable/ic_media_pause,从名字可以看出这是“播放”和“停止”两个按钮,直接在activity_main.xml中根布局<RelativeLayout/>标签的最后加入以下布局代码:

   <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentTop="true"
        android:gravity="center"
        android:orientation="horizontal">
 
        <Button
            android:id="@+id/play"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginRight="10dp"
            android:background="@android:drawable/ic_media_play" />
 
        <Button
            android:id="@+id/stop"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="@android:drawable/ic_media_pause" />
    </LinearLayout>

在 Java 代码中监听这两个 Button 的点击事件,在点击播放的时候自动翻下一页,对应的动画就是右边进入和左边退出,即in_from_rightout_from_left。我们可以在布局文件中的<ViewFlipper/>标签中加入

android:inAnimation="@anim/in_from_right"
android:outAnimation="@anim/out_from_left"

或者在 Java 代码中通过

mViewFlipper.setInAnimation();
mViewFlipper.setOutAnimation();

设置入场和出场动画,最终在 MainActivity 的 onCreate()函数的末尾添加如下 Java 代码:

findViewById(R.id.play).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mViewFlipper.setAutoStart(true);
                mViewFlipper.setInAnimation(mContext, R.anim.in_from_right);
                mViewFlipper.setOutAnimation(mContext, R.anim.out_from_left);
                mViewFlipper.setFlipInterval(2000);
                mViewFlipper.startFlipping();
                Toast.makeText(MainActivity.this,
                        "启动自动播放", Toast.LENGTH_SHORT).show();
            }
        });
 
 
        findViewById(R.id.stop).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mViewFlipper.stopFlipping();
                Toast.makeText(MainActivity.this,
                        "停止自动播放", Toast.LENGTH_SHORT).show();
            }
        });

运行之后点击播放即可实现自动翻页。

4. 小结

本节学习了一个很方便实现幻灯片、轮播图的控件:ViewFlipper,在运营活动、广告 Banner 等场景非常常见,可以通过 xml 静态或者 API 动态设置动画及翻转时间间隔,也可以主动触发上翻和下翻动作。大家可以自己思考一下,如果不用 ViewFlipper,只用前面讲的基础布局如何实现这个效果。


相关文章
|
1月前
|
缓存 前端开发 Android开发
安卓开发中的自定义视图:从零到英雄
【10月更文挑战第42天】 在安卓的世界里,自定义视图是一块画布,让开发者能够绘制出独一无二的界面体验。本文将带你走进自定义视图的大门,通过深入浅出的方式,让你从零基础到能够独立设计并实现复杂的自定义组件。我们将探索自定义视图的核心概念、实现步骤,以及如何优化你的视图以提高性能和兼容性。准备好了吗?让我们开始这段创造性的旅程吧!
26 1
|
2月前
|
Android开发 开发者
安卓应用开发中的自定义视图
【9月更文挑战第37天】在安卓开发的海洋中,自定义视图犹如一座座小岛,等待着勇敢的探索者去发现其独特之处。本文将带领你踏上这段旅程,从浅滩走向深海,逐步揭开自定义视图的神秘面纱。
44 3
|
4月前
|
供应链 物联网 区块链
未来触手可及:探索新兴技术的趋势与应用安卓开发中的自定义视图:从基础到进阶
【8月更文挑战第30天】随着科技的飞速发展,新兴技术如区块链、物联网和虚拟现实正在重塑我们的世界。本文将深入探讨这些技术的发展趋势和应用场景,带你领略未来的可能性。
|
1月前
|
Android开发 数据安全/隐私保护 虚拟化
安卓手机远程连接登录Windows服务器教程
安卓手机远程连接登录Windows服务器教程
62 4
|
1月前
|
Android开发
布谷语音软件开发:android端语音软件搭建开发教程
语音软件搭建android端语音软件开发教程!
|
1月前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
3月前
|
Android开发 开发者
安卓开发中的自定义视图:从入门到精通
【9月更文挑战第19天】在安卓开发的广阔天地中,自定义视图是一块充满魔力的土地。它不仅仅是代码的堆砌,更是艺术与科技的完美结合。通过掌握自定义视图,开发者能够打破常规,创造出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战应用,一步步展示如何用代码绘出心中的蓝图。无论你是初学者还是有经验的开发者,这篇文章都将为你打开一扇通往创意和效率的大门。让我们一起探索自定义视图的秘密,将你的应用打造成一件艺术品吧!
71 10
|
3月前
|
XML 编解码 Android开发
安卓开发中的自定义视图控件
【9月更文挑战第14天】在安卓开发中,自定义视图控件是一种高级技巧,它可以让开发者根据项目需求创建出独特的用户界面元素。本文将通过一个简单示例,引导你了解如何在安卓项目中实现自定义视图控件,包括创建自定义控件类、处理绘制逻辑以及响应用户交互。无论你是初学者还是有经验的开发者,这篇文章都会为你提供有价值的见解和技巧。
55 3
|
3月前
|
前端开发 Android开发 开发者
安卓应用开发中的自定义视图基础
【9月更文挑战第13天】在安卓开发的广阔天地中,自定义视图是一块神奇的画布,它允许开发者将想象力转化为用户界面的创新元素。本文将带你一探究竟,了解如何从零开始构建自定义视图,包括绘图基础、触摸事件处理,以及性能优化的实用技巧。无论你是想提升应用的视觉吸引力,还是追求更流畅的交互体验,这里都有你需要的金钥匙。
|
3月前
|
前端开发 搜索推荐 Android开发
探索安卓开发中的自定义视图##
【9月更文挑战第6天】 在安卓应用开发的世界里,自定义视图如同绘画艺术中的色彩,它们为界面设计增添了无限可能。通过掌握自定义视图的绘制技巧,开发者能够创造出既符合品牌形象又提升用户体验的独特界面元素。本文将深入浅出地介绍如何从零开始构建一个自定义视图,包括基础框架搭建、关键绘图方法实现、事件处理机制以及性能优化策略。准备好让你的安卓应用与众不同了吗?让我们开始吧! ##