2017-07-18 47 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