ViewSwtcher代表了视图切换组件,它本身继承了FrameLayout,因此可以将多个View层叠在一起,每次只显示一个组件。当程序控制从一个View切换到另一个View时,ViewSwitcher支持指定动画效果。

为了给ViewSwitcher添加多个组件,一般通过调用ViewSwitcher的setFactory(ViewSwitcher.ViewFactory)方法为之设置ViewFactory,并由该ViewFactory为之创建View即可。

下面通过实例来介绍ViewFactory的用法。

  实例:仿Android系统Launcher界面。

       Android4.2界面已经实现了分屏、左右滚动,本实例就是通过ViewSwitcher来实现Android 4.2的分屏、左右滚动效果。

为了实现该效果,程序主界面考虑使用ViewSwitcher来组合多个GridView,每个GridView代表一个屏幕的应用程序,GridView中每个单元格显示一个应用程序的图标好程序名。

该程序的主界面布局文件如下。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!-- 定义一个ViewSwitcher组件 -->
<ViewSwitcher android:id="@+id/viewSwitcher"
android:layout_width="fill_parent"
android:layout_height="fill_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="&lt;" />
<!-- 定义滚动下一屏的按钮 -->
<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="&gt;"/>
</RelativeLayout>

上面的布局文件中只是定义了一个ViewSwitcher组件和两个按钮,这两个按钮分别用于控制该ViewSwitcher显示上一屏、下一屏的程序列表。
        该实例的重点在于为该ViewSwitcher设置ViewFactory对象,并且当用户单击“<”和“>”两个按钮时控制ViewSwitcher显示“上一屏”和“下一屏” 的应用程序。

该程序会考虑使用扩展BaseAdapter的方式为GridView提供Adapter,而本实例的关键就是根据用户单击的按钮来动态来动态计算该BaseAdapter应该显示哪些程序列表。该程序的Activity代码如下。

package org.crazyit.helloworld;

import java.util.ArrayList;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import android.widget.ViewSwitcher.ViewFactory; public class ViewAnimatorTest 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
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_animator_test);
inflater=LayoutInflater.from(ViewAnimatorTest.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 ViewFactory(){
//实际上就是返回一个GridView组件
@Override
public View makeView() {
// TODO Auto-generated method stub
//加载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,R.anim.slide_in_left);
//为ViewSwitcher的组件隐藏过程设置动画
switcher.setOutAnimation(this,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() {
// TODO Auto-generated method stub
//如果已经到了最后一屏,且应用程序的数量不能整除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 Object getItem(int position) {
// TODO Auto-generated method stub
//根据screenNo计算第position个列表项的数据
return items.get(screenNo*NUMBER_PER_SCREEN+
position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
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(((DataItem)getItem(position)).drawable);
//获取R.layout.labelicon布局文件中的TextView组件,并为之设置文本
TextView textView=(TextView)view.findViewById(R.id.textview);
textView.setText(((DataItem)getItem(position)).dataName);
return
view;
} };
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.view_animator_test, menu);
return true;
} }

上面的程序中使用screenNo保存当前正在显示第几屏的程序列表。该程序的关键在于粗体字代码部分,该粗体字代码创建了BaseAdapter对象,这个BaseAdapter对象会根据sceenNo动态计算该Adapter总共包含多少个列表项(如getCout()方法所示)。会根据screenNo计算每个列表项的数据(getItem(int position)方法所示)。
   BaseAdapter的getView()只是简单加载了R.layout.labelicon布局文件,并使用当前列表项的图片数据填充R.layout.labelicon布局文件中的ImageView,使用当前列表项的文本数据填充R.layout.labelicon布局文件中的TextView。下面是R.layout.lablicon布局文件的代码。

<?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"
>
<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>

黑体字使用的R.layout.slidelistview布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:numColumns="4"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</GridView>

当用户单击“>”按钮时,程序的事件处理函数将会控制ViewSwitcher调用showNext()方法显示下一屏的程序列表——而且此时screenNo被加1,因而Adapter将会动态计算下一屏的程序列表,再将该Adapter传给ViewSwitcher接下来要显示的GridView。

为了实现ViewSwitcher切换View时的动画效果,程序的事件处理方法中调用了ViewSwitcher的setAnimation()、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>

其中R.anim.slide_out_left动画资源对应的代码如下。

<?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>

R.anim.slide_in_left动画资源对应的代码如下。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 设置从左边边拖进来的动画
android:duration指定动画持续时间 -->
<translate
android:fromXDelta="-50%p"
android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
</set>

R.anim.slide_out_right动画资源对应的代码如下:

<?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="50%p"
android:duration="@android:integer/config_mediumAnimTime"/>
</set>

运行上面的程序,可以看到下图所示的效果。
 

ViewSwitcher的功能与用法的更多相关文章

  1. Android ViewSwitcher 的功能与用法

    ViewSwitcher 代表了视图切换组件, 本身继承了FrameLayout ,可以将多个View叠在一起 ,每次只显示一个组件.当程序控制从一个View切换到另个View时,ViewSwitch ...

  2. Android 自学之画廊视图(Gallery)功能和用法

    Gallery与之前讲的Spinner有共同的父类:AbsSpinner,表明Gallery和Spinner都是一个列表框.他们之间的区别在于Spinner显示的是一个垂直的列表框,而Gallery显 ...

  3. 搜索框(SearchView)的功能与用法

    SearchView是搜索框组件,它可以让用户在文本框内输入汉字,并允许通过监听器监控用户输入,当用户用户输入完成后提交搜索按钮时,也通过监听器执行实际的搜索. 使用SearchView时可以使用如下 ...

  4. 数值选择器(NumberPicker)的功能与用法

    数值选择器用于让用户输入数值,用户既可以通过键盘输入数值,也可以通过拖动来选择数值.使用该组件常用如下三个方法. setMinValue(int minVal):设置该组件支持的最小值. setMax ...

  5. 日历视图(CalendarView)组件的功能和用法

    日历视图(CalendarView)可用于显示和选择日期,用户既可选择一个日期,也可通过触摸来滚动日历.如果希望监控该组件的日历改变,可调用CalendarView的setOnDateChangeLi ...

  6. 星级评分条(RatingBar)的功能和用法

    星级评分条与拖动条有相同的父类:AbsSeekBar,因此它们十分相似.实际上星级评分条与拖动条的用法.功能都十分接近:它们都是允许用户通过拖动条来改变进度.RatingBar与SeekBar最大区别 ...

  7. 拖动条(SeekBar)的功能和用法

    拖动条和进度条非常相似,只是进度条采用颜色填充来表明进度完成的程序,而拖动条则通过滑块的位置来标识数值——而且拖动条允许用户拖动滑块来改变值,因而拖动条通常用于对系统的某种数值进行调节,比如调节音量等 ...

  8. StackView的功能和用法

    StackView也是AdapterViewAnimator的子类,它也用于显示Adapter提供的系列View.SackView将会以“堆叠(Stack)”方式来显示多个列表项. 为了控制Stack ...

  9. MySQL常用存储引擎功能与用法详解

    本文实例讲述了MySQL常用存储引擎功能与用法. MySQL存储引擎主要有两大类: 1. 事务安全表:InnoDB.BDB. 2. 非事务安全表:MyISAM.MEMORY.MERGE.EXAMPLE ...

随机推荐

  1. Android NDK 下的宽字符编码转换及icu库的使用(转)

    原贴http://topic.csdn.net/u/20101022/16/1b2e0cec-b9d2-42ea-8d9c-4f1bb8320a54.html?r=70149216 ,看过并动手实现, ...

  2. Activity中 左滑动返回监听

    网易新闻中有个比较炫的效果,在QQ进入聊天界面也有这种效果,就是从界面左侧滑动到右侧时,界面退出,其实功能很容易实现: 1) Activity 去实现 implements OnTouchListen ...

  3. Ceph RBD CephFS 存储

    Ceph RBD  CephFS 存储 环境准备: (这里只做基础测试, ceph-manager , ceph-mon, ceph-osd 一共三台) 10.6.0.140 = ceph-manag ...

  4. 开始学习MFC

    <<对0基础MFC者的一点建议>>---------------------摘自某论坛lint2008的回复,不管对错,先看看.     因为上半年自己刚刚学了点MFC,算是对 ...

  5. Smali文件语法解析

    大家都应该知道APK文件其实就是一个MIME为ZIP的压缩包,我们修改ZIP后缀名方式可以看到内部的文件结构,例如修改后缀后用RAR打开鳄鱼小顽皮APK能看到的是(Google Play下载的完整版版 ...

  6. gitlab应用

    1.git config --global user.email "my@bimt.com" //注册本地环境 2.ssh-keygen -t rsa -C "my@bi ...

  7. iOS系统弃用方法更新方法

    -boundingRectWithSize:options:attributes:context:用法 - (CGSize)sizeWithFont:(UIFont *)font constraine ...

  8. 关于 CentOS 7 里面 普通用户 Ulimit max user processes 值的问题

    最近在对tomcat 的一个 项目进行 压测, 普通用户 启动 tomcat 的时候 压力上去以后就会报 java.lang.OutOfMemoryError 的错误, 这种错误 按道理来说都是 系统 ...

  9. 日志文件 统计 网站PV IP

    1. 安装rrdtool yum install rrdtool 2. 创建 rrdtool 数据库 rrdtool create /opt/local/rrdtool/jicki.rrd -s 30 ...

  10. Zipf’s Law

    Let f(w) be the frequency of a word w in free text. Suppose that all the words of a text are ranked ...