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

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent" >

  <!-- 定义一个 ViewSwitcher 组件 -->
  <ViewSwitcher 
    android:id="@+id/viewSwitcher"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    ></ViewSwitcher>
  
  <!-- 定义一个滚动到上一屏的按钮 -->
  <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>

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

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

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

/**
 * 不积跬步无以至千里.
 * @author peter.
 *
 */
public class MainActivity extends Activity {

  // 定义一个常量,用于显示每幕显示应用程序的数量
  private static final int NUMBER_PER_SCREEN = 12;
  
  // 代表应用程序的内部类
  public static class DataItem {
    // 应用程序的名称
    public String dataName;
    // 应用程序的图标
    public Drawable drawable;
  }
  
  // 保存系统所有应用程序的List集合
  private ArrayList<DataItem> items = new ArrayList<MainActivity.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.activity_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 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)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();
    }
  }
  
  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);
      // 获取
      TextView textview = (TextView) view.findViewById(R.id.textview);
      textview.setText(getItem(position).dataName);
      return view;
    }
  };
}

GridView布局文件代码:

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

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

GridView每一项的布局代码:

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

<?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"
  android:gravity="center"
  android:orientation="vertical" >
  
  <ImageView 
    android:id="@+id/imageview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />

  <TextView 
    android:id="@+id/textview"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:gravity="center"
    />
</LinearLayout>

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

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

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

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

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
  <!-- 设置从右边拖出去的动画 -->
  <translate 
    android:fromXDelta="100%"
    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">
  <!-- 设置从左边拖出去的动画 -->
  <translate 
    android:fromXDelta="0"
    android:toXDelta="-100%p"
    android:duration="@android:integer/config_mediumAnimTime"
    />
</set>

运行完程序显如下效果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值