【android_温故知新】第 6 组 UI 组件:ViewAnimator 及其子类
来源:互联网 发布:中文域名转码查询 编辑:程序博客网 时间:2024/05/22 15:51
- 概述
- ViewAnimator 支持的常用 XML 属性
- ViewSwitcher 的功能与用法
- 实例仿 Android 系统 Launcher 界面
- 图像切换器 ImageSwitcher 的功能与用法
- 实例支持动画的图片浏览器
- 文本切换器 TextSwitcher 的功能与用法
- 实例TextSwitcher
- ViewFlipper 的功能与用法
- 实例自动播放的图片库
概述
ViewAnimator 是一个基类,它继承了 FrameLayout,因此它表现出 FrameLayout 的特征,可以将多个 View 组件“叠”在一起。ViewAnimator 额外增加的功能正如它的名字所暗示的,ViewAnimator 可以在 View 切换时表现出动画效果。
ViewAnimator 支持的常用 XML 属性
ViewSwitcher 的功能与用法
ViewSwitch 代表了试图切换组件,它本身继承了 FrameLayout,因此可以将多个 View 层叠在一起,每次只显示一个组件。当程序控制从一个 View 切换到另一个 View 时,ViewSwitcher 支持指定的动画效果。
为了给 ViewSwitcher 添加多个组件,一般通过调用 ViewSwitcher 的 setFactory (ViewSwitcher.ViewFactory)方法为之设置 ViewFactory,并由该 ViewFactory 为之创建 View 即可。
实例:仿 Android 系统 Launcher 界面
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 定义一个ViewSwitcher组件 --> <ViewSwitcher android:id="@+id/viewSwitcher" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- 定义滚动到上一屏的按钮 --> <Button android:id="@+id/button_prev" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:onClick="prev" android:text="<" /> <!-- 定义滚动到下一屏的按钮 --> <Button android:id="@+id/button_next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:onClick="next" android:text=">" /></RelativeLayout>
public class MainActivity extends Activity { // 定义一个常量,用于显示每屏显示的应用程序数 public static final int NUMBER_PER_SCREEN = 12; // 代表应用程序的内部类, public static class DataItem { // 应用程序名称 public String dataName; // 应用程序图标 public Drawable drawable; } // 保存系统所有应用程序的List集合 private ArrayList<DataItem> items = new ArrayList<DataItem>(); // 记录当前正在显示第几屏的程序 private int screenNo = -1; // 保存程序所占的总屏数 private int screenCount; ViewSwitcher switcher; // 创建LayoutInflater对象 LayoutInflater inflater; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); inflater = LayoutInflater.from(MainActivity.this); // 创建一个包含40个元素的List集合,用于模拟包含40个应用程序 for (int i = 0; i < 40; i++) { String label = "" + i; Drawable drawable = getResources().getDrawable( R.drawable.ic_launcher); DataItem item = new DataItem(); item.dataName = label; item.drawable = drawable; items.add(item); } // 计算应用程序所占的总屏数 // 如果应用程序的数量能整除NUMBER_PER_SCREEN,除法的结果就是总屏数 // 如果不能整除,总屏数应该是除法的结果再加1 screenCount = items.size() % NUMBER_PER_SCREEN == 0 ? items.size() / NUMBER_PER_SCREEN : items.size() / NUMBER_PER_SCREEN + 1; switcher = (ViewSwitcher) findViewById(R.id.viewSwitcher); switcher.setFactory(new ViewSwitcher.ViewFactory() { // 实际上就是返回一个GridView组件 @Override public View makeView() { // 加载R.layout.slidelistview组件,实际上就是一个GridView组件 return inflater.inflate(R.layout.slidelistview, null); } }); // 页面加载时先显示第一屏 next(null); } public void next(View v) { if (screenNo < screenCount - 1) { screenNo++; // 为ViewSwitcher的组件显示过程设置动画 switcher.setInAnimation(this, R.anim.slide_in_right); // 为ViewSwitcher的组件隐藏过程设置动画 switcher.setOutAnimation(this, R.anim.slide_out_left); // 控制下一屏将要显示的GridView对应的Adapter ((GridView) switcher.getNextView()).setAdapter(adapter); // 单击右边按钮,显示下一屏 // 学习手势检测后,也可通过手势检测实现显示下一屏 switcher.showNext(); // ① } } public void prev(View v) { if (screenNo > 0) { screenNo--; // 为ViewSwitcher的组件显示过程设置动画 switcher.setInAnimation(this, android.R.anim.slide_in_left); // 为ViewSwitcher的组件隐藏过程设置动画 switcher.setOutAnimation(this, android.R.anim.slide_out_right); // 控制下一屏将要显示的GridView对应的 Adapter ((GridView) switcher.getNextView()).setAdapter(adapter); // 单击左边按钮,显示上一屏,当然可以采用手势 // 学习手势检测后,也可通过手势检测实现显示上一屏 switcher.showPrevious(); //② } } // 该BaseAdapter负责为每屏显示的GridView提供列表项 private BaseAdapter adapter = new BaseAdapter() { @Override public int getCount() { // 如果已经到了最后一屏,且应用程序的数量不能整除NUMBER_PER_SCREEN if (screenNo == screenCount - 1 && items.size() % NUMBER_PER_SCREEN != 0) { // 最后一屏显示的程序数为应用程序的数量对NUMBER_PER_SCREEN求余 return items.size() % NUMBER_PER_SCREEN; } // 否则每屏显示的程序数量为NUMBER_PER_SCREEN return NUMBER_PER_SCREEN; } @Override public DataItem getItem(int position) { // 根据screenNo计算第position个列表项的数据 return items.get(screenNo * NUMBER_PER_SCREEN + position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position , View convertView, ViewGroup parent) { View view = convertView; if (convertView == null) { // 加载R.layout.labelicon布局文件 view = inflater.inflate(R.layout.labelicon, null); } // 获取R.layout.labelicon布局文件中的ImageView组件,并为之设置图标 ImageView imageView = (ImageView) view.findViewById(R.id.imageview); imageView.setImageDrawable(getItem(position).drawable); // 获取R.layout.labelicon布局文件中的TextView组件,并为之设置文本 TextView textView = (TextView) view.findViewById(R.id.textview); textView.setText(getItem(position).dataName); return view; } };}
上面的程序使用 screenNo 保存当前正在显示第几屏的程序列表。该程序的关键在于 BaseAdapter 对象。这个 BaseAdapter 会根据 screenNo 动态计算该 Adapter 总共包含多少个列表项(如 getCount() 方法所示)。会根据 screenNo 计算每个列表项的数据(如 getItem(int position) 方法所示 )。
BaseAdapter 的 getView() 只是简单加载了 R.layout.labelicon 布局文件,并使用当前列表项的图片数据填充 R.layout.labelicon 布局文件中的 ImageView,使用当前列表项的文本数据填充 R.layout.labelicon 布局文件中的 TextView。下面是 R.layout.labelicon 布局文件的代码。
<?xml version="1.0" encoding="utf-8"?><!-- 定义一个垂直的LinearLayout,该容器中放置一个ImageView和一个TextView --><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center"> <ImageView android:id="@+id/imageview" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" /> </LinearLayout>
当用户单击 “>” 按钮时,程序的事件处理函数将会控制 ViewSwitcher 调用 showNext() 方法显示下一屏的程序列表——而且此时 screenNo 被加 1,因而 Adapter 将会动态计算下一屏的程序列表,再将该 Adapter 传给 ViewSwitcher 接下来要显示的 GridView。
为了实现 ViewSwitcher 切换 View 时的动画效果。程序的事件处理方法中调用了 ViewSwitcher 的 setInAnimation()、setOutAnimation() 方法来设置动画效果。本程序不仅利用了 Android 系统提供的两个动画资源,还自行提供了动画资源。
其中 R.anim.slide_in_right 动画资源对应的代码如下。
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 设置从右边拖进来的动画 android:duration指定动画持续时间 --> <translate android:fromXDelta="100%p" android:toXDelta="0" android:duration="@android:integer/config_mediumAnimTime" /></set>
程序清单:slide_out_left.xml
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 设置从左边拖出去的动画 android:duration指定动画持续时间 --> <translate android:fromXDelta="0" android:toXDelta="-100%p" android:duration="@android:integer/config_mediumAnimTime" /></set>
图像切换器 ( ImageSwitcher ) 的功能与用法
ImageView 继承了 ViewSwitcher,因此它具有与 ViewSwitcher 相同的特征:可以在切换 View 组件时使用动画效果。ImageView 继承了 ViewSwitcher,并重写了 ViewSwitcher 的 showNext() 、showPrevious() 方法,因此 ImageSwitcher 使用起来更加简单。使用 ImageSwitcher 只要如下两步即可。
1. 为 ImageSwitcher 提供一个 ViewFactory,该 ViewFactory 生成的 View 组件必须是 ImageView。
2. 需要切换图片时,只要调用 ImageSwitcher 的 setImageDrawable(Drawable drawable)、setImageResource(int resid) 和 setImageURI(Uri uri) 方法更换图片即可。
实例:支持动画的图片浏览器
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal"> <!-- 定义一个GridView组件 --> <GridView android:id="@+id/grid01" android:layout_width="match_parent" android:layout_height="wrap_content" android:horizontalSpacing="2dp" android:verticalSpacing="2dp" android:numColumns="4" android:gravity="center"/> <!-- 定义一个ImageSwitcher组件 --> <ImageSwitcher android:id="@+id/switcher" android:layout_width="300dp" android:layout_height="300dp" android:layout_gravity="center_horizontal" android:inAnimation="@android:anim/fade_in" android:outAnimation="@android:anim/fade_out"/></LinearLayout>
上面布局文件中的代码定义了一个 ImageSwitcher,并通过 android:inAnimation 和 android:outAnimation 指定了图片切换时的动画效果。
接下来 Activity 代码需要为该 ImageSwitcher 设置 ViewFactory,并让该 ViewFactory 的 makeView() 方法返回 ImageView 。下面是该 Activity 的代码。
public class MainActivity extends Activity { int[] imageIds = new int[] { R.drawable.bomb5, R.drawable.bomb6, R.drawable.bomb7 , R.drawable.bomb8, R.drawable.bomb9, R.drawable.bomb10 , R.drawable.bomb11, R.drawable.bomb12, R.drawable.bomb13 , R.drawable.bomb14, R.drawable.bomb15, R.drawable.bomb16 }; ImageSwitcher switcher; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 创建一个List对象,List对象的元素是Map List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>(); for (int i = 0; i < imageIds.length; i++) { Map<String, Object> listItem = new HashMap<String, Object>(); listItem.put("image", imageIds[i]); listItems.add(listItem); } // 获取显示图片的ImageSwitcher switcher = (ImageSwitcher) findViewById(R.id.switcher); // 为ImageSwitcher设置图片切换的动画效果 switcher.setFactory(new ViewFactory() { @Override public View makeView() { // 创建ImageView对象 ImageView imageView = new ImageView(MainActivity.this); imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); imageView.setLayoutParams(new ImageSwitcher.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); // 返回ImageView对象 return imageView; } }); // 创建一个SimpleAdapter SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems // 使用/layout/cell.xml文件作为界面布局 , R.layout.cell, new String[]{"image"}, new int[]{R.id.image1}); GridView grid = (GridView) findViewById(R.id.grid01); // 为GridView设置Adapter grid.setAdapter(simpleAdapter); // 添加列表项被选中的监听器 grid.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { // 显示当前被选中的图片 switcher.setImageResource(imageIds[position]); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); // 添加列表项被单击的监听器 grid.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 显示被单击的图片 switcher.setImageResource(imageIds[position]); } }); }}
上面的代码中重写了 ViewFactory 的 makeView() 方法,该方法返回一个 ImageView 对象,这样该 ImageSwitcher 即可正常工作。该 Activity 还为 GridView 绑定了事件监听器,当用户单击 GridView 或选中 GridView 的指定单元格时,ImageSwitcher 切换为显示对应的图片。
文本切换器 (TextSwitcher) 的功能与用法
TextSwitcher 继承了 ViewSwitcher,因此它具有与 ViewSwitcher 相同的特征:可以在切换 View 组件时使用动画效果。与 ImageSwitcher 相似的是,使用 TextSwitcher 也需要设置一个 ViewFactory。与 ImageSwitcher 相似的是,使用 TextSwitcher 也需要设置一个 ViewFactory。与 ImageSwitcher 不同的是,TextSwitcher 所需的 ViewFactory 的 makeView() 方法必须返回一个 TextView 组件。
实例:TextSwitcher
<?xml version="1.0" encoding="utf-8" ?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <!-- 定义一个TextSwitcher,并指定了文本切换时的动画效果 --> <TextSwitcher android:id="@+id/textSwitcher" android:layout_width="match_parent" android:layout_height="wrap_content" android:inAnimation="@android:anim/slide_in_left" android:outAnimation="@android:anim/slide_out_right" android:onClick="next"/></LinearLayout>
public class MainActivity extends Activity { TextSwitcher textSwitcher; String[] strs = new String[] { "疯狂Java讲义", "轻量级Java EE企业应用实战", "疯狂Android讲义", "疯狂Ajax讲义" }; int curStr; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); textSwitcher = (TextSwitcher) findViewById(R.id.textSwitcher); textSwitcher.setFactory(new ViewSwitcher.ViewFactory() { public View makeView() { TextView tv = new TextView(MainActivity.this); tv.setTextSize(40); tv.setTextColor(Color.MAGENTA); return tv; } }); // 调用next方法显示下一个字符串 next(null); } // 事件处理函数,控制显示下一个字符串 public void next(View source) { textSwitcher.setText(strs[curStr++ % strs.length]); // ① }}
上面的代码重写了 ViewFactory 的 makeView() 方法,该方法返回了一个 TextView,这样即可让 TextSwitcher 正常工作。当程序要切换 TextSwitcher 显示文本时,调用 TextSwitcher 的 setText() 方法修改文本即可 —— 如上面的 ①号代码所示。
ViewFlipper 的功能与用法
ViewFlipper 组件继承了 ViewAnimator,它可调用 addView(View v) 添加多个组件,一旦向 ViewFlipper 中添加了多个组件之后,ViewFlipper 可使用动画控制多个组件之间的切换效果。
ViewFlipper 与前面介绍的 AdapterViewFlipper 有较大的相似性,他们可以控制组件切换的动画效果。它们的区别是:ViewFlipper 需要开发者通过 addView(View v) 添加多个 View,而 AdapterViewFlipper 则只要传入一个 Adapter,Adapter 将会负责提供多个 View。因此 ViewFlipper 可以指定与 AdapterViewFlipper 相同的 XML 属性。
实例:自动播放的图片库
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ViewFlipper android:id="@+id/details" android:layout_width="match_parent" android:layout_height="match_parent" android:flipInterval="1000"> <ImageView android:src="@drawable/java" android:layout_width="match_parent" android:layout_height="wrap_content"> </ImageView> <ImageView android:src="@drawable/android" android:layout_width="match_parent" android:layout_height="wrap_content"> </ImageView> <ImageView android:src="@drawable/javaee" android:layout_width="match_parent" android:layout_height="wrap_content"> </ImageView> </ViewFlipper> <Button android:text="<" android:onClick="prev" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerInParent="true" android:onClick="auto" android:text="自动播放"/> <Button android:text=">" android:onClick="next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true"/></RelativeLayout>
上面的布局文件定义了一个 ViewFlipper,并在该 ViewFlipper 中定义了三个 ImageView,这意味着该 ViewFlipper 包含了三个子组件。接下来再 Activity 代码中即可调用 ViewFlipper 的 showPrevious()、showNext() 等方法控制 ViewFlipper 显示上一个、下一个子组件。为了控制组件切换时的动画效果,还需要调用 ViewFlipper 的 setInAnimation()、setOutAnimation() 方法设置动画效果。
public class MainActivity extends Activity { private ViewFlipper viewFlipper; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); viewFlipper = (ViewFlipper) findViewById(R.id.details); } public void prev(View source) { viewFlipper.setInAnimation(this, R.anim.slide_in_right); viewFlipper.setOutAnimation(this, R.anim.slide_out_left); // 显示上一个组件 viewFlipper.showPrevious(); // 停止自动播放 viewFlipper.stopFlipping(); } public void next(View source) { viewFlipper.setInAnimation(this, android.R.anim.slide_in_left); viewFlipper.setOutAnimation(this, android.R.anim.slide_out_right); // 显示下一个组件 viewFlipper.showNext(); // 停止自动播放 viewFlipper.stopFlipping(); } public void auto(View source) { viewFlipper.setInAnimation(this, android.R.anim.slide_in_left); viewFlipper.setOutAnimation(this, android.R.anim.slide_out_right); // 开始自动播放 viewFlipper.startFlipping(); }}
- 【android_温故知新】第 6 组 UI 组件:ViewAnimator 及其子类
- 【android_温故知新】第 2 组 UI 组件:TextView及其子类
- 【android_温故知新】第 3 组 UI 组件:ImageView 及其子类
- 【android_温故知新】第 4 组 UI 组件:AdapterView 及其子类
- 【android_温故知新】第 5 组 UI 组件:ProgressBar 及其子类
- UI组件:ViewAnimator及其子类
- 【android_温故知新】第 1 组 UI 组件:布局管理器
- Android界面编程之七 第六组UI组件:ViewAnimator及其子类
- 安卓UI控件-ViewAnimator及其子类
- 第2组UI组件:TextView及其子类
- 第3组UI组件:ImageView及其子类
- 第4组UI组件:AdapterView及其子类
- 第5组UI组件:ProgressBar及其子类
- ViewAnimator及其子类
- Android ViewAnimator及其子类
- VIewAnimator及其子类
- UI组件:TextView及其子类
- UI组件:ImageView及其子类
- Java回炉之反射(一)
- Ubuntu15.04 安装卡在logo界面不动
- 自适应高度 — 按照文字 设置显示控件自适应 高度
- org.apache.struts2.json.JSONException:
- JAVA 路径问题
- 【android_温故知新】第 6 组 UI 组件:ViewAnimator 及其子类
- cin>>和cin.get()对EOF的处理机制有什么不同
- 喝酒不骑马的Android自学日记(2)
- Java笔记4:JDBC纯驱动方式连接Oracle
- 要修改的
- 运输层—TCP
- 读书笔记《高效程序员的45个习惯敏捷开发修炼之道》
- IOS吐槽狂人:Info.plist
- HTTP server git