首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >像instagram这样的Android后台

像instagram这样的Android后台
EN

Stack Overflow用户
提问于 2017-07-18 20:15:53
回答 1查看 1.5K关注 0票数 0

简单而简短的版本:我正试图实现一个像Instagram应用程序一样的后台程序。

他们的导航是如何工作的

在instagram中,他们使用来自底部栏的导航。而不知道代码是什么样子。他们创造了某种4车道的背靠背。

所以,让我们说,我点击家(第一车道)。然后,我设法点击一个帖子->,点击一个用户->,点击另一个帖子->,最后点击一个哈希标签

然后,我在那条车道的后排增加了4页。

然后,我做一些类似于另一条车道的事情(比如帐户页面)。

我知道两条车道都有4页。如果我现在按下按钮的话。当我打开它们的时候,我会回到原来的页面。

但是,如果我单击“返回到家”(从底部导航)并从那里单击“回退”按钮的话。我会从1号车道返回,而不是2号车道。

大问题

我怎么才能像背靠背那样实现这条车道呢?有没有一种简单的方法让我不去想?

到目前为止我所做的一切,

我做得不多。我创建了一个测试项目,在那里我尝试了这种类型的导航。到目前为止,我所做的就是为我所有的底部导航页面创建一个庞大的背靠背。

我对如何实现这种功能的猜测是,将背靠背的某些部分移到顶部,将另一部分移回。但这怎么可能?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-07-22 11:38:50

我设法解决了我正在处理的问题。不要给我充分的信任。我看过一个参考代码。请检查下面。

这也许不是一个固溶体。但是它可以帮助你理解它是如何工作的逻辑。因此,您可以创建适合您需要的自己的解决方案。

希望这会有所帮助:)

背景我的应用程序是如何工作的

首先。我只想让大家知道我的应用程序是如何工作的。所以你知道我为什么选择实现这个导航的路线。我有一个活动,它保存对它正在使用的所有根片段的引用。该活动一次只添加一个根片段。取决于用户单击的按钮。

当活动创建一个新的根片段时。它将把它推送给处理它的管理类。

该活动本身覆盖onBackPressed(),并调用已组成的backstacks onBackpressed()函数。

该活动还将将侦听器传递给管理类。这个侦听器将告诉活动什么时候关闭应用程序。以及刷新当前活动片段的时间。

BackStackManager.java

这是管理类。它保存了对所有不同背景堆栈的引用。它还将任何片段事务任务委托给它的FragmentManager类。

代码语言:javascript
运行
复制
public class BackStackManager {

    //region Members
    /** Reference to the made up backstack */
    private final LinkedList<BackStack> mBackStacks;
    /** Reference to listener */
    private final BackStackHelperListener mListener;
    /** Reference to internal fragment manager */
    private final BackStackFragmentManager mFragmentManager;
    //endregion


    //region Constructors
    public BackStackManager(@NonNull final BackStackHelperListener listener,
                            @NonNull final FragmentManager fragmentManager) {
        mBackStacks = new LinkedList<>();
        mListener = listener;
        mFragmentManager = new BackStackFragmentManager(fragmentManager);
    }
    //endregion


    //region Methods


    /** When adding a new root fragment
     * IMPORTANT: Activity his holding the reference to the root. */
    public void addRootFragment(@NonNull final Fragment fragment,
                                final int layoutId) {
        if (!isAdded(fragment)) {
            addRoot(fragment, layoutId);
        }
        else if (isAdded(fragment) && isCurrent(fragment)) {
            refreshCurrentRoot();
        }
        else {
            switchRoot(fragment);
            mFragmentManager.switchFragment(fragment);
        }
    }

    /** When activity is calling onBackPressed */
    public void onBackPressed() {
        final BackStack current = mBackStacks.peekLast();
        final String uuid = current.pop();

        if (uuid == null) {
            removeRoot(current);
        }
        else {
            mFragmentManager.popBackStack(uuid);
        }
    }

    /** Adding child fragment */
    public void addChildFragment(@NonNull final Fragment fragment,
                                 final int layoutId) {

        final String uuid = UUID.randomUUID().toString();
        final BackStack backStack = mBackStacks.peekLast();

        backStack.push(uuid);

        mFragmentManager.addChildFragment(fragment, layoutId, uuid);
    }

    /** Remove root */
    private void removeRoot(@NonNull final BackStack backStack) {
        mBackStacks.remove(backStack);


        //After removing. Call close app listener if the backstack is empty
        if (mBackStacks.isEmpty()) {
            mListener.closeApp();
        }
        //Change root since the old one is out
        else {
            BackStack newRoot = mBackStacks.peekLast();
            mFragmentManager.switchFragment(newRoot.mRootFragment);
        }
    }

    /** Adding root fragment */
    private void addRoot(@NonNull final Fragment fragment, final int layoutId) {

        mFragmentManager.addFragment(fragment, layoutId);

        //Create a new backstack and add it to the list
        final BackStack backStack = new BackStack(fragment);
        mBackStacks.offerLast(backStack);
    }

    /** Switch root internally in the made up backstack */
    private void switchRoot(@NonNull final Fragment fragment) {

        for (int i = 0; i < mBackStacks.size(); i++) {
            BackStack backStack = mBackStacks.get(i);
            if (backStack.mRootFragment == fragment) {
                mBackStacks.remove(i);
                mBackStacks.offerLast(backStack);
                break;
            }
        }
    }

    /** Let listener know to call refresh */
    private void refreshCurrentRoot() {
        mListener.refresh();
    }

    /** Convenience method */
    private boolean isAdded(@NonNull final Fragment fragment) {
        for (BackStack backStack : mBackStacks) {
            if (backStack.mRootFragment == fragment) {
                return true;
            }
        }
        return false;
    }

    /** Convenience method */
    private boolean isCurrent(@NonNull final Fragment fragment) {
        final BackStack backStack = mBackStacks.peekLast();
        return backStack.mRootFragment == fragment;
    }

    //endregion
}

BackStackFragmentManager.java

这个类处理所有片段事务。例如添加/删除/隐藏/显示。这个类生活在BackStackManager类中。

代码语言:javascript
运行
复制
public class BackStackFragmentManager {

    //region Members
    /** Reference to fragment manager */
    private final FragmentManager mFragmentManager;
    /** Last added fragment */
    private Fragment mLastAdded;
    //endregion


    //region Constructors
    public BackStackFragmentManager(@NonNull final FragmentManager fragmentManager) {
        mFragmentManager = fragmentManager;
    }
    //endregion


    //region Methods

    /** Switch root fragment */
    public void switchFragment(@NonNull final Fragment fragment) {
        final FragmentTransaction transaction = mFragmentManager.beginTransaction();

        transaction.show(fragment);
        transaction.hide(mLastAdded);

        transaction.commit();

        mLastAdded = fragment;
    }

    /** Adding child fragment to a root */
    public void addChildFragment(@NonNull final Fragment fragment,
                                 final int layoutId,
                                 @NonNull final String tag) {


        final FragmentTransaction transaction = mFragmentManager.beginTransaction();
        transaction.add(layoutId, fragment, tag);
        transaction.commit();
    }


    /** Add a root fragment */
    public void addFragment(@NonNull Fragment fragment, int layoutId) {
        final FragmentTransaction transaction = mFragmentManager.beginTransaction();

        //since we hide/show. This should only happen initially
        if (!fragment.isAdded()) {
            transaction.add(layoutId, fragment, fragment.getClass().getName());
        }
        else {
            transaction.show(fragment);
        }

        if (mLastAdded != null) {
            transaction.hide(mLastAdded);
        }

        transaction.commit();

        mLastAdded = fragment;
    }

    /** Pop back stack
     * Function is removing childs that is not used!
     */
    public void popBackStack(@NonNull final String tag) {
        final Fragment fragment = mFragmentManager.findFragmentByTag(tag);
        final FragmentTransaction transaction = mFragmentManager.beginTransaction();
        transaction.remove(fragment);
        transaction.commit();
    }

    //endregion
}

BackStack.java

这是一个简单的类,它只处理对根的内部引用和对所有逆堆栈子条目的标记。以及处理这些子条目

代码语言:javascript
运行
复制
public class BackStack {

    //region Members
    public final Fragment mRootFragment;
    final LinkedList<String> mStackItems;
    //endregion


    //region Constructors
    public BackStack(@NonNull final Fragment rootFragment) {
        mRootFragment = rootFragment;
        mStackItems = new LinkedList<>();
    }

    //endregion


    //region Methods
    public String pop() {
        if (isEmpty()) return null;
        return mStackItems.pop();
    }

    public void push(@NonNull final String id) {
        mStackItems.push(id);
    }


    public boolean isEmpty() {
        return mStackItems.isEmpty();
    }
    //endregion
}

侦听器

关于这件事没什么好说的。它由活动实现。

代码语言:javascript
运行
复制
public interface BackStackHelperListener {
    /** Let the listener know that the app should close. The backstack is depleted */
    void closeApp();

    /** Let the listener know that the user clicked on an already main root. So app can do
     * a secondary action if needed
     */
    void refresh();

}

参考资料

https://blog.f22labs.com/instagram-like-bottom-tab-fragment-transaction-android-389976fb8759

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45176274

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档