Android ViewFlipper

Android ViewFlipper

在很多APP都有如下的头条/热榜效果(上下自动翻滚)

在这里插入图片描述

这种效果可以使用很多方式实现,有一个简便的方式可以使用ViewFlipper控件实现,ViewFlipper控件继承结果如下:

请添加图片描述

可以看出ViewFlipper 继承自ViewAnimator,ViewAnimator可以将在添加到其中的两个或多个子View之间进行动画处理的简单。一次只显示子View。可以定期在每个子View之间自动翻转。

1.简单使用

1.1 通过xml布局配置翻滚的item

activity.xml布局中添加ViewFlipper控件

<ViewFlipperandroid:id="@+id/vf_incluede"android:layout_width="match_parent"android:layout_height="50dp"android:autoStart="true"android:background="#00dd00"android:inAnimation="@anim/anim_in"android:outAnimation="@anim/anim_out"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_vertical"android:paddingLeft="10dip"android:text="这第1条消息."android:textSize="20sp"android:textStyle="bold" /><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_vertical"android:paddingLeft="10dip"android:text="这第2条消息.."android:textSize="20sp"android:textStyle="bold" />
</ViewFlipper>

显示效果:

请添加图片描述

默认ViewFlipper是无动画,这里通过inAnimation、outAnimation配置来子View进入和移出动画,

inAnimation动画配置如下文件(anim/anim_in.xml):

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:duration="400"android:fromYDelta="100%p"android:toYDelta="0" /><alphaandroid:duration="500"android:fromAlpha="0.0"android:toAlpha="1.0" />
</set>

outAnimation动画配置如下文件(anim/anim_out.xml):

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:duration="400"android:fromYDelta="0"android:toYDelta="-100%p" /><alphaandroid:duration="500"android:fromAlpha="1.0"android:toAlpha="0.0" />
</set>

可以看出,这里的两个动画文件均使用的是补间动画的动画集合(位移动画、透明度动画)

ViewFlipper可配置的xml参数:

android:autoStart : 设置显示该组件是否是自动播放(默认 false)

android:inAnimation : 设置组件进入时使用的动画

android:outAnimation : 设置组件移出时使用的动画

android:flipInterval:设置自动播放的时间间隔(ViewFlipper默认3000ms)

android:animateFirstView:设置显示该组件的第一个View时是否使用动画(默认true,可以手动向空的ViewFlipper addView 方式添加View看到效果)

ViewFlipper可以通过代码设置上述配置(不再列举),也可以通过代码来控制播放,具体api如下:

startFlipping() :开始播放

stopFlipping() : 停止播放

1.2 通过动态代码添加翻滚的item

activity.xml布局中添加ViewFlipper控件

<ViewFlipperandroid:id="@+id/vf_no_incluede"android:layout_width="match_parent"android:layout_height="50dp"android:autoStart="true"android:background="#0000aa"android:inAnimation="@anim/anim_in"android:outAnimation="@anim/anim_out" />

第二步:通过代码添加子item

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final ViewFlipper v2 = findViewById(R.id.vf_no_incluede);//创建布局View view1 = LayoutInflater.from(this).inflate(R.layout.layout_view, null);View view2 = LayoutInflater.from(this).inflate(R.layout.layout_view, null);View view3 = LayoutInflater.from(this).inflate(R.layout.layout_view, null);((TextView) view1).setText("hello");((TextView) view2).setText("world");((TextView) view3).setText("fighting");//添加子itemv2.addView(view1);v2.addView(view2);v2.addView(view3);//设置自动循环v2.setAutoStart(true);v2.setFlipInterval(2000);// 每隔2秒自动切换一次v2.setOnTouchListener(new View.OnTouchListener() {private float startX;@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:startX = event.getX();break;case MotionEvent.ACTION_UP:float endX = event.getX();if (startX - endX > 100) { // 向右滑动v2.stopFlipping();v2.showNext();v2.startFlipping();} else if (endX - startX > 100) { // 向左滑动v2.stopFlipping();v2.showPrevious();v2.startFlipping();}break;}return true;}});//通过按钮来控制开始与暂停Button btn = findViewById(R.id.btn);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (!v2.isFlipping())v2.startFlipping();elsev2.stopFlipping();}});}
}

2.通过适配器的方式

AdapterViewFlipper的继承关系如下:

请添加图片描述

注:AdapterViewFlipper是api11(Android 3.0)中新增的,现在的APP最低支持版本肯定大于此版本,基本可以忽略。

从继承关系可以看出AdapterViewFlipper同ListView类似,都继承了AdapterView,所以AdapterViewFlipper可以像ListView一样使用数据适配器来填充数据。

先定义一个AdapterViewFlipper如下:

<AdapterViewFlipperandroid:id="@+id/vf_adapter"android:layout_width="match_parent"android:layout_height="50dp"android:layout_gravity="center"android:autoStart="true"android:background="#cccccc"android:flipInterval="2000"android:inAnimation="@animator/anim_in"android:outAnimation="@animator/anim_out" />

同ViewFlipper,AdapterViewFlipper默认是无动画,这里通过inAnimation、outAnimation配置来子View进入和移出动画(注意这里只能配置单一的ObjectAnimator属性动画),这里设置了一个自动播放动画间隔(android:flipInterval)3000毫秒,因为AdapterViewFlipper默认间隔是10000毫秒,android:autoStart 同ViewFlipper设置动画是否自动播放,android:animateFirstView在AdapterViewFlipper设置是无效的。

这里AdapterViewFlipper因为继承自AdapterViewAnimator所以它也有android:loopViews(设置循环到最后一个组件后是否自动“转头”到第一个组件)配置,但是,AdapterViewFlipper设置这个属性无效,源码解释为视图翻转器应该循环浏览视图(在AdapterViewFlipper构造函数中将loopViews设置了true)

AdapterViewFlipper同ViewFlipper可以通过代码设置上述配置(不再列举),也可以通过代码来控制播放,具体api如下:

startFlipping() :开始播放

stopFlipping() : 停止播放

inAnimation动画配置如下文件(animator/anim_in.xml):

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:duration="500"android:propertyName="translationY"android:valueFrom="150"android:valueTo="0" />

这里属性动画存放在animator目录下。

outAnimation动画配置如下文件(animator/anim_out.xml):

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:duration="500"android:propertyName="translationY"android:valueFrom="0"android:valueTo="-150"/>

这里的valueFrom、valueTo是移动距离(像素),如想适配,可使用代码创建属性动画计算View移动的精确距离。

AdapterViewFlipper因为继承了AdapterView,所以需要通过代码设置一个Adapter展现效果,数据适配器如下:

public class ViewFlipperAdapter extends BaseAdapter {private Context context;private List<String> data;public ViewFlipperAdapter(Context context, List<String> data) {this.context = context;this.data = data;}@Overridepublic int getCount() {return data == null ? 0 : data.size();}@Overridepublic Object getItem(int position) {return data == null ? null : data.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view;ViewHolder viewHolder;if (convertView == null) {view = LayoutInflater.from(context).inflate(R.layout.layout_item, parent, false);viewHolder = new ViewHolder(view);view.setTag(viewHolder);} else {view = convertView;viewHolder = (ViewHolder) convertView.getTag();}viewHolder.tv_item.setText(data.get(position));return view;}static class ViewHolder {public TextView tv_item;public ViewHolder(View view) {this.tv_item = view.findViewById(R.id.tv_item);}}
}

这里使用ViewHolder做了数据适配器View缓存处理,效率更高。

这里的每个item布局(layout_item)如下:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/tv_item"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:textSize="20sp"android:textStyle="bold" />

最后设置数据适配器到AdapterViewFlipper上即可:

AdapterViewFlipper avf_view = (AdapterViewFlipper) findViewById(R.id.avf_view);
List<String> data = new ArrayList<>();
for (int i = 0; i < 10000; i++) {data.add("这是第" + i + "条消息");
}
ViewFlipperAdapter viewFlipperAdapter = new ViewFlipperAdapter(this, data);
//也可通过代码设置动画
//avf_view.setInAnimation(ObjectAnimator.ofFloat(avf_view, View.TRANSLATION_Y,150.0f,0.0f));
//avf_view.setOutAnimation(ObjectAnimator.ofFloat(avf_view, View.TRANSLATION_Y,0.0f,-150.0f));
avf_view.setAdapter(viewFlipperAdapter);

注意

AdapterViewFlipper继承了AdapterView,所以同ListView,也可以设置setOnItemClickListener来监听每个Item的点击事件,当然也可以在数据适配中为每一个Item设置点击事件。这里如果setOnItemClickListener设置每个Item的点击事件,默认是不回调的,因为AdapterViewFlipper父类AdapterViewAnimator中重写了onTouchEvent函数,但是在MotionEvent.ACTION_DOWN时返回值一直是false,导致onTouchEvent函数中的MotionEvent.ACTION_UP,无法回调,从而无法回调OnItemClickListener,因此要想使回调生效,只需重写onTouchEvent函数,并返回true即可:

public class ClickAdapterViewFlipper extends AdapterViewFlipper {public ClickAdapterViewFlipper(Context context) {super(context);}public ClickAdapterViewFlipper(Context context, AttributeSet attrs) {super(context, attrs);}public ClickAdapterViewFlipper(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public ClickAdapterViewFlipper(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}@Overridepublic boolean onTouchEvent(MotionEvent ev) {super.onTouchEvent(ev);return true;}
}

代码中可以使用ClickAdapterViewFlipper,这样设置setOnItemClickListener就可以正常回调了。

3.ViewFlipper、AdapterViewFlipper对比

复用性

  • ViewFlipper中的子view只能在xml中提前写好,或者在代码中通过 addView 的形式添加,这种形式不具有复用性质,只能处理较少的数据。
  • AdapterViewFlipper 因为有数据适配器,所以具有复用属性,可以处理大量的数据。

动画效果

  • ViewFlipper在设置动画时接收的是Animation——补间动画,可以是单一动画效果,也可以是动画集合。
  • AdapterViewFlipper 在设置动画的时候接收的是 ObjectAnimator——属性动画,而且只能是单一动画,不能使用动画集合。

属性配置

  • ViewFlipper的默认Interval为3000ms(3秒);
  • AdapterViewFlipper的默认Interval为10000ms(10秒);
  • ViewFlipper只有1条数据也执行动画,AdapterViewFlipper只有1条数据时不会执行动画;
  • AdapterViewFlipper比ViewFlipper多一个android:loopViews配置,但是AdapterViewFlipper设置此属性无效;
  • AdapterViewFlipper中设置android:animateFirstView是无效的,在ViewFlipper中设置有效;

4.参考链接

Android 中 ViewFlipper、AdapterViewFlipper使用

Android之ViewFlipper使用详解

[【Android开发基础】轮播图ViewFlipper](

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/9063.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在VMware上利用Samba实现资源共享

一、背景 FTP协议能让主机之间的文件传输变得简单方便&#xff0c;但是FTP协议的本质是传输文件。 举个栗子&#xff1a;当客户端想修改服务器上的test.txt&#xff0c;需要先get test.txt将文件下载下来&#xff0c;修改后再put test.txt 有没有一种方式能使客户端直接修改…

关于支付接口测试点的思考

支付接口测试是一项非常重要的测试工作&#xff0c;以下是一些测试支付接口的建议&#xff1a; 测试支付流程&#xff1a; 测试支付流程的正确性&#xff0c;包括支付前、支付中和支付后的各个环节&#xff0c;确保支付流程的顺畅和正确。 测试支付金额&#xff1a; 测试支…

Python 中的 Unit testing 文件写入

在 Python 中进行单元测试时&#xff0c;有时候需要测试文件写入操作。为了模拟文件写入并进行单元测试&#xff0c;你可以使用 Python 的 unittest 模块&#xff0c;并结合 io.StringIO 或 tempfile 模块来模拟文件操作。 1、问题背景 在 Python 中&#xff0c;为 ConfigPars…

Docker下Open WebUI,Ollama的安装实践

提示一下Open WebUI与ollama的关系。后端的同学可以理解为Open WebUI等于是个Navicat&#xff0c;Ollama就是具体的数据库实例。 官方安装文档&#xff1a; &#x1f3e1; Home | Open WebUI Open WebUI官网文档翻译&#xff1a; 注意&#xff1a; 使用Docker安装Open WebU…

58. 【Android教程】音频录制:MediaRecord

在第 57 节我们使用 MediaPlayer 实现了一个 mp3 播放器&#xff0c;除了播放 Android 还提供了 MediaRecorder 用于录音。Android 设备基本都会有一个麦克风&#xff0c;通过 MediaRecorder 可以打开麦克风进行语音采集&#xff0c;这一节我们就来学习如何在 Android 系统上实…

深入解析C++的auto自动类型推导(二)

目录 使用auto的好处 新标准新增功能 使用auto的限制 上一篇详细讲解了使用auto关键字进行自动类型推导时的推导规则&#xff0c;这一篇重点讲解auto的使用以及C14、C17、C20等新标准对auto的功能完善&#xff0c;最后再介绍auto的使用限制。上一篇请从这里阅读&#xff1a;…

线程池核心原理浅析

前言 由于系统资源是有限的&#xff0c;为了降低资源消耗&#xff0c;提高系统的性能和稳定性&#xff0c;引入了线程池对线程进行统一的管理和监控&#xff0c;本文将详细讲解线程池的使用、原理。 为什么使用线程池 池化思想 线程池主要用到了池化思想&#xff0c;池化思想…

【计算机科学速成课】笔记一

文章目录 写在前面1.计算机的早期历史2.电子计算机3.布尔运算和逻辑门4.二进制5.算术逻辑单元-ALU6.寄存器和内存 写在前面 所有的一切源于这样一个网站——CS自学指南。 这是新手小白入门计算机科学必要了解的知识——【计算机科学速成课】[40集全/精校] - Crash Course Comp…

Dragonfly 拓扑的路由算法

Dragonfly 拓扑的路由算法 1. Dragonfly 上的路由 (1)最小路由(2)非最小路由 2. 评估3. 存在问题 (1)吞吐量限制(2)较高的中间延迟 references Dragonfly 拓扑的路由算法 John Kim, William J. Dally 等人在 2008 年的 ISCA 中提出技术驱动、高度可扩展的 Dragonfly 拓扑。而…

在做题中学习(53): 寻找旋转数组中的最小值

153. 寻找旋转排序数组中的最小值 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a;O(logn)->很可能就是二分查找 思路&#xff1a;再看看题目要求&#xff0c;可以画出旋转之后数组中元素的大小关系&#xff1a; 首先&#xff0c;数组是具有二段性的(适配二分查…

数据库(MySQL)—— 索引

数据库&#xff08;MySQL&#xff09;—— 索引 什么是索引创建索引使用 CREATE INDEX 语句使用 ALTER TABLE 语句在创建表时定义索引特殊类型索引注意事项 举个例子无索引的情况有索引的情况为什么索引快索引的结构 今天我们来看看MySQL中的索引&#xff1a; 什么是索引 MyS…

财政部、交通运输部:推动北斗导航等新技术与交通基础设施融合

财政部、交通运输部&#xff1a;推动北斗导航等新技术与交通基础设施深度融合 近日&#xff0c;为深入贯彻落实中共中央、国务院关于加快建设交通强国、数字中国等决策部署&#xff0c;推进公路水路交通基础设施数字转型、智能升级、融合创新&#xff0c;加快发展新质生产力&a…

VisualGDB:Linux动态库项目创建、编译及库的使用

此篇接上篇 《VisualGDB:为Linux项目添加系统依赖库》,在本篇中我们重点分享一下如何基于VisualGDB 在VS中创建Linux动态库项目,如何编译及使用创建的动态库。 一、VisualGDB创建Linux动态库项目 如下,我们创建一个Linux下的动态库项目MyMath 二、编译动态库 我们稍微…

哈夫曼编码python算法实现(图片版)

一、问题&#xff1a; 请使用哈夫曼编码方法对给定的字符串&#xff0c;进行编码&#xff0c;以满足发送的编码总长度最小&#xff0c;且方便译码。“AABBCCDDEEABCDDCDBAEEAAA” 二、过程&#xff1a; 三、结果&#xff1a;

手动实现简易版RPC(四)

手动实现简易版RPC(四) 往期内容 手动实现简易版RPC&#xff08;一&#xff09;&#xff1a;RPC简介及系统架构 手动实现简易版RPC&#xff08;二&#xff09;&#xff1a;简单RPC框架实现 手动实现简易版RPC(三)&#xff1a;mock数据生成 前言 接上几篇博客我们实现了最…

【6D位姿估计】FoundationPose 跑通demo 训练记录

前言 本文记录在FoundationPose中&#xff0c;跑通基于CAD模型为输入的demo&#xff0c;输出位姿信息&#xff0c;可视化结果。 然后分享NeRF物体重建部分的训练&#xff0c;以及RGBD图为输入的demo。 1、搭建环境 方案1&#xff1a;基于docker镜像&#xff08;推荐&#xf…

重置密码之后无法ssh登录

背景描述 我这边有个服务器S&#xff0c;我从ServerA可以ssh上去&#xff0c;但是我从堡垒机B无法ssh上去&#xff1b;一开始以为是密码问题&#xff0c;手动重置密码&#xff0c;但是依然无法登录进去&#xff1b;一直提示密码错误&#xff1b;改了好几次密码都不行 问题原因…

5.9号模拟前端面试10问

5.9号模拟前端面试10问 1.html语义化的理解 HTML语义化是指使用具有明确含义的HTML标签来描述内容&#xff0c;而不仅仅是使用<div>和<span>等通用容器标签。语义化的HTML代码更易于阅读和维护&#xff0c;同时也有助于搜索引擎优化&#xff08;SEO&#xff09;。…

达梦数据库限制用户登录IP测试

达梦数据库创建用户时可以限制登录ip和时间段。 创建测试测试用户 create user test1 identified by Test_1234 ALLOW_IP "192.168.100.101"; 限定该用户只能通过192.168.100.101地址登录数据库 连接测试 上图可见&#xff0c;192.168.100.101客户端可以连接上19…

wish、亚马逊怎么给店铺引流?怎么运用自养号测评提高流量的转化率?

作为全球知名的跨境电商平台&#xff0c;wish、亚马逊为卖家提供了一个拓展海外市场的机会。然而&#xff0c;在wish、亚马逊平台上建立和经营一家成功的店铺需要有效的引流策略。那么&#xff0c;Wish、亚马逊怎样才能给店铺引流呢&#xff1f; 一、Wish、亚马逊怎么给店铺引…