Android的碎片 - 多个选项卡/页面流,自定义backstack [英] Android Fragments - Multiple tabs/pageflows, custom backstack

查看:195
本文介绍了Android的碎片 - 多个选项卡/页面流,自定义backstack的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我运行到内存问题与碎片,我可以利用一些帮助,以采取适当的路径。因为应用程序需要保留几条路径,用户需要在应用程序中(并且用户可以来回跳转),我不能用一个简单的backstack。导航处理片段是这样的:

I'm running into memory issues with fragments and I could use some help as to the appropriate path to take. I cannot use a simple backstack because the application needs to retain several paths that the user takes within the application (and the user can jump back and forth). The navigation handles fragments in this way:

transaction.hide(currentFragment).show(newFragment).commit();

我觉得你会帮我的情况是有暂时破坏了片段的视图,然后重新当片段视图获取放回(而不是简单地隐藏从用户的视图的UI)。从阅读的API,它听起来并不像躲方法做到这一点。有谁知道,如果有一些内置的方法来对FragmentTransaction / FragmentManager /片断类,让我做到这一点?

What I think would help my situation is having the view of the fragment temporarily destroyed and then recreated when the fragment gets placed back in view (instead of simply hiding the UI from the user's view). From reading the API, it doesn't sound like the hide method does this. Does anyone know if there are some built-in methods to the FragmentTransaction/FragmentManager/Fragment class that will allow me to do this?

我考虑的是创造我自己的每个片段生命周期的另一种选择。我已经使用tabhost以及探讨,但它不会出现它要解决内存问题。如果您有其他的想法,我接受它。

Another option I'm considering is creating my own lifecycle for each fragment. I've explored using tabhost as well, but it doesn't appear it's going to solve the memory issues. If you have another idea, I'm open to it.

谢谢你们,我AP preciate这个你有所帮助。

Thanks guys, I appreciate your help with this.

推荐答案

我想出了一个解决方案,以达到更好的存储管理解决方案(适配器型)具有保存在同一时间多个用户的旅行(的东西独立标签那些重新presents backstacks)。我报废使用FragmentManager,因为它是不利于这种行为。我会在这里留下我的答案的情况下,任何人都运行到需要这样的想法使用具有FragmentStatePagerAdapter ViewPagers多backstacks的一个类似的问题 - 一个viewpager在他们的应用程序的每个选项卡(这仍然可以更清洁了,但你可以得到JIST)

I came up with a solution to achieve a better memory managed solution (adapter-based) for having multiple user journeys saved at the same time (independent tabs with something that represents backstacks). I scrapped using the FragmentManager as it was not conducive to this behavior. I will leave my answer here in case anyone else runs into a similar problem of needing this idea of multiple backstacks using ViewPagers with FragmentStatePagerAdapter - one viewpager for each tab in their app (this can still be cleaned up more but you can get the jist):

主要活动:

public class MultiTabbedActivity extends FragmentActivity implements NavigationFragment.OnNavigationSelectedListener
{

    private Page1Fragment mPage1;
    private Page2Fragment mPage2;


    private CustomFragment mCurrent;
    private String mNav;

    private List<CustomFragment> mPage1BackStack;
    private List<CustomFragment> mPage2BackStack;

    private CustomViewPager mPagerPage1;
    private CustomViewPager mPagerPage2;

    private boolean mUpdating = false;

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

        // initialize the backstacks
        mPage1BackStack = new ArrayList<CustomFragment>();
        mPage2BackStack = new ArrayList<CustomFragment>();

        mPage1 = new Page1Fragment();
        mPage2 = new Page2Fragment();

        mPage1BackStack.add(mPage1);
        mPage2BackStack.add(mPage2);

        mPagerPage1 = (CustomViewPager) findViewById(R.id.page1_fragment);
        mPagerPage2 = (CustomViewPager) findViewById(R.id.page2_fragment);

        mPagerPage1.setOffscreenPageLimit(3); //Customizable to determine how many 
        mPagerPage2.setOffscreenPageLimit(3); //fragments you want to hold in memory

        mPagerPage1.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager(), mPage1BackStack));
        mPagerPage2.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager(), mPage2BackStack));

        displayPager(mPagerPage1);
        mCurrent = mPage1;
        mNav = GlobalConstants.PAGE_PAGE1;

    }

    private void displayPager(ViewPager pager)
    {
        mPagerPage1.setVisibility(ViewPager.GONE);
        mPagerPage2.setVisibility(ViewPager.GONE);

        pager.setCurrentItem(pager.getAdapter().getCount() - 1);
        pager.getAdapter().notifyDataSetChanged();
        pager.setVisibility(ViewPager.VISIBLE);
    }

    @Override
    public void onNavSelected(String page)
    {
        if (page != null && page != "" && !mUpdating)
        {
            // Determine the Fragment selected
            if (page.equalsIgnoreCase(GlobalConstants.PAGE_PAGE1))
            {
                mNav = GlobalConstants.PAGE_PAGE1;
                displayPager(mPagerPage1);
                mCurrent = mPage1BackStack.get(mPage1BackStack.size() - 1);
            }
            else if (page.equalsIgnoreCase(GlobalConstants.PAGE_PAGE2))
            {
                mNav = GlobalConstants.PAGE_PAGE2;
                displayPager(mPagerPage2);
                mCurrent = mPage2BackStack.get(mPage2BackStack.size() - 1);
            }
        }
    }


    @Override
    public void onBackPressed()
    {
        PageFragment navFrag = null;
        // Update the Navigation Menu to indicate the currently visible
        // Fragment
        try
        {
            mUpdating = true;

            if (mPage1BackStack.size() > 1 && mNav.equalsIgnoreCase(GlobalConstants.PAGE_PAGE1))
            {
                mPagerPage1.setCurrentItem(mPage1BackStack.size() - 2);
                mPage1BackStack.remove(mPage1BackStack.size() - 1);
                navFrag = mPage1BackStack.get(mPage1BackStack.size() - 1);
                mPagerPage1.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager(), mPage1BackStack));
            }
            else if (mPage2BackStack.size() > 1 && mNav.equalsIgnoreCase(GlobalConstants.PAGE_PAGE2))
            {
                mPagerPage2.setCurrentItem(mPage2BackStack.size() - 2);
                mPage2BackStack.remove(mPage2BackStack.size() - 1);
                navFrag = mPage2BackStack.get(mPage2BackStack.size() - 1);
                mPagerPage2.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager(), mPage2BackStack));
            }
            else
            {
                super.onBackPressed();
            }

            if (navFrag != null)
                mCurrent = navFrag;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            mUpdating = false;
        }
    }

    public void updateFragment(PageFragment newFragment)
    {
        if (mNav.equalsIgnoreCase(GlobalConstants.PAGE_PAGE1))
        {
            mPage1BackStack.add(newFragment);
            displayPager(mPagerPage1);
        }
        else if (mNav.equalsIgnoreCase(GlobalConstants.PAGE_PAGE2))
        {
            mPage2BackStack.add(newFragment);
            displayPager(mPagerPage2);
        }
        mCurrent = newFragment;
    }
}

CustomViewPager:

CustomViewPager:

public class CustomViewPager extends ViewPager {

    private boolean enabled;

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.enabled = false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (this.enabled) {
            return super.onTouchEvent(event);
        }

        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (this.enabled) {
            return super.onInterceptTouchEvent(event);
        }

        return false;
    }

    public void setPagingEnabled(boolean enabled) {
        this.enabled = enabled;
    }
}

CustomAdapter:

CustomAdapter:

public class CustomFragmentAdapter extends FragmentStatePagerAdapter
{
    List<CustomFragment> mFragments;

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

    public List<PageFragment> getmFragments()
    {
        return mFragments;
    }

    public void setmFragments(List<CustomFragment> mFragments)
    {
        this.mFragments = mFragments;
    }

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

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

UI(包裹的线性布局中):

UI (wrapped inside a linear layout):

    <fragment
        android:id="@+id/navigation_fragment"
        android:name="your.package.here.NavigationFragment"
        android:layout_width="70dp"
        android:layout_height="match_parent" />

    <FrameLayout
        android:id="@+id/page_fragment"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="2" >

        <your.package.here.CustomViewPager
            android:id="@+id/page1_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone" />
        <your.package.here.CustomViewPager
            android:id="@+id/page2_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone" />
    </FrameLayout>

这篇关于Android的碎片 - 多个选项卡/页面流,自定义backstack的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆