2017-07-18 44 views
0

简单和简单的版本:我正在尝试像应用Instagram一样实现一个后台堆栈。像instagram一样的Android背景栈

他们如何工作的导航

在Instagram的,他们使用的导航从bottombar。不知道代码是怎么样的。他们创造了某种4车道的后台。

因此,让我说我点击家(第1巷)。然后,我点击一个帖子 - >点击一个用户 - >点击另一个帖子 - >并最后点击一个#标签

然后我添加了4页到该巷道的后台。

然后我做了类似于另一个通道的东西(可以说账户页面)。

我知道在两个页面中都有4个页面。如果我在这一点上回击按钮。当我打开它们时,我只会遍历相同的页面。

但是,如果我反而回到首页(从底部的导航),并从那里点击后退按钮。我会从第1泳道,而不是巷道2

最大的问题

我怎样才能做到这一点车道像backstacking穿越回来?有没有一种简单的方式我没有想到?

我管理至今

我还没有成功地做了很多事情要做。我创建了一个测试项目,在这里我尝试了这种类型的导航。我设法做到目前为止是创建一个大规模的后台堆栈的所有我的底部导航页面

我对如何实现这种功能的猜测是将后台的某些部分移动到顶部并将其他移回。但这怎么可能?

+0

我在移动所以现在不能回答,但你可以在每个国家都有它自己的页面使用FragmentManager回堆栈并覆盖主活动的onBackPressed来调用活动的FragmentManager的popBackStack方法 –

回答

0

我设法解决了我遇到的问题。不要给我充分的信用。我有一个我看过的参考代码。请检查下面。

这可能不是一个可靠的解决方案。但它可以帮助你理解它的工作原理。因此,您可以创建适合您需求的解决方案。

希望这有助于:)

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

开始。我只想让大家知道我的应用程序的工作原理。所以你知道我为什么选择了实现这种导航的路线。我有一个活动,它保留对所使用的所有根片段的引用。该活动一次仅添加一个根片段。取决于用户点击的按钮。

活动创建新的根片段时。它会将其推送到处理它的管理类。

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

该活动还会将监听者传递给管理类。这个监听器会告诉活动什么时候关闭应用程序。并且当刷新当前活性片段

BackStackManager.java

这是管理类。它保持对所有不同的后台的参考。它还将任何片段事务责任委托给其FragmentManager类。

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类中。

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

这是一个简单的类,只是处理的根和标签的所有返回堆栈子条目内引用。而且处理这些子项的

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 
} 

监听

不多说了这件事。它是由活动实现

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