如何在ViewPager中替换片段

时间:2014-02-26 03:40:37

标签: android listview android-viewpager fragment

我已经坚持这个问题几天了,这让我发疯了。看起来我正在尝试做的事情将是一个非常常见的用例,但我不能为我的生活弄明白。

所以,问题是:我想替换ViewPager中的片段并维持Backstack的正常操作

我的ViewPager包含两个显示ListViews的片段。当我在ViewPager的第一个位置时,我希望能够深入查看ListView并能够使用后退按钮退出:

艺术家 - >专辑 - >歌曲

艺术家< - 专辑< - 歌曲

这些元素中的每一个都是作为一个包含它自己的ListView的单独片段实现的。

当用户向右滑动时,我想使用ViewPager在单独的片段中显示当前播放列表。

所以典型的流程可能是:

艺术家 - >专辑 - > Swipe Right to Playlist fragment - >播放列表 - > Swipe Left to return - >相册

经过多次实验,我已经设法提出了这个替代艺术家/专辑片段的解决方案,但是不可能使用后退按钮退出片段:

   public interface ItemSelectedListener {
    void onItemSelected(Item item);
}

public class ListPagerAdapter extends FragmentPagerAdapter {
    private static final String TAG = RMPDApplication.APP_PREFIX + "ListPagerAdapter";
    SearchView searchView;
    FragmentManager fragmentManager;
    AbstractListFragment firstFragment;
    PlaylistFragment playlistFragment;


    public ListPagerAdapter(SearchView searchView, FragmentManager fm) {
        super(fm);
        this.searchView = searchView;
        fragmentManager = fm;
    }

    class FragmentChanger implements ItemSelectedListener {
        @Override
        public void onItemSelected(Item item) {
            AbstractListFragment newFragment;
            if (item instanceof Artist) {
                newFragment = new ArtistAlbumsListFragment(searchView, (Artist) item, new FragmentChanger());
            } else {
                newFragment = new SongListFragment(searchView, (Album) item);
            }

            FragmentTransaction ft = fragmentManager.beginTransaction();
            ft.remove(firstFragment);
            ft.commit();
            firstFragment = newFragment;
            notifyDataSetChanged();
        }
    }


    @Override
    public Fragment getItem(int position) {
        if (position == 1) {
            Log.i(TAG, "Returning playlistFragment");
            if (playlistFragment == null) {
                playlistFragment = new PlaylistFragment(searchView);
            }
            return playlistFragment;

        } else {
            Log.i(TAG, "Returning firstFragment");
            if(firstFragment == null) {
                firstFragment = new ArtistListFragment(new FragmentChanger(), searchView);
            }
            return firstFragment;
        }
    }

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public int getItemPosition(Object object) {
        Log.i(TAG, "getItemPosition: " + object.getClass().getSimpleName());
        if(object instanceof PlaylistFragment) {
            return POSITION_UNCHANGED;
        }
        return POSITION_NONE;
    }
}

我将FragmentChanger传递给每个片段,然后在onItemClick()中将其称为唯一方法:

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    final Artist artist = (Artist) adapter.getItem(position);
    itemSelectedListener.onItemSelected(artist);
}

这几乎可以正常工作,单击一个项目会将片段替换为所需的片段,但我无法返回上一个片段。如果有人能帮我解决这个问题,我将非常感激。

修改

好的,我已经与J.Romero的建议合作了。最后,我在一个BrowserFragment中实现了所有前进/后退功能,并覆盖onBackPressed()来处理后退按钮。我会添加相关代码以防其他人帮助。

这是我的ViewPager:

public class ListPagerAdapter extends FragmentPagerAdapter {
    SearchView searchView;
    BrowserFragment browserFragment;
    PlaylistFragment playlistFragment;

    public ListPagerAdapter(SearchView searchView, FragmentManager fm) {
        super(fm);
        this.searchView = searchView;
    }

    public boolean browserFragmentCanGoBack() {
        return browserFragment.canGoBack();
    }

    public void browserFragmentBack() {
        browserFragment.goBack();
    }

    @Override
    public Fragment getItem(int position) {
        if (position == 1) {
            if (playlistFragment == null) {
                playlistFragment = new PlaylistFragment(searchView);
            }
            return playlistFragment;

        } else {
            if (browserFragment == null) {
                browserFragment = new BrowserFragment(searchView);
            }
            return browserFragment;
        }
    }

    @Override
    public int getCount() {
        return 2;
    }
}

然后在托管活动中,我重写onBackPressed(),如下所示:

@Override
public void onBackPressed() {
    if (viewPager.getCurrentItem() == 0) {
        if (pagerAdapter.browserFragmentCanGoBack()) {
            pagerAdapter.browserFragmentBack();
        } else {
            super.onBackPressed();
        }
    } else {
        viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
    }
}

它有效!

1 个答案:

答案 0 :(得分:2)

您可以通过覆盖活动中的onBackPressed方法并跟踪用户当前所处的级别以及显示或返回以及适当的活动来管理“backstack”。

@Override
public void onBackPressed(){
    if (mLevel > 1) {
        // in your case probably change the adapter item for the page
        mViewPagerAdapter.notifyDataSetChanged()
    }
    ...
}
相关问题