使用动态页面创建 ViewPager(prev/next 页面查看器,循环,例如 Book 应用程序)

Create ViewPager with dynamic pages (prev/next page viewer, circular, e.g. Book app)

如何创建包含动态创建页面的 ViewPager?页数没有限制。从一开始,用户就可以向左或向右导航(滑动)以获取上一页或下一页。所以没有 'page 0' (在列表中)。

一个应用程序可以是一本书。它可以是一个天气(或数据)应用程序,显示前几天的数据或未来几天的天气预报。 在书柜中,重新启动应用程序后可能会显示在第 35 页。当用户导航到上一页时,会立即显示第 34 页。所以 - 使用片段列表不起作用。

更新:我从问题中删除了源代码,因为我已经创建了一个完整的解决方案。它在一个 give Github 项目中。

使ViewPager循环的解决方案是基于portfoliobuider's post and tobi_b's post的建议。

您可以在 this Github project 中找到一个很好的例子。每个页面(或片段)都是完全动态生成的。支持向后或向前导航(如此循环)。当然它有AndroidX作为基础。

Activity是:

public class MainActivity extends FragmentActivity {
    static MainActivity mainActivity;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mainActivity = this;
        if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(android.R.id.content,
                            new PagerFragment()).commit();
        }
    }
}

PagerFragment 是:

public class PagerFragment extends Fragment {
    private static final int SET_ITEM_DELAY = 300;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View result=inflater.inflate(R.layout.pager, container, false);
        final ViewPager pager= result.findViewById(R.id.pager);
        pager.addOnPageChangeListener( new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }
            @Override
            public void onPageSelected( final int position) {
                pager.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        handleSetCurrentItem(position);
                    }
                }, SET_ITEM_DELAY);
            }
            @Override
            public void onPageScrollStateChanged(int state) {
            }
            private void handleSetCurrentItem(final int position) {
                final int lastPosition = pager.getAdapter().getCount() - 1;
                if (position == 0) {
                    pager.setCurrentItem(lastPosition - 1, false);
                } else if (position == lastPosition) {
                    pager.setCurrentItem(1, false);
                }
            }
        });
        pager.setAdapter(buildAdapter());
        pager.setCurrentItem(1); // not 0 !!!
        return(result);
    }
    private PagerAdapter buildAdapter() {
        return(new SampleAdapter(getActivity(), getChildFragmentManager()));
    }
}

SamplerAdapter 是:

public class SampleAdapter extends FragmentStatePagerAdapter {
    private int numberOfPages = 10;
    Context ctxt = null;
    public SampleAdapter(Context ctxt, FragmentManager mgr) {
        super(mgr);
        this.ctxt = ctxt;
    }
    @Override
    public int getCount() {
        return (numberOfPages + 2);
    }

    @Override
    public Fragment getItem(final int position) {
        if (position == 0) {
            return (EditorFragment.newInstance(numberOfPages - 1));
        } else if (position == numberOfPages + 1) {
            return (EditorFragment.newInstance(0));
        } else {
            return (EditorFragment.newInstance(position - 1));
        }
    }
    @Override
    public String getPageTitle(int position) {
        return (EditorFragment.getTitle(ctxt, position));
    }
}

布局文件是:

<?xml version="1.0" encoding="utf-8"?>
<androidx.viewpager.widget.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<!--    <androidx.viewpager.widget.PagerTitleStrip could be placed here -->
</androidx.viewpager.widget.ViewPager>

动态片段为:

public class EditorFragment extends Fragment {
    private static final String KEY_POSITION = "position";
    static EditorFragment newInstance(int position) {
        EditorFragment frag = new EditorFragment();
        Bundle args = new Bundle();
        args.putInt(KEY_POSITION, position);
        frag.setArguments(args);
        return (frag);
    }
    static String getTitle(Context ctxt, int position) {
        return (String.format(ctxt.getString(R.string.hint), position + 1));
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View result = inflater.inflate(R.layout.editor, container, false);
        EditText editor = (EditText) result.findViewById(R.id.editor);
        int position = getArguments().getInt(KEY_POSITION, -1);
        editor.setHint(getTitle(getActivity(), position));
        return (result);
    }
}

它有一个非常简单的布局文件:

<EditText xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/editor"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:inputType="textMultiLine"
    android:gravity="left|top" />

效果很好!