Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions conductor/src/main/java/com/bluelinelabs/conductor/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,65 @@ public final Router getChildRouter(@NonNull ViewGroup container, @Nullable Strin
return childRouter;
}

public interface TabControllerFactory {
RouterTransaction getRootControllerForTab();
}

private ControllerHostedRouter previousTabRouter = null;

@NonNull
public final Router switchChildRouterForTab(
@NonNull ViewGroup container,
@Nullable String tag,
TabControllerFactory controllerFactory) {

@IdRes final int containerId = container.getId();

ControllerHostedRouter currentRouter = null;
for (ControllerHostedRouter router : childRouters) {
if (router.getHostId() == containerId && TextUtils.equals(tag, router.getTag())) {
currentRouter = router;
break;
}
}

if (currentRouter == null) {
currentRouter = new ControllerHostedRouter(container.getId(), tag);
currentRouter.setHost(this, container);
childRouters.add(currentRouter);

if (isPerformingExitTransition) {
currentRouter.setDetachFrozen(true);
}

} else {
currentRouter.prepareForHostTabAttach();

if (!currentRouter.hasHost()) {
currentRouter.setHost(this, container);
}
}

if (!currentRouter.hasRootController()) {
currentRouter.setRootForTab(controllerFactory.getRootControllerForTab());
}

currentRouter.switchTabRouter(previousTabRouter == null ? null : previousTabRouter.backstack.peek());


if (previousTabRouter != null) {
container.post(new Runnable() {
@Override
public void run() {
previousTabRouter.removeHost();
}
});
}

previousTabRouter = currentRouter;
return currentRouter;
}

/**
* Removes a child {@link Router} from this Controller. When removed, all Controllers currently managed by
* the {@link Router} will be destroyed.
Expand Down
47 changes: 47 additions & 0 deletions conductor/src/main/java/com/bluelinelabs/conductor/Router.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.bluelinelabs.conductor.ControllerChangeHandler.ChangeTransaction;
import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeListener;
import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler;
import com.bluelinelabs.conductor.changehandler.SwapTabChangeHandler;
import com.bluelinelabs.conductor.internal.NoOpControllerChangeHandler;
import com.bluelinelabs.conductor.internal.ThreadUtils;
import com.bluelinelabs.conductor.internal.TransactionIndexer;
Expand Down Expand Up @@ -497,6 +498,44 @@ public void setBackstack(@NonNull List<RouterTransaction> newBackstack, @Nullabl
}
}

@SuppressWarnings("WeakerAccess")
@UiThread
public void switchTabRouter(@Nullable RouterTransaction from) {
ThreadUtils.ensureMainThread();

Iterator<RouterTransaction> backstackIterator = backstack.reverseIterator();
while (backstackIterator.hasNext()) {
RouterTransaction transaction = backstackIterator.next();

if (transaction.controller.getNeedsAttach()) {
ControllerChangeHandler handler = new SwapTabChangeHandler();
performControllerChange(transaction, from, true, handler);
}
}
}

@SuppressWarnings("WeakerAccess")
@UiThread
public void setRootForTab(@NonNull RouterTransaction rootTransaction) {
ThreadUtils.ensureMainThread();

rootTransaction.controller.setNeedsAttach(true);
List<RouterTransaction> rootTransactions = Collections.singletonList(rootTransaction);

removeAllExceptVisibleAndUnowned();
ensureOrderedTransactionIndices(rootTransactions);

backstack.setBackstack(rootTransactions);

// Ensure all new controllers have a valid router set
Iterator<RouterTransaction> backstackIterator = backstack.reverseIterator();
while (backstackIterator.hasNext()) {
RouterTransaction transaction = backstackIterator.next();
transaction.onAttachedToRouter();
setControllerRouter(transaction.controller);
}
}

/**
* Returns whether or not this Router has a root {@link Controller}
*/
Expand Down Expand Up @@ -618,6 +657,14 @@ public void onActivityDestroyed(@NonNull Activity activity) {
container = null;
}

public void prepareForHostTabAttach() {
RouterTransaction transaction = backstack.peek();
if (transaction != null){
transaction.controller.setNeedsAttach(true);
transaction.controller.prepareForHostDetach();
}
}

public void prepareForHostDetach() {
for (RouterTransaction transaction : backstack) {
if (ControllerChangeHandler.completeHandlerImmediately(transaction.controller.getInstanceId())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ public class SimpleSwapChangeHandler extends ControllerChangeHandler implements

private boolean removesFromViewOnPush;

private boolean canceled;
protected boolean canceled;

private ViewGroup container;
private ControllerChangeCompletedListener changeListener;
protected ViewGroup container;
protected ControllerChangeCompletedListener changeListener;

public SimpleSwapChangeHandler() {
this(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.bluelinelabs.conductor.changehandler;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.ViewGroup;

import com.bluelinelabs.conductor.ControllerChangeHandler;

/**
* A {@link ControllerChangeHandler} that will instantly swap Views with no animations or transitions.
*/
public class SwapTabChangeHandler extends SimpleSwapChangeHandler {

public SwapTabChangeHandler() {
}


@Override
public void performChange(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
if (!canceled) {
if (from != null) {
container.removeView(from);
}

if (to != null && to.getParent() == null) {
container.addView(to);
}
}

if (container.getWindowToken() != null) {
changeListener.onChangeCompleted();
} else {
this.changeListener = changeListener;
this.container = container;
container.addOnAttachStateChangeListener(this);
}

}
}