ViewSwitcher的功能与用法View

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

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

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

实例:仿 Android 系统 Launcher 界面

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

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

该程序的主界面布局如下:

程序清单:/ViewSwitcherDemo/res/layout/activity_main.xml

 

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.   
  6.     <!-- 定义一个 ViewSwitcher 组件 -->  
  7.     <ViewSwitcher   
  8.         android:id="@+id/viewSwitcher"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="fill_parent"  
  11.         ></ViewSwitcher>  
  12.       
  13.     <!-- 定义一个滚动到上一屏的按钮 -->  
  14.     <Button   
  15.         android:id="@+id/button_prev"  
  16.         android:layout_width="wrap_content"  
  17.         android:layout_height="wrap_content"  
  18.         android:layout_alignParentBottom="true"  
  19.         android:layout_alignParentLeft="true"  
  20.         android:onClick="prev"  
  21.         android:text="<"  
  22.         />  
  23.       
  24.     <!-- 定义一个滚动到下一屏的按钮 -->  
  25.     <Button   
  26.         android:id="@+id/button_next"  
  27.         android:layout_width="wrap_content"  
  28.         android:layout_height="wrap_content"  
  29.         android:layout_alignParentBottom="true"  
  30.         android:layout_alignParentRight="true"  
  31.         android:onClick="next"  
  32.         android:text=">"  
  33.         />  
  34.   
  35. </RelativeLayout>  

布局文件中定义了两个按钮,用于控制ViewSwitcher的上一屏和下一屏的程序列表。程序中采用按钮的方式控制翻页,也可以自己略加修改,改成滑动滚动屏幕。

 

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

程序清单:/ViewSwitcherDemo/src/com/example/viewswitcherdemo/MainActivity.Java

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 不积跬步无以至千里. 
  3.  * @author peter. 
  4.  * 
  5.  */  
  6. public class MainActivity extends Activity {  
  7.   
  8.     // 定义一个常量,用于显示每幕显示应用程序的数量  
  9.     private static final int NUMBER_PER_SCREEN = 12;  
  10.       
  11.     // 代表应用程序的内部类  
  12.     public static class DataItem {  
  13.         // 应用程序的名称  
  14.         public String dataName;  
  15.         // 应用程序的图标  
  16.         public Drawable drawable;  
  17.     }  
  18.       
  19.     // 保存系统所有应用程序的List集合  
  20.     private ArrayList<DataItem> items = new ArrayList<MainActivity.DataItem>();  
  21.       
  22.     // 记录当前正在显示第几屏的程序  
  23.     private int screenNo = -1;  
  24.       
  25.     // 保存程序所占的总屏数  
  26.     private int screenCount;  
  27.     ViewSwitcher switcher;  
  28.     // 创建 LayoutInflater 对象  
  29.     LayoutInflater inflater;  
  30.       
  31.     @Override  
  32.     protected void onCreate(Bundle savedInstanceState) {  
  33.         super.onCreate(savedInstanceState);  
  34.         setContentView(R.layout.activity_main);  
  35.         inflater = LayoutInflater.from(MainActivity.this);  
  36.         // 创建一个包含40个元素的List集合,用于模拟包含40个应用程序  
  37.         for (int i = 0; i < 40; i++) {  
  38.             String label = "" + i;  
  39.             Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher);  
  40.             DataItem item = new DataItem();  
  41.             item.dataName = label;  
  42.             item.drawable = drawable;  
  43.             items.add(item);  
  44.         }  
  45.         // 计算应用程序所占的总屏数  
  46.         // 如果应用程序的数量能整除NUMBER_PER_SCREEN,除法的结果就是总屏数  
  47.         // 如果不能整除,总屏数应该是除法的结果再加 1.  
  48.         screenCount = items.size() % NUMBER_PER_SCREEN == 0 ?   
  49.                 items.size() / NUMBER_PER_SCREEN :   
  50.                 items.size() / NUMBER_PER_SCREEN + 1;  
  51.         switcher = (ViewSwitcher) findViewById(R.id.viewSwitcher);  
  52.         switcher.setFactory(new ViewFactory() {  
  53.             // 实际上就是返回一个GridView组件  
  54.             @Override  
  55.             public View makeView() {  
  56.                 // 加载R.layout.slidelistview组件,实际上就是一个GridView组件  
  57.                 return inflater.inflate(R.layout.slidelistview, null);  
  58.             }  
  59.         });  
  60.         // 页面加载时先显示第一屏  
  61.         next(null);  
  62.     }  
  63.   
  64.     public void next(View v) {  
  65.         if (screenNo < screenCount - 1) {  
  66.             screenNo ++;  
  67.             // 为ViewSwitcher的组件显示过程设置动画  
  68.             switcher.setInAnimation(this, R.anim.slide_in_right);  
  69.             // 为ViewSwitcher的组件隐藏过程设置动画  
  70.             switcher.setOutAnimation(this, R.anim.slide_out_left);  
  71.             ((GridView)switcher.getNextView()).setAdapter(adapter);  
  72.             switcher.showNext();  
  73.         }  
  74.     }  
  75.       
  76.     public void prev(View v) {  
  77.         if (screenNo > 0) {  
  78.             screenNo--;  
  79.             // 为viewSwitcher的组件显示过程设置动画  
  80.             switcher.setInAnimation(this, android.R.anim.slide_in_left);  
  81.             // 为viewSwitcher的组件隐藏过程设置动画  
  82.             switcher.setOutAnimation(this, android.R.anim.slide_out_right);  
  83.             // 控制下一屏将要显示的GridView对应的Adapter  
  84.             ((GridView)switcher.getNextView()).setAdapter(adapter);  
  85.             switcher.showPrevious();  
  86.         }  
  87.     }  
  88.       
  89.     private BaseAdapter adapter = new BaseAdapter() {  
  90.           
  91.         @Override  
  92.         public int getCount() {  
  93.             // 如果已经到了最后一屏,且应用程序数量不能整除NUMBER_PER_SCREEN  
  94.             if (screenNo == screenCount - 1   
  95.                     && items.size() % NUMBER_PER_SCREEN != 0) {  
  96.                 // 最后一屏显示的程序数为应用程序的数量对NUMBER_PER_SCREEN求余  
  97.                 return items.size() % NUMBER_PER_SCREEN;  
  98.             }  
  99.             // 否则每屏显示的程序数量为NUMBER_PER_SCREEN  
  100.             return NUMBER_PER_SCREEN;  
  101.         }  
  102.           
  103.         @Override  
  104.         public DataItem getItem(int position) {  
  105.             // 根据screenNo计算第position个列表项的数据  
  106.             return items.get(screenNo * NUMBER_PER_SCREEN + position);  
  107.         }  
  108.           
  109.         @Override  
  110.         public long getItemId(int position) {  
  111.             return position;  
  112.         }  
  113.   
  114.         @Override  
  115.         public View getView(int position, View convertView, ViewGroup parent) {  
  116.             View view = convertView;  
  117.             if (convertView == null) {  
  118.                 // 加载R.layout.labelicon布局文件  
  119.                 view = inflater.inflate(R.layout.labelicon, null);  
  120.             }  
  121.             // 获取R.layout.labelicon布局文件中的ImageView组件,并为之设置图标  
  122.             ImageView imageView = (ImageView)view.findViewById(R.id.imageview);  
  123.             imageView.setImageDrawable(getItem(position).drawable);  
  124.             // 获取  
  125.             TextView textview = (TextView) view.findViewById(R.id.textview);  
  126.             textview.setText(getItem(position).dataName);  
  127.             return view;  
  128.         }  
  129.     };  
  130. }  

GridView布局文件代码:

 

程序清单:/ViewSwitcherDemo/res/layout/slidelistview.xml

 

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <GridView  
  3.   xmlns:android="http://schemas.android.com/apk/res/android"  
  4.   android:layout_width="match_parent"  
  5.   android:numColumns="4"  
  6.   android:layout_height="match_parent">  
  7. </GridView>  

GridView每一项的布局代码:

 

程序清单:/ViewSwitcherDemo/res/layout/labelicon.xml

 

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:gravity="center"  
  6.     android:orientation="vertical" >  
  7.       
  8.     <ImageView   
  9.         android:id="@+id/imageview"  
  10.         android:layout_width="wrap_content"  
  11.         android:layout_height="wrap_content"  
  12.         />  
  13.   
  14.     <TextView   
  15.         android:id="@+id/textview"  
  16.         android:layout_height="wrap_content"  
  17.         android:layout_width="fill_parent"  
  18.         android:gravity="center"  
  19.         />  
  20. </LinearLayout>  

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

 

为了实现ViewSwitcher切换View时的动画效果,程序事件处理方法中调用了Android系统提供的两个动画资源,还自行提供了动画资源。

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

程序清单:/ViewSwitcherDemo/res/anim/slide_in_right.xml

 

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <set xmlns:android="http://schemas.android.com/apk/res/android">  
  3.     <!-- 设置从右边拖出去的动画 -->  
  4.     <translate   
  5.         android:fromXDelta="100%"  
  6.         android:toXDelta="0"  
  7.         android:duration="@android:integer/config_mediumAnimTime"  
  8.         />  
  9. </set>  



 

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

程序清单:

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <set xmlns:android="http://schemas.android.com/apk/res/android">  
  3.     <!-- 设置从左边拖出去的动画 -->  
  4.     <translate   
  5.         android:fromXDelta="0"  
  6.         android:toXDelta="-100%p"  
  7.         android:duration="@android:integer/config_mediumAnimTime"  
  8.         />  
  9. </set>  

运行完程序显如下效果:

 


切换时可以看到动画效果

不懂之处可以加本人QQ:798628358

posted @ 2016-11-28 15:37  天涯海角路  阅读(195)  评论(0)    收藏  举报