实现ViewPager动态添加和删除页面

类似于天气预报中用户添加一个城市的天气,就新生成一个天气信息展示页面;删除一个城市的天气,则相应的天气信息展示页被删除的效果。(一步一步的)总结一下该效果是如何通过ViewPager来实现的。

本例实现的功能:用户可以通过点击添加按钮来添加一个新的页面;点击删除按钮,删除当前页面。

1.准备工作

    由于本例并不是主要讲ViewPager的用法,而且关于ViewPager的使用网上也有许多教程,所以ViewPager的部分不会太详细的解释(重点在添加、删除页面部分)

1.1 布局文件

ViewPager中页面的布局文件view.xml:

  1. <?xml version=“1.0” encoding=“utf-8”?>
  2. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
  3.     android:orientation=“vertical” android:layout_width=“match_parent”
  4.     android:layout_height=“match_parent”>
  5.     <TextView
  6.         android:id=“@+id/text_view”
  7.         android:gravity=“center”
  8.         android:layout_width=“match_parent”
  9.         android:layout_height=“wrap_content” />
  10. </LinearLayout>

MainActivity布局文件activity_main.xml:

  1. <?xml version=“1.0” encoding=“utf-8”?>
  2. <RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”
  3.     android:layout_width=“match_parent”
  4.     android:layout_height=“match_parent”>
  5.     <android.support.v4.view.ViewPager
  6.         android:id=“@+id/view_pager”
  7.         android:layout_width=“match_parent”
  8.         android:layout_height=“match_parent”></android.support.v4.view.ViewPager>
  9. </RelativeLayout>

 

1.2 适配器

新建一个类MyPagerAdapter继承自android.support.v4.view.PagerAdapter :

  1. package com.example.viewpagerdemo;
  2. import android.support.v4.view.PagerAdapter;
  3. import android.view.View;
  4. import android.view.ViewGroup;
  5. import java.util.List;
  6. public class MyPagerAdapter extends PagerAdapter{
  7.     private List<View> viewList;
  8.     public MyPagerAdapter(List<View> viewList){
  9.         this.viewList = viewList;
  10.     }
  11.     @Override
  12.     public void destroyItem(ViewGroup container, int position, Object object) {
  13.         container.removeView((View)object);
  14.     }
  15.     @Override
  16.     public int getCount() {
  17.         return viewList.size();
  18.     }
  19.     @Override
  20.     public Object instantiateItem(ViewGroup container, int position) {
  21.         container.addView(viewList.get(position));
  22.         return viewList.get(position);
  23.     }
  24.     @Override
  25.     public boolean isViewFromObject(View view, Object object) {
  26.         return view == object;
  27.     }
  28.     @Override
  29.     public int getItemPosition(Object object) {
  30.         return POSITION_NONE;
  31.     }
  32. }

注意,destroyItem方法和getItemPosition方法,这里先请大家留意一下,下面会解释这两个方法和平常使用的ViewPager有何不同…

2. 具体实现

  先上代码,再梳理实现步骤;
package com.example.viewpagerdemo;  
  1. import android.support.v4.view.ViewPager;
  2. import android.support.v7.app.AppCompatActivity;
  3. import android.os.Bundle;
  4. import android.view.LayoutInflater;
  5. import android.view.Menu;
  6. import android.view.MenuItem;
  7. import android.view.View;
  8. import android.widget.TextView;
  9. import java.util.ArrayList;
  10. import java.util.List;
  11. public class MainActivity extends AppCompatActivity {
  12.     private List<View> viewList = new ArrayList<>();//ViewPager数据源
  13.     private MyPagerAdapter myPagerAdapter;//适配器
  14.     private ViewPager viewPager;
  15.     private int count = 0//页面展示的数据,无实际作用
  16.     @Override
  17.     protected void onCreate(Bundle savedInstanceState) {
  18.         super.onCreate(savedInstanceState);
  19.         setContentView(R.layout.activity_main);
  20.         myPagerAdapter = new MyPagerAdapter(viewList);//创建适配器实例
  21.         viewPager = (ViewPager) findViewById(R.id.view_pager);
  22.         viewPager.setAdapter(myPagerAdapter);//为ViewPager设置适配器
  23.     }
  24.     /**
  25.      * 添加选项菜单
  26.      * 为了不影响ViewPager每个页面的一致性,这里使用选项菜单来操作添加和删除页面的点击事件
  27.      */
  28.     @Override
  29.     public boolean onCreateOptionsMenu(Menu menu) {
  30.         menu.add(1,1,1,“添加页面”);
  31.         menu.add(1,2,1,“删除页面”);
  32.         return super.onCreateOptionsMenu(menu);
  33.     }
  34.     /**
  35.      * 为选项菜单设置点击事件监听
  36.      */
  37.     @Override
  38.     public boolean onOptionsItemSelected(MenuItem item) {
  39.         switch (item.getItemId()){
  40.             case 1://添加页面的点击事件
  41.                 String text = “页面” + count;
  42.                 count++;
  43.                 addPage(text);
  44.                 break;
  45.             case 2://删除页面的点击事件
  46.                 delPage();
  47.                 break;
  48.         }
  49.         return super.onOptionsItemSelected(item);
  50.     }
  51.     /**
  52.      *该方法封装了添加页面的代码逻辑实现,参数text为要展示的数据
  53.      */
  54.     public void addPage(String text){
  55.         LayoutInflater inflater = LayoutInflater.from(this);//获取LayoutInflater的实例
  56.         View view = inflater.inflate(R.layout.view, null);//调用LayoutInflater实例的inflate()方法来加载页面的布局
  57.         TextView textView = (TextView) view.findViewById(R.id.text_view);//获取该View对象的TextView实例
  58.         textView.setText(text);//展示数据
  59.         viewList.add(view);//为数据源添加一项数据
  60.         myPagerAdapter.notifyDataSetChanged();//通知UI更新
  61.     }
  62.     /**
  63.      * 删除当前页面
  64.      */
  65.     public void delPage(){
  66.         int position = viewPager.getCurrentItem();//获取当前页面位置
  67.         viewList.remove(position);//删除一项数据源中的数据
  68.         myPagerAdapter.notifyDataSetChanged();//通知UI更新
  69.     }
  70. }

代码梳理:

1. 首先是一些初始化操作(ViewPager的使用): 定义一个空的数据源viewList; 创建数据适配器实例myPagerAdapter;为ViewPager设置数据适配器.(现在程序已经可以运行了,但是ViewPager里是空的,没有页面的)

2. 设置用户的添加和删除的点击事件;这里我用了一个选项菜单作为用户的点击按钮(不太了解选项菜单的看官,可以直接跳过onCreateOptionsMenu和onOptionsItemSelected这两个方法,只当他们是两个”按钮“即可)

3. 我们可以发现许多程序页面的布局结构都是相同的,不同的只是展示的内容信息(想象天气预报的天气信息展示页);所以我们最开始写了页面的布局view.xml,相当于一个模版,每一个不同的页面只是我们为其设置的展示数据不同。每当用户点击”添加页面时“,执行addPage()方法,该方法首先通过LayoutInflater的实例获取的View的实例(LayoutInflater的用法也请自行查询。其实findViewById也是返回的一个View的实例),然后拿到View实例里面的控件实例textView,设置展示信息,最后为ViewPager的数据源添加一项数据,添加了一个页面需要使用notifyDataSetChanged方法通知UI更新。(ViewPager中使notifyDataSetChanged方法起作用需要重写适配器中的getItemPosition方法)

4. 删除页面,当用户点击”删除页面“时,执行delPage()方法,该方法首先通过getCurrentItem方法获取当前页面滑动到了哪个位置,再通过移除数据源中的数据项,并且通知UI更新来实现页面的删除。

看到许多的ViewPager教程中适配器的destroyItem方法都是这样写的:

  1. <span style=“font-size:12px;”>public void destroyItem(ViewGroup container, int position, Object object) {
  2.         container.removeView(viewList.get(position));
  3.     }</span>

这样写在删除页面的时候会报下标越界异常,原因也很容易发现,当前页面的view项已经被我们从viewList中移除了,但是destroyItem方法中仍然在访问它。修改方法在上面的适配器的代码中已经给出了。

总结,添加和删除页面都是操作通过数据源的实现的。由于本例只是介绍ViewPager的动态添加、删除页面,所以有些问题,比如为什么ViewPager动态更新UI为什么要重写getItemPosition方法,并没有去深究,有兴趣的看官可以自行了解。另外发现本例一个bug,每次退出再进入的时候上次添加的页面没有了,这是由于我们并没有将数据源存储起来。

欢迎大家交流指正

源码下载:http://download.csdn.net/download/yunyis/10133529

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注