ViewPager 的简单使用(二)

ViewPager 的简单使用(一)中简单的使用了 ViewPager ,但是 ViewPager 常常和 Fragment 以前使用,这时需要的适配器为 FragmentPagerAdapter 或者 FragmentStatePagerAdapter

下面只是一个简单的示例,效果如下(AndroidStudio1.5):






ListPagerAdapter.java :

package com.crazy.viewpagertest;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;


public class ListPagerAdapter extends FragmentPagerAdapter {
    // 每个页面显示多少条目
    private static final int ITEMS_PER_PAGE = 2;

    private List<String> mItems;

    public ListPagerAdapter(FragmentManager fm, List<String> items) {
        super(fm);
        mItems = items;
    }

    /**
     *  这个位置首次需要一个 Fragment 时,该方法才会被调用
     */
    @Override
    public Fragment getItem(int position) {
        int start = position * ITEMS_PER_PAGE;
        return ArrayListFragment.newInstance(getPageList(position), start);
    }

    @Override
    public int getCount() {
        // 得到的分页总数
        int pages = mItems.size() / ITEMS_PER_PAGE;
        // 如果列表的大小不能整除页面的大小,就多添加一个页面来显示剩余的值
        int excess = mItems.size() % ITEMS_PER_PAGE;
        if (excess > 0) {
            pages++ ;
        }
        return pages;
    }

    /**
     *  这个方法会在 getItem() 之后针对新的 Fragment 被调用,而且在超出页数限制部分的
     *  Fragment 再加回来时,也会调用该方法;要确保这些元素会被更新到列表中
     */
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        ArrayListFragment fragment =
                (ArrayListFragment)super.instantiateItem(container, position);
        fragment.updateListItems(getPageList(position));
        return fragment;
    }

    /**
     *  当 notifyDataSetChanged() 被调用时,该方法也会被框架调用。必须决定如何为新的
     *  数据集更改每个 Fragment 。如果某个位置的 Fragment 不在需要,会返回 POSITION_NONE,
     *  这样适配器就可以将其删除
     */
    @Override
    public int getItemPosition(Object object) {
        ArrayListFragment fragment = (ArrayListFragment)object;
        int position = fragment.getBaseIndex() / ITEMS_PER_PAGE;
        if (position >= getCount()) {
            // 不在需要这个页面
            return POSITION_NONE;
        } else {
            // 刷新 Fragment 数据显示
            fragment.updateListItems(getPageList(position));
            return position;
        }
    }

    /**
     *  辅助方法,用于获取整个列表的某一部分,然后显示在给定的 Fragment 上。
     */
    private List<String> getPageList(int position) {
        int start = position * ITEMS_PER_PAGE;
        int end = Math.min(start + ITEMS_PER_PAGE, mItems.size());
        List<String> itemPage = mItems.subList(start, end);

        return itemPage;
    }

    /**
     *  内部自定义 Fragment,它会通过 ListView 中显示列表的一个片段,
     *  并提供外部方法来更新列表
     */
    public static class ArrayListFragment extends Fragment {

        private ArrayList<String> mItems;
        private ArrayAdapter<String> mAdapter;
        private int mBaseIndex;

        // 使用工厂模式创建 Fragment
        static ArrayListFragment newInstance(List<String> page,
                                             int baseIndex) {
            ArrayListFragment fragment = new ArrayListFragment();
            fragment.updateListItems(page);
            fragment.setBaseIndex(baseIndex);
            return fragment;
        }

        public ArrayListFragment(){
            super();
            mItems = new ArrayList<String>();
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 为列表条目创建一个新的适配器
            mAdapter = new ArrayAdapter<String>(getActivity(),
                    android.R.layout.simple_list_item_1, mItems);
        }

        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater,
                                 ViewGroup container,
                                 Bundle savedInstanceState) {
            // 构造并返回一个 ListView,为它关联适配器
            ListView listView = new ListView(getActivity());
            listView.setAdapter(mAdapter);

            return listView;
        }

        /**
         *  在全局列表中保存一个索引,记录页面开始的地方
         */
        public void setBaseIndex(int index) {
            mBaseIndex = index;
        }

        /**
         *  在全局列表中检索索引,可以找到页面开始的地方
         */
        public int getBaseIndex(){
            return mBaseIndex;
        }

        public void updateListItems(List<String> items) {
            mItems.clear();
            for (String piece : items) {
                mItems.add(piece);
            }

            if (mAdapter != null) {
                mAdapter.notifyDataSetChanged();
            }
        }
    }
}



        FragmentPagerAdapter 帮我们实现了 PagerAdapter 底层的很多功能。不必再实现 instantiateItem() ,destroyItem() 和 isViewFromObject() 方法,只需要重写 getItem() 来为每个页面位置提供相应的 Fragment 。这个例子让每个页面的条目显示数量为 2。在 getItem() 内创建 Fragment 时,会传入列表中的一部分数据,而这些数据是根据索引偏移和之前定义的常量来计算的。分页的数量由 getItem() 方法返回。

虽然 ViewPager 不会跟踪滚动出限定值之外的 Fragment ,但 FragmentManager 会继续跟踪。因此,当之前的 Fragment 回滚时,getItem() 不会被再次调用,因为 Fragment 已经存在了。但是正因为如此,如果一个数据集在这期间发生改变 Fragment 列表数据不会跟着更新。这就是重写 instantiateItem() 的原因。





MainActivity.java :

package com.crazy.viewpagertest;

import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import java.util.ArrayList;
import java.util.Date;

public class MainActivity extends AppCompatActivity {

    private ArrayList<String> mListItems;
    private ListPagerAdapter mAdapter;
    private int count = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 创建初始数据集
        mListItems = new ArrayList<>();
        mListItems.add("北京");
        mListItems.add("上海");
        mListItems.add("广州");
        mListItems.add("深圳");
        mListItems.add("武汉");
        mListItems.add("兰州");
        mListItems.add("成都");

        // 把数据关联到 ViewPager 上
        ViewPager pager = (ViewPager)findViewById(R.id.ViewPager);
        mAdapter = new ListPagerAdapter(getSupportFragmentManager(), mListItems);

        pager.setAdapter(mAdapter);
    }

    public void onAddClick(View v) {
        // 在列表的末尾添加新的条目
        mListItems.add("Crazy boy: " + countData() +"," + new Date());
        mAdapter.notifyDataSetChanged();

    }

    // 该方法是纯粹为了显示时方便观察效果,无其他意义
    private int countData(){
        return count++;
    }

    public void onRemoveClick(View v) {
        // 从列表中删除一个条目
        if (!mListItems.isEmpty()) {
            mListItems.remove(0);
        }
        mAdapter.notifyDataSetChanged();
    }
}



content_main.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.crazy.viewpagertest.MainActivity"
    tools:showIn="@layout/activity_main">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="添加 item"
        android:onClick="onAddClick" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="删除 item"
        android:onClick="onRemoveClick" />

    <android.support.v4.view.ViewPager
        android:id="@+id/ViewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </android.support.v4.view.ViewPager>

</LinearLayout>



        ViewPager 中还有几个其他的方法:

1. setPageMargin() 和 setPageMarginDrawable() 允许在页面之间设置一些额外的间隔,并且使用一个 Drawable (可选)来填充间隔的内容。

2. setCurrentItem() 允许以编程的方式设置要显示的页面,并提供一个选项来禁用页面的切换时的滚动画面。

3. OnPageChangeListener 用于将滚动和变更动作通知给应用程序。

----> onPageSelected() 会在显示一个新页面时被调用。

----> 当发生滚动操作时会连续调用 onPageSelected() 。

----> onPageScrollStateChanged() 在 ViewPager 处于以下状态时会被调用:闲置时,用户主动滚动 ViewPager 时,自动滚动对齐到最近的页面时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值