简体   繁体   English

使用ViewPager的主从视图

[英]Master-Detail View using ViewPager

I'd like to change the master-detail implementation of my Android phone app. 我想更改我的Android手机应用程序的主从实现。 Currently, users can select items from a ListView , opening a new activity. 当前,用户可以从ListView选择项目,以打开新活动。 To select a different activity, the user must return to the list. 要选择其他活动,用户必须返回列表。 Instead of this pogo-sticking, I'd like the user to swipe left and right to page through the documents using a ViewPager . 我希望用户可以使用ViewPager左右滑动来翻阅文档,而不是这种ViewPager There can be many documents, so I'd like to load at most 3 pages at a time - the current page, the previous, and the next. 可能有很多文档,所以我想一次最多加载3页-当前页面,上一页和下一页。 Paging back and forth should then add and remove pages left and right. 然后来回分页应左右添加和删除页面。 I've created an adapter implementing FragmentStatePagerAdapter that handles static content (eg TextViews) nicely. 我创建了一个实现FragmentStatePagerAdapter的适配器,该适配器可以很好地处理静态内容(例如TextViews)。 Also deleting pages seems to work OK (not included here). 另外,删除页面似乎可以正常进行(此处不包括)。 But when I add eg an EditText content is copied over from one page to the next when paging. 但是,当我添加例如EditText内容时,分页时会将内容从一页复制到下一页。

Below is the code for the adapter and for the activity. 以下是适配器和活动的代码。 There are two questions I have: 我有两个问题:

  1. What is wrong with my adapter that causes the undesired copying of EditText from one fragment to the next? 我的适配器有什么问题,会导致EditText从一个片段到另一个片段的意外复制?
  2. This is my first shot at this, and it's probably far from an optimal implementation. 这是我的第一枪,可能离最佳实现还很远。 But I find this to be such a common use case that I almost feel like there would be a ready made framework for it. 但是我发现这是一个非常常见的用例,以至于我几乎觉得将有一个现成的框架。 Could this be achieved much easier? 可以容易得多吗?

Pager Adapter: 寻呼机适配器:

public class DetailPagerAdapter extends FragmentStatePagerAdapter {

    private final List<Fragment> mFragments;
    private final static String TAG = "DetailPagerAdapter";

    public DetailPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        mFragments = fragments;
    }

    @Override
    public int getCount() {
        return mFragments.size();
    }

    @Override
    public int getItemPosition(Object object) {
        return PagerAdapter.POSITION_NONE;
    }

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

    public void addItem(Fragment fragment) {
        mFragments.add(fragment);
        notifyDataSetChanged();
    }

    public void removeItem(int position) {
        mFragments.remove(position);
        notifyDataSetChanged();
    }

    public void insertItem(int position, Fragment fragment) {
        mFragments.add(position, fragment);
        notifyDataSetChanged();
    }
}

PagingActivity Base Class: PagingActivity基类:

public abstract class PagingActivity 
        extends AppCompatActivity
        implements ViewPager.OnPageChangeListener {

    protected ViewPager mViewPager;
    DetailPagerAdapter mViewPagerAdapter;
    protected ArrayList<String> mAllItemIds;
    private String mPreviousItemId;
    private String mCurrentItemId;
    private String mNextItemId;

    private boolean mMuteOnPageSelected = false;


    protected abstract Fragment getNewPageFragment(String id);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        List<Fragment> initialFragments = new ArrayList<>();

        int currentItemIndex = mAllItemIds.indexOf(mCurrentItemId);
        int pageSelection = 1;
        // Add previous view.
        if (currentItemIndex > 0) {
            mPreviousItemId = mAllItemIds.get(mAllItemIds.indexOf(mCurrentItemId) - 1);
            initialFragments.add(getNewPageFragment(mPreviousItemId));
        } else {
            pageSelection = 0;
            mPreviousItemId = null;
        }
        // Add current view.
        initialFragments.add(getNewPageFragment(mCurrentItemId));
        // Add next view.
        if (currentItemIndex < mAllItemIds.size() - 1) {
            mNextItemId = mAllItemIds.get(mAllItemIds.indexOf(mCurrentItemId) + 1);
            initialFragments.add(getNewPageFragment(mNextItemId));
        } else {
            mNextItemId = null;
        }

        mViewPagerAdapter = new DetailPagerAdapter(getSupportFragmentManager(), initialFragments);
        mViewPager.setAdapter(mViewPagerAdapter);
        mViewPager.setCurrentItem(pageSelection);

        mViewPager.addOnPageChangeListener(this);
    }

    @Override
    public void onPageSelected(int position) {

        if (!mMuteOnPageSelected) {
            mCurrentItemId = ((PagingFragment) (mViewPagerAdapter.getItem(mViewPager.getCurrentItem()))).getItemId();
            int currentItemIndex = mAllItemIds.indexOf(mCurrentItemId);

            // Navigated to the right.
            if (position == mViewPagerAdapter.getCount() - 1) {
                // Add next if not already pointing at the last available item.
                if (currentItemIndex < mAllItemIds.size() - 1) {
                    mNextItemId = mAllItemIds.get(mAllItemIds.indexOf(mCurrentItemId) + 1);
                    mViewPagerAdapter.addItem(getNewPageFragment(mNextItemId));
                } else {
                    mNextItemId = null;
                }
                // If it succeeds remove first item.
                int itemCount = mViewPagerAdapter.getCount();
                if ((itemCount > 3) || ((itemCount == 3) && (currentItemIndex == mAllItemIds.size() - 1))) {
                    mMuteOnPageSelected = true;
                    mViewPagerAdapter.removeItem(0);
                    mViewPager.setCurrentItem(1);
                    mMuteOnPageSelected = false;
                }
            }

            // Navigated to the left.
            else if (position == 0) {
                // Add item on the left if not already pointing at the first available item.
                if (currentItemIndex > 0) {
                    mPreviousItemId = mAllItemIds.get(mAllItemIds.indexOf(mCurrentItemId) - 1);
                    mViewPagerAdapter.insertItem(0, getNewPageFragment(mPreviousItemId));
                } else {
                    mPreviousItemId = null;
                }
                // Check if last item needs to be removed and selection updated.
                int itemCount = mViewPagerAdapter.getCount();
                if (itemCount == 3) {
                    if (currentItemIndex == 0) {
                        // Points to the first of two items.
                        // -> do not change selection
                        // -> remove rightmost item.
                        mViewPagerAdapter.removeItem(itemCount - 1);
                    } else if (currentItemIndex == mAllItemIds.size() - 2) {
                        // Will point to the middle of 3 items.
                        // -> nothing to remove
                        // -> select middle page.
                        mMuteOnPageSelected = true;
                        mViewPager.setCurrentItem(1);
                        mMuteOnPageSelected = false;
                    }
                } else if (itemCount > 3) {
                    // Pager contains 4 items, first item selected.
                    // -> remove rightmost item
                    // -> select middle page.
                    mMuteOnPageSelected = true;
                    mViewPagerAdapter.removeItem(itemCount - 1);
                    mViewPager.setCurrentItem(1);
                    mMuteOnPageSelected = false;
                }
            }

            mViewPagerAdapter.notifyDataSetChanged();
        }
    }
}

The second question was the key: Yes, at least the current state can be achieved much easier by letting the adapter handle the full array of items. 第二个问题是关键:是的,通过让适配器处理全部项目,至少可以更轻松地实现当前状态。 FragmentStatePagerAdapter only loads as many fragments at a time as needed, so it can handle all the manual work I had done in the activity. FragmentStatePagerAdapter仅加载所需数量的片段,因此它可以处理我在活动中完成的所有手动工作。

Pager Adapter 寻呼机适配器

public class MyPagerAdapter extends FragmentStatePagerAdapter {

    private List<String> mAllItemIds;

    public MyPagerAdapter(Context context, FragmentManager fm) {
        super(fm);
        mAllItemIds = ...
    }

    @Override
    public int getCount() {
        return mAllItemIds.size();
    }

    @Override
    public int getItemPosition(Object object) {
        return PagerAdapter.POSITION_NONE;
    }

    @Override
    public Fragment getItem(int position) {
        return MyFragment.newInstance(mAllItemIds.get(position));
    }

    public void removeItem(int position) {

        // add needed code here to remove item also from source
        // ...

        mAllItemIds.remove(position);
        notifyDataSetChanged();
    }
}

Activity 活动

public abstract class PagingActivity extends AppCompatActivity {

    protected ViewPager mViewPager;
    MyPagerAdapter mViewPagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mViewPager = (ViewPager)findViewById(R.id.viewPager);
        mViewPagerAdapter = new MyPagerAdapter(this, getSupportFragmentManager());
        mViewPager.setAdapter(mViewPagerAdapter);
    }

    private void deleteItem() {
        mViewPagerAdapter.removeItem(mViewPager.getCurrentItem());
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM