• ViewSwitcher的功能与用法


         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>

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

       

         

  • 相关阅读:
    enum 与 enum class
    git error: unable to rewind rpc post data
    ip地址转换
    大端字节序&小端字节序(网络字节序&主机字节序)
    c++虚析构函数
    引用
    单例模式
    c++ 类静态成员、非静态成员初始化
    算法导论进度帖startedby20131029
    Linux驱动程序接口
  • 原文地址:https://www.cnblogs.com/wolipengbo/p/3387774.html
Copyright © 2020-2023  润新知