ViewPager 的简单使用(二)

来源:互联网 发布:纽约 伦敦 知乎 编辑:程序博客网 时间:2024/05/17 23:58

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时,自动滚动对齐到最近的页面时。

0 0
原创粉丝点击