简析ListView与ViewPager

简析ListView与ViewPager

今天在这里和大家分享一下我对ListView和ViewPager的了解。简单索引如下:
- ListView
定义
一些常用属性
Adapter 常用的实现类
ArrayAdapter 的使用
SimpleAdapter 的使用
- ViewPager
定义
主要方法
OnPageChangeListener
三种适配器的简单说明:
PagerAdapter
FragmentPagerAdapter
FragmentStatePagerAdapter

ListView

说到ListView大家也许不会陌生,这个UI组件在我们手机里面的许多应用软件中都有使用,它常用来以垂直列表的形式显示所有列表项。

ListView的定义

需要在对应的界面布局文件中定义,如:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@android:color/darker_gray"
        android:dividerHeight="2px"
        android:headerDividersEnabled="false">
    ListView>

LinearLayout>

值得注意的是,在布局文件中定义ListView时,需要为其定义id。此处的代码为:“android:id=”@+id/list””,该id在后面的操作中会经常使用,请不要忘记

ListView的一些常用属性

android:divider    //设置List列表项的分隔条(既可以用颜色分隔也可以用Drawable分隔)
android:dividerHeight     //设置分隔条的高度
android:entries       //指定一个数组资源,Android将根据该数组资源来生成ListView
android:footerDividersEnabled       //如果设置为false,则不在footer View之前绘制分隔条
android:headerDividersEnabled       //如果设置为false,则不在header View之后绘制分隔条

注意:如果此处使用了”android:entries”,则需要在values文件下创建对应的资源文件

事实上,通过以上方法已经可以创建ListView了。只不过这样创建出来的ListView十分简单,能够定制的内容很少,甚至连每个列表项的字号大小、颜色等属性都不能改变。

如果想对ListView的外观、行为进行定制,就需要把ListView作为AdapterView使用,进而通过Adapter控制每个列表项的外观和行为。

Adapter常用的实现类有:

  • ArrayAdapter:简单、易用的Adapter,通常用于将数组或List集合的多个值包装成多个列表项

  • SimpleAdapter:功能强大、并不“简单”的Adapter,可用于将List集合的多个对象包装成多个列表项

  • SimpleCursorAdapter:与SimpleAdapter基本相同,只是用于包装Cursor提供的数据

  • BaseAdapter:通常用于被扩展。扩展BaseAdapter可以对各列表项进行最大限度的定制。

本文仅介绍ArrayAdapter与SimpleAdapter

下面,我们通过代码来实际操作一下如何使用ArrayAdapter:

        private ListView listView;
        private List stringList;
        private ArrayAdapterarrayAdapter;
        ……
        ……
        /**
         * 初始化ListView
         */
        listView = (ListView) findViewById(R.id.list);

        /**
         * 准备数据源
         */
        stringList = new ArrayList<>();
        stringList.add("新的朋友");
        stringList.add("群聊");
        stringList.add("标签");
        stringList.add("公众号");

        /**
         * 建立ArrayAdapter适配器对象
         */
        arrayAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,stringList);

        /**
         * ListView加载对应的适配器
         */
        listView.setAdapter(arrayAdapter);

在创建ArrayAdapter时,必须指定如下三个参数:

pic1

  • Context:这个参数代表了访问整个Android应用的接口,几乎创建所有组件都需要传入Context对象

pic2

  • LayoutRes:一个资源ID,该ID代表了一个TextView,该TextView组件将作为ArrayAdapter的列表项组件。

pic3

  • List < String >:该数组或List将负责为多个列表项提供数据

效果如下:(真机版)

简析ListView与ViewPager_第1张图片

如果程序的窗口仅仅需要一个列表,那么可以直接让Activity继承ListActivity来快速实现。ListActivity无须布局文件——相当于它的布局文件只有一个ListView,因此只要为ListActivity设置Adapter即可

下面,我们通过代码来实际操作一下如何使用SimpleAdapter:

    private ListView listView;
    private List stringList;
    private SimpleAdapter simpleAdapter;
    private List> dataList;

    ……
    ……

    /**
     * 初始化ListView
     */
    listView = (ListView) findViewById(R.id.list);

    /**
     * 准备数据源
     */
    stringList = new ArrayList<>();
    stringList.add("新的朋友");
    stringList.add("群聊");
    stringList.add("标签");
    stringList.add("公众号");
    dataList = new ArrayList>();

    /**
     * 创建SimpleAdapter适配器对象
     */
    simpleAdapter = new SimpleAdapter(this,getData(),R.layout.simple_item,new String[]{"image","text"},new int[]{R.id.image,R.id.text});

    /**
     * ListView加载对应的适配器
     */
    listView.setAdapter(simpleAdapter);
    ……
    ……

    public List> getData()
    {
        for (int i=0;i<4;i++)
        {
            Mapmap = new HashMap<>();
            map.put("image",R.mipmap.ic_launcher_round);
            map.put("text",list.get(i));
            dataList.add(map);
        }
        return dataList;
    }

在创建SimpleAdapter时,必须指定如下五个参数:

pic5

  • Context:此处不再重复说明

pic6

  • List< ? extends Map < String,?>>data:此处应该传入一个List

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="horizontal"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <ImageView
        android:id="@+id/image"     //此处需要定义id
        android:layout_margin="15dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher_round"/>

    <TextView
        android:id="@+id/text"        //此处需要定义id
        android:layout_width="wrap_content"
        android:layout_height="30dp"
        android:textSize="20sp"
        android:textColor="#000000"
        android:text="Demo"
        android:layout_margin="25dp"/>

LinearLayout>

pic8

  • String[ ]:该参数是一个String[ ]类型的参数,该参数决定提取Map < String,?>对象中哪些key(键)对应的value(值)来生成列表项。例如此处决定提取key为:”image”,”text”对应的value

pic9

  • int [ ]:该参数是一个int[ ]类型的参数,该参数决定填充指定界面布局的特定组件。例如此处决定填充指定组件的id为:R.id.image,R.id.text

效果如下:(测试版)

简析ListView与ViewPager_第2张图片

ViewPager

现如今,ViewPager用于实现页面间的切换,我们在各大应用程序中均可看到它的影子。ViewPager使用前也需要在对应的布局文件中定义。

ViewPager的定义

需要在对应的界面布局文件中定义,如:

.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center">

    .support.v4.view.ViewPager>

同样地,这里也需要为ViewPager定义id

ViewPager中的主要方法介绍

  • setAdapter(PagerAdapter adapter)

    该方法为ViewPager设置适配器,ViewPager有三种适配器,它们分别有不同的特性

  • setCurrentItem(int item)

    该方法设置显示item位置的界面

  • setOffscreenPageLimit(int limit)

    该方法用来设置当前显示页面左右两边各缓存的页面数

  • addOnPageChangeListener(OnPageChangeListener listener)

    该方法为ViewPager添加页面切换时的监听

  • setOnScrollChangeListener(OnScrollChangeListener l)

    该方法为ViewPager增加滚动状态监听,但该方法需要minSdkVersion为23

OnPageChangeListener中的三个方法简单介绍

  • onPageScrollStateChanged(int state)

    该方法在手指操作屏幕的时候发生变化。有三个值:0(END),1(PRESS) ,2(UP) 。当用手指滑动翻页时,手指按下去的时候会触发这个方法,state值为1,手指抬起时,如果发生了滑动(即使很小),这个值会变为2,然后最后变为0 。总共执行这个方法三次。一种特殊情况是手指按下去以后一点滑动也没有发生,这个时候只会调用这个方法两次,state值分别是1,0 。当setCurrentItem翻页时,会执行这个方法两次,state值分别为2 ,0

  • onPageScrolled(int position, float positionOffset, int positionOffsetPixels)

    • position:当用手指滑动时,如果手指按在页面上不动,position和当前页面index是一致的;如果手指向左拖动(相应页面向右翻动),这时候position大部分时间和当前页面是一致的,只有翻页成功的情况下最后一次调用才会变为目标页面;如果手指向右拖动(相应页面向左翻动),这时候position大部分时间和目标页面是一致的,只有翻页不成功的情况下最后一次调用才会变为原页面。当直接设置setCurrentItem翻页时,如果是相邻的情况(比如现在是第二个页面,跳到第一或者第三个页面),如果页面向右翻动,大部分时间是和当前页面是一致的,只有最后才变成目标页面;如果向左翻动,position和目标页面是一致的。这和用手指拖动页面翻动是基本一致的。如果不是相邻的情况,比如我从第一个页面跳到第三个页面,position先是0,然后逐步变成1,然后逐步变成2;我从第三个页面跳到第一个页面,position先是1,然后逐步变成0,并没有出现为2的情况。
    • positionOffset:当前页面滑动比例,如果页面向右翻动,这个值不断变大,最后在趋近1的情况后突变为0。如果页面向左翻动,这个值不断变小,最后变为0
    • positionOffsetPixels:当前页面滑动像素,变化情况和positionOffset一致

三个方法的执行顺序:用手指拖动翻页时,最先执行一遍 onPageScrollStateChanged(1),然后不断执行 onPageScrolled,放手指的时候,直接立即执行一次 onPageScrollStateChanged(2),然后立即执行一次 onPageSelected,然后再不断执行 onPageScrollStateChanged,最后执行一次 onPageScrollStateChanged(0)

下面,我们来说一下ViewPager的几种适配器的使用

先放一张图来大概了解一下其中的关系:

简析ListView与ViewPager_第3张图片

PagerAdapter

首先,让我们来看一下代码:

    private ListviewList;
    private ViewPager pager;

@Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pager = (ViewPager) findViewById(R.id.pager);

        /**
         * 通过inflate方法将对应布局文件转化为View对象
         * 使用View对象来作为ViewPager的数据源
         */
        View view1 = View.inflate(this,R.layout.view_1,null);
        View view2 = View.inflate(this,R.layout.view_2,null);
        View view3 = View.inflate(this,R.layout.view_3,null);
        View view4 = View.inflate(this,R.layout.view_4,null);

        viewList.add(view1);
        viewList.add(view2);
        viewList.add(view3);
        viewList.add(view4);

        /**
        * 创建PagerAdapter的适配器对象
        */
       MyPagerAdapter adapter = new MyPagerAdapter(viewList);

       /**
         * ViewPager加载对应的适配器
         */
          pager.setAdapter(adapter);
    }

这里我就不给出view_1、2、3、4布局的代码啦,大家稍微脑补一下吧

此外,这里我是新建一个子类 MyPagerAdapter来创建对象的,下面给出这个子类的代码:

public class MyPagerAdapter extends PagerAdapter
{

    private ListviewList;

    public MyPagerAdapter(List viewList)
    {
        this.viewList = viewList;
    }

    @Override
    public int getCount()
    {
        return viewList.size();//返回的是页面的数量
    }

    @Override
    public boolean isViewFromObject(View view, Object object)
    {
        return view == object;//判断View是否来着于object对象
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position)
    {
        container.addView(viewList.get(position));
        return viewList.get(position);//实例化一个页面
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object)
    {
        container.removeView(viewList.get(position));
        //销毁一个网面。一般情况下,PagerAdapter只会三个三个地加载View对象,创建和销毁都是自动调用的
    }
FragmentPagerAdapter

这种方法最好用于有限个静态fragment页面的管理。尽管不可见的视图有时会被销毁,但用户所有访问过的fragment都会被保存在内存中。因此fragment实例会保存大量的各种状态,这就造成了很大的内存开销。

下面我们来看一下代码:

    private ViewPager pager;
    private List fragmentList;
@Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pager = (ViewPager) findViewById(R.id.pager);

        /**
         * 通过Fragment对象作为ViewPager的数据源
         */
        fragmentList = new ArrayList<>();
        fragmentList.add(new Fragment1());
        fragmentList.add(new Fragment2());
        fragmentList.add(new Fragment3());
        fragmentList.add(new Fragment4());

        /**
         * 创建FragmentAdapter的适配器对象
         */
        MyFragmentPagerAdapter adapter1 = new MyFragmentPagerAdapter(getSupportFragmentManager(),fragmentList);

        /**
         * ViewPager加载对应的适配器
         */
        pager.setAdapter(adapter1);
    }

这里也不给出 Fragment1、2、3、4这四个类的代码啦,其实里面因为只是演示所以也没有放什么东西进去

下面给出 MyFragmentPagerAdapter的代码:

public class MyFragmentPagerAdapter extends FragmentPagerAdapter
{

    private ListfragmentList;

    public MyFragmentPagerAdapter(FragmentManager fm,List fragmentList)
    {
        super(fm);
        this.fragmentList = fragmentList;
    }

    @Override
    public Fragment getItem(int position)
    {
        return fragmentList.get(position);//返回position位置关联的Fragment
    }

    @Override
    public int getCount()
    {
        return fragmentList.size();//返回所有fragment的数量
    }
}
FragmentStatePagerAdapter

在上面的FragmentPagerAdapter中我们了解到,这个适配器最好用于有限个静态fragment页面的管理。但如果要处理大量的页面切换时怎么办?这时建议使用FragmentStatePagerAdapter

该适配器适合处理大量的页面切换,其能能够保存和恢复Fragment状态的适配器,超出缓存的Fragment会调用onDestory()方法,彻底对销毁Fragment进行销毁

由于 FragmentPagerAdapter和我们上面所说的 FragmentPagerAdapter十分相似,故此处便不举例了

你可能感兴趣的:(简析ListView与ViewPager)