Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d4b5a5ef6 | |||
| ae27c5e453 | |||
| e4d23a7c74 | |||
| 778cdcfd58 | |||
| 5e730947aa | |||
| 71b10c7365 | |||
| 8c323b9613 | |||
| af45aae110 | |||
| d4c7e5791e | |||
| dc4c3a9709 | |||
| ef84fbd547 | |||
| 431569763e | |||
| 7b5bab3681 | |||
| 86b32afdcb | |||
| 557e4c2122 | |||
| 8b29c1cd56 | |||
| 30ef5a187b | |||
| ebe69bf98b | |||
| a907263ab8 | |||
| 7528437f65 | |||
| e2e8260876 | |||
| 6dfc5839cc |
+3
-4
@@ -14,10 +14,9 @@ jdk:
|
||||
- oraclejdk8
|
||||
|
||||
branches:
|
||||
except:
|
||||
- v2
|
||||
- feature/nested_controllers
|
||||
- feature/save_restore_lifecycle
|
||||
only
|
||||
- develop
|
||||
- master
|
||||
|
||||
before_install:
|
||||
- chmod +x .buildscript/deploy_snapshot.sh
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[](https://travis-ci.org/bluelinelabs/Conductor) [](http://android-arsenal.com/details/1/3361)
|
||||
[](https://travis-ci.org/bluelinelabs/Conductor) [](http://android-arsenal.com/details/1/3361) [](http://javadoc.io/doc/com.bluelinelabs/conductor)
|
||||
|
||||
# Conductor
|
||||
|
||||
@@ -20,21 +20,33 @@ Conductor is architecture-agnostic and does not try to force any design decision
|
||||
## Installation
|
||||
|
||||
```gradle
|
||||
compile 'com.bluelinelabs:conductor:1.1.5'
|
||||
compile 'com.bluelinelabs:conductor:2.0.1'
|
||||
|
||||
// If you want the components that go along with
|
||||
// Android's support libraries (currently just a PagerAdapter):
|
||||
compile 'com.bluelinelabs:conductor-support:1.1.5'
|
||||
compile 'com.bluelinelabs:conductor-support:2.0.1'
|
||||
|
||||
// If you want RxJava/RxAndroid lifecycle support:
|
||||
compile 'com.bluelinelabs:conductor-rxlifecycle:1.1.5'
|
||||
compile 'com.bluelinelabs:conductor-rxlifecycle:2.0.1'
|
||||
```
|
||||
|
||||
SNAPSHOT:
|
||||
|
||||
```gradle
|
||||
compile 'com.bluelinelabs:conductor:1.1.6-SNAPSHOT'
|
||||
compile 'com.bluelinelabs:conductor-support:1.1.6-SNAPSHOT'
|
||||
compile 'com.bluelinelabs:conductor-rxlifecycle:1.1.6-SNAPSHOT'
|
||||
compile 'com.bluelinelabs:conductor:2.0.2-SNAPSHOT'
|
||||
compile 'com.bluelinelabs:conductor-support:2.0.2-SNAPSHOT'
|
||||
compile 'com.bluelinelabs:conductor-rxlifecycle:2.0.2-SNAPSHOT'
|
||||
```
|
||||
|
||||
You also have to add the url to the snapshot repository:
|
||||
|
||||
```gradle
|
||||
allprojects {
|
||||
repositories {
|
||||
...
|
||||
|
||||
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||
}
|
||||
```
|
||||
|
||||
## Components to Know
|
||||
@@ -53,7 +65,7 @@ __ControllerTransaction__ | Transactions are used to define data about adding Co
|
||||
```java
|
||||
public class MainActivity extends Activity {
|
||||
|
||||
private Router mRouter;
|
||||
private Router router;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -61,17 +73,17 @@ public class MainActivity extends Activity {
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
ViewGroup container = (ViewGroup)findViewById(R.id.controller_container)
|
||||
ViewGroup container = (ViewGroup)findViewById(R.id.controller_container);
|
||||
|
||||
mRouter = Conductor.attachRouter(this, container, savedInstanceState);
|
||||
if (!mRouter.hasRootController()) {
|
||||
mRouter.setRoot(new HomeController());
|
||||
router = Conductor.attachRouter(this, container, savedInstanceState);
|
||||
if (!router.hasRootController()) {
|
||||
router.setRoot(RouterTransaction.with(new HomeController()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (!mRouter.handleBack()) {
|
||||
if (!router.handleBack()) {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
@@ -112,11 +124,11 @@ The lifecycle of a Controller is significantly simpler to understand than that o
|
||||
### Custom Change Handlers
|
||||
`ControllerChangeHandler` can be subclassed in order to perform different functions when changing between two `Controllers`. Two convenience `ControllerChangeHandler` subclasses are included to cover most basic needs: `AnimatorChangeHandler`, which will use an `Animator` object to transition between two views, and `TransitionChangeHandler`, which will use Lollipop's `Transition` framework for transitioning between views.
|
||||
|
||||
### Child Controllers
|
||||
`addChildController` can be called on a `Controller` in order to add nested `Controller`s. Child `Controller`s will receive all lifecycle callbacks that parents get.
|
||||
### Child Routers & Controllers
|
||||
`getChildRouter` can be called on a `Controller` in order to get a nested `Router` into which child `Controller`s can be pushed. This enables creating advanced layouts, such as Master/Detail.
|
||||
|
||||
### RxJava Lifecycle
|
||||
If the RxLifecycle dependency has been added, there is an `RxController` available that can be used along with the standard [RxLifecycle library](https://github.com/trello/RxLifecycle). There is also a `ControllerLifecycleProvider` available if you do not wish to use this subclass.
|
||||
If the RxLifecycle dependency has been added, there is an `RxController` available that can be used along with the standard [RxLifecycle library](https://github.com/trello/RxLifecycle). There is also a `ControllerLifecycleProvider` available if you do not wish to use this subclass.
|
||||
|
||||
## License
|
||||
```
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.1.0'
|
||||
classpath 'com.android.tools.build:gradle:2.1.2'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
POM_NAME=Conductor RxLifecycle Extensions
|
||||
POM_ARTIFACT_ID=conductor-rxlifecycle
|
||||
POM_PACKAGING=jar
|
||||
POM_PACKAGING=aar
|
||||
|
||||
+5
-5
@@ -15,7 +15,7 @@ import rx.subjects.BehaviorSubject;
|
||||
*/
|
||||
public abstract class RxController extends Controller implements ControllerLifecycleProvider {
|
||||
|
||||
private final BehaviorSubject<ControllerEvent> mLifecycleSubject;
|
||||
private final BehaviorSubject<ControllerEvent> lifecycleSubject;
|
||||
|
||||
public RxController() {
|
||||
this(null);
|
||||
@@ -23,28 +23,28 @@ public abstract class RxController extends Controller implements ControllerLifec
|
||||
|
||||
public RxController(Bundle args) {
|
||||
super(args);
|
||||
mLifecycleSubject = ControllerLifecycleSubjectHelper.create(this);
|
||||
lifecycleSubject = ControllerLifecycleSubjectHelper.create(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@CheckResult
|
||||
public final Observable<ControllerEvent> lifecycle() {
|
||||
return mLifecycleSubject.asObservable();
|
||||
return lifecycleSubject.asObservable();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@CheckResult
|
||||
public final <T> Observable.Transformer<T, T> bindUntilEvent(@NonNull ControllerEvent event) {
|
||||
return RxLifecycle.bindUntilEvent(mLifecycleSubject, event);
|
||||
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@CheckResult
|
||||
public final <T> Observable.Transformer<T, T> bindToLifecycle() {
|
||||
return RxControllerLifecycle.bindController(mLifecycleSubject);
|
||||
return RxControllerLifecycle.bindController(lifecycleSubject);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
POM_NAME=Conductor Support Extensions
|
||||
POM_ARTIFACT_ID=conductor-support
|
||||
POM_PACKAGING=jar
|
||||
POM_PACKAGING=aar
|
||||
|
||||
+54
-12
@@ -1,24 +1,34 @@
|
||||
package com.bluelinelabs.conductor.support;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.support.v4.view.PagerAdapter;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.ChildControllerTransaction;
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.bluelinelabs.conductor.Router;
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
|
||||
/**
|
||||
* An adapter for ViewPagers that will handle adding and removing Controllers
|
||||
*/
|
||||
public abstract class ControllerPagerAdapter extends PagerAdapter {
|
||||
|
||||
private final Controller mHost;
|
||||
private static final String KEY_SAVED_PAGES = "ControllerPagerAdapter.savedStates";
|
||||
private static final String KEY_SAVES_STATE = "ControllerPagerAdapter.savesState";
|
||||
|
||||
private final Controller host;
|
||||
private boolean savesState;
|
||||
private SparseArray<Bundle> savedPages = new SparseArray<>();
|
||||
|
||||
/**
|
||||
* Creates a new ControllerPagerAdapter using the passed host.
|
||||
*/
|
||||
public ControllerPagerAdapter(Controller host) {
|
||||
mHost = host;
|
||||
public ControllerPagerAdapter(Controller host, boolean saveControllerState) {
|
||||
this.host = host;
|
||||
savesState = saveControllerState;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,21 +40,36 @@ public abstract class ControllerPagerAdapter extends PagerAdapter {
|
||||
public Object instantiateItem(ViewGroup container, int position) {
|
||||
final String name = makeControllerName(container.getId(), getItemId(position));
|
||||
|
||||
Controller controller = mHost.getChildController(name);
|
||||
if (controller == null) {
|
||||
controller = getItem(position);
|
||||
Router router = host.getChildRouter(container, name);
|
||||
if (savesState && !router.hasRootController()) {
|
||||
Bundle routerSavedState = savedPages.get(position);
|
||||
|
||||
mHost.addChildController(ChildControllerTransaction.builder(controller, container.getId())
|
||||
.tag(name)
|
||||
.build());
|
||||
if (routerSavedState != null) {
|
||||
router.restoreInstanceState(routerSavedState);
|
||||
}
|
||||
}
|
||||
|
||||
return controller;
|
||||
if (!router.hasRootController()) {
|
||||
router.setRoot(RouterTransaction.with(getItem(position))
|
||||
.tag(name));
|
||||
} else {
|
||||
router.rebindIfNeeded();
|
||||
}
|
||||
|
||||
return router.getControllerWithTag(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(ViewGroup container, int position, Object object) {
|
||||
mHost.removeChildController((Controller)object);
|
||||
Router router = ((Controller)object).getRouter();
|
||||
|
||||
if (savesState) {
|
||||
Bundle savedState = new Bundle();
|
||||
router.saveInstanceState(savedState);
|
||||
savedPages.put(position, savedState);
|
||||
}
|
||||
|
||||
host.removeChildRouter(router);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,6 +77,23 @@ public abstract class ControllerPagerAdapter extends PagerAdapter {
|
||||
return ((Controller)object).getView() == view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable saveState() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(KEY_SAVES_STATE, savesState);
|
||||
bundle.putSparseParcelableArray(KEY_SAVED_PAGES, savedPages);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreState(Parcelable state, ClassLoader loader) {
|
||||
Bundle bundle = (Bundle)state;
|
||||
if (state != null) {
|
||||
savesState = bundle.getBoolean(KEY_SAVES_STATE, false);
|
||||
savedPages = bundle.getSparseParcelableArray(KEY_SAVED_PAGES);
|
||||
}
|
||||
}
|
||||
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ android {
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode Integer.parseInt(project.VERSION_CODE)
|
||||
versionName project.VERSION_NAME
|
||||
consumerProguardFiles 'proguard-rules.txt'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
POM_NAME=Conductor
|
||||
POM_ARTIFACT_ID=conductor
|
||||
POM_PACKAGING=jar
|
||||
POM_PACKAGING=aar
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Retain constructor that is called by using reflection to recreate the Controller
|
||||
-keepclassmembers public class * extends com.bluelinelabs.conductor.Controller {
|
||||
public <init>();
|
||||
public <init>(android.os.Bundle);
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.bluelinelabs.conductor;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeListener;
|
||||
import com.bluelinelabs.conductor.internal.LifecycleHandler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ActivityHostedRouter extends Router {
|
||||
|
||||
private LifecycleHandler lifecycleHandler;
|
||||
|
||||
public final void setHost(@NonNull LifecycleHandler lifecycleHandler, @NonNull ViewGroup container) {
|
||||
if (this.lifecycleHandler != lifecycleHandler || this.container != container) {
|
||||
if (this.container != null && this.container instanceof ControllerChangeListener) {
|
||||
removeChangeListener((ControllerChangeListener)this.container);
|
||||
}
|
||||
|
||||
if (container instanceof ControllerChangeListener) {
|
||||
addChangeListener((ControllerChangeListener)container);
|
||||
}
|
||||
|
||||
this.lifecycleHandler = lifecycleHandler;
|
||||
this.container = container;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Activity getActivity() {
|
||||
return lifecycleHandler != null ? lifecycleHandler.getLifecycleActivity() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
super.onActivityDestroyed(activity);
|
||||
lifecycleHandler = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void invalidateOptionsMenu() {
|
||||
if (lifecycleHandler != null && lifecycleHandler.getFragmentManager() != null) {
|
||||
lifecycleHandler.getFragmentManager().invalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
lifecycleHandler.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
void startActivity(Intent intent) {
|
||||
lifecycleHandler.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
void startActivityForResult(String instanceId, Intent intent, int requestCode) {
|
||||
lifecycleHandler.startActivityForResult(instanceId, intent, requestCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
void startActivityForResult(String instanceId, Intent intent, int requestCode, Bundle options) {
|
||||
lifecycleHandler.startActivityForResult(instanceId, intent, requestCode, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerForActivityResult(String instanceId, int requestCode) {
|
||||
lifecycleHandler.registerForActivityResult(instanceId, requestCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
void unregisterForActivityResults(String instanceId) {
|
||||
lifecycleHandler.unregisterForActivityResults(instanceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
void requestPermissions(String instanceId, @NonNull String[] permissions, int requestCode) {
|
||||
lifecycleHandler.requestPermissions(instanceId, permissions, requestCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean hasHost() {
|
||||
return lifecycleHandler != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
List<Router> getSiblingRouters() {
|
||||
return lifecycleHandler.getRouters();
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import android.os.Bundle;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@@ -12,34 +13,34 @@ class Backstack implements Iterable<RouterTransaction> {
|
||||
|
||||
private static final String KEY_ENTRIES = "Backstack.entries";
|
||||
|
||||
private final ArrayDeque<RouterTransaction> mBackStack = new ArrayDeque<>();
|
||||
private final Deque<RouterTransaction> backStack = new ArrayDeque<>();
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean isEmpty() {
|
||||
return mBackStack.isEmpty();
|
||||
return backStack.isEmpty();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return mBackStack.size();
|
||||
return backStack.size();
|
||||
}
|
||||
|
||||
public RouterTransaction root() {
|
||||
return mBackStack.size() > 0 ? mBackStack.getLast() : null;
|
||||
return backStack.size() > 0 ? backStack.getLast() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<RouterTransaction> iterator() {
|
||||
return mBackStack.iterator();
|
||||
return backStack.iterator();
|
||||
}
|
||||
|
||||
public Iterator<RouterTransaction> reverseIterator() {
|
||||
return mBackStack.descendingIterator();
|
||||
return backStack.descendingIterator();
|
||||
}
|
||||
|
||||
public List<RouterTransaction> popTo(RouterTransaction transaction) {
|
||||
List<RouterTransaction> popped = new ArrayList<>();
|
||||
if (mBackStack.contains(transaction)) {
|
||||
while (mBackStack.peek() != transaction) {
|
||||
if (backStack.contains(transaction)) {
|
||||
while (backStack.peek() != transaction) {
|
||||
RouterTransaction poppedTransaction = pop();
|
||||
popped.add(poppedTransaction);
|
||||
}
|
||||
@@ -50,21 +51,21 @@ class Backstack implements Iterable<RouterTransaction> {
|
||||
}
|
||||
|
||||
public RouterTransaction pop() {
|
||||
RouterTransaction popped = mBackStack.pop();
|
||||
popped.getController().destroy();
|
||||
RouterTransaction popped = backStack.pop();
|
||||
popped.controller.destroy();
|
||||
return popped;
|
||||
}
|
||||
|
||||
public RouterTransaction peek() {
|
||||
return mBackStack.peek();
|
||||
return backStack.peek();
|
||||
}
|
||||
|
||||
public void remove(RouterTransaction transaction) {
|
||||
mBackStack.removeFirstOccurrence(transaction);
|
||||
backStack.removeFirstOccurrence(transaction);
|
||||
}
|
||||
|
||||
public void push(RouterTransaction transaction) {
|
||||
mBackStack.push(transaction);
|
||||
backStack.push(transaction);
|
||||
}
|
||||
|
||||
public List<RouterTransaction> popAll() {
|
||||
@@ -75,10 +76,31 @@ class Backstack implements Iterable<RouterTransaction> {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void detachAndSaveInstanceState(Bundle outState) {
|
||||
ArrayList<Bundle> entryBundles = new ArrayList<>(mBackStack.size());
|
||||
for (RouterTransaction entry : mBackStack) {
|
||||
entryBundles.add(entry.detachAndSaveInstanceState());
|
||||
public void setBackstack(List<RouterTransaction> backstack) {
|
||||
for (RouterTransaction existingTransaction : backStack) {
|
||||
boolean contains = false;
|
||||
for (RouterTransaction newTransaction : backstack) {
|
||||
if (existingTransaction.controller == newTransaction.controller) {
|
||||
contains = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!contains) {
|
||||
existingTransaction.controller.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
backStack.clear();
|
||||
for (RouterTransaction transaction : backstack) {
|
||||
backStack.push(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveInstanceState(Bundle outState) {
|
||||
ArrayList<Bundle> entryBundles = new ArrayList<>(backStack.size());
|
||||
for (RouterTransaction entry : backStack) {
|
||||
entryBundles.add(entry.saveInstanceState());
|
||||
}
|
||||
|
||||
outState.putParcelableArrayList(KEY_ENTRIES, entryBundles);
|
||||
@@ -89,7 +111,7 @@ class Backstack implements Iterable<RouterTransaction> {
|
||||
if (entryBundles != null) {
|
||||
Collections.reverse(entryBundles);
|
||||
for (Bundle transactionBundle : entryBundles) {
|
||||
mBackStack.push(new RouterTransaction(transactionBundle));
|
||||
backStack.push(new RouterTransaction(transactionBundle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeListen
|
||||
*/
|
||||
public class ChangeHandlerFrameLayout extends FrameLayout implements ControllerChangeListener {
|
||||
|
||||
private int mInProgressTransactionCount;
|
||||
private int inProgressTransactionCount;
|
||||
|
||||
public ChangeHandlerFrameLayout(Context context) {
|
||||
super(context);
|
||||
@@ -38,17 +38,17 @@ public class ChangeHandlerFrameLayout extends FrameLayout implements ControllerC
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
return (mInProgressTransactionCount > 0) || super.onInterceptTouchEvent(ev);
|
||||
return (inProgressTransactionCount > 0) || super.onInterceptTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeStarted(Controller to, Controller from, boolean isPush, ViewGroup container, ControllerChangeHandler handler) {
|
||||
mInProgressTransactionCount++;
|
||||
inProgressTransactionCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeCompleted(Controller to, Controller from, boolean isPush, ViewGroup container, ControllerChangeHandler handler) {
|
||||
mInProgressTransactionCount--;
|
||||
inProgressTransactionCount--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
package com.bluelinelabs.conductor;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* A {@link ControllerTransaction} implementation used for adding child {@link Controller}s.
|
||||
*/
|
||||
public class ChildControllerTransaction extends ControllerTransaction {
|
||||
|
||||
private static final String KEY_CONTAINER_ID = "ChildControllerTransaction.containerId";
|
||||
private static final String KEY_ADD_TO_LOCAL_BACKSTACK = "ChildControllerTransaction.addToLocalBackstack";
|
||||
|
||||
/** The ID of the ViewGroup that the child {@link Controller} will be added to */
|
||||
public final int containerId;
|
||||
|
||||
/** If true, the hosting {@link Controller} will be responsible for reversing this transaction if the user presses the back button */
|
||||
public final boolean addToLocalBackstack;
|
||||
|
||||
ChildControllerTransaction(Builder builder) {
|
||||
super(builder);
|
||||
containerId = builder.containerId;
|
||||
addToLocalBackstack = builder.addToLocalBackstack;
|
||||
}
|
||||
|
||||
ChildControllerTransaction(@NonNull Bundle bundle) {
|
||||
super(bundle);
|
||||
containerId = bundle.getInt(KEY_CONTAINER_ID);
|
||||
addToLocalBackstack = bundle.getBoolean(KEY_ADD_TO_LOCAL_BACKSTACK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle detachAndSaveInstanceState() {
|
||||
Bundle bundle = super.detachAndSaveInstanceState();
|
||||
bundle.putInt(KEY_CONTAINER_ID, containerId);
|
||||
bundle.putBoolean(KEY_ADD_TO_LOCAL_BACKSTACK, addToLocalBackstack);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Builder
|
||||
*
|
||||
* @param controller The Controller to add as a child
|
||||
* @param containerId The ID of the ViewGroup to which the controller's view should be added
|
||||
*/
|
||||
public static Builder builder(@NonNull Controller controller, @IdRes int containerId) {
|
||||
return new Builder(controller, containerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link ControllerTransaction.Builder} implementation used for adding child {@link Controller}s.
|
||||
*/
|
||||
public static class Builder extends ControllerTransaction.Builder<Builder> {
|
||||
|
||||
@IdRes final int containerId;
|
||||
|
||||
boolean addToLocalBackstack;
|
||||
|
||||
Builder(@NonNull Controller controller, @IdRes int containerId) {
|
||||
super(controller);
|
||||
this.containerId = containerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* If true, the hosting {@link Controller} will be responsible for reversing this transaction if the user presses the back button.
|
||||
*/
|
||||
public Builder addToLocalBackstack(boolean addToLocalBackstack) {
|
||||
this.addToLocalBackstack = addToLocalBackstack;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Creates the transaction */
|
||||
public ChildControllerTransaction build() {
|
||||
return new ChildControllerTransaction(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Executable → Regular
+26
-2
@@ -5,12 +5,13 @@ import android.support.annotation.NonNull;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.ControllerTransaction.ControllerChangeType;
|
||||
import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler;
|
||||
import com.bluelinelabs.conductor.internal.ClassUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* ControllerChangeHandlers are responsible for swapping the View for one Controller to the View
|
||||
@@ -22,6 +23,8 @@ public abstract class ControllerChangeHandler {
|
||||
private static final String KEY_CLASS_NAME = "ControllerChangeHandler.className";
|
||||
private static final String KEY_SAVED_STATE = "ControllerChangeHandler.savedState";
|
||||
|
||||
private static final Map<String, ControllerChangeHandler> inProgressPushHandlers = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Responsible for swapping Views from one Controller to another.
|
||||
*
|
||||
@@ -51,6 +54,15 @@ public abstract class ControllerChangeHandler {
|
||||
*/
|
||||
public void restoreFromBundle(@NonNull Bundle bundle) { }
|
||||
|
||||
/**
|
||||
* Will be called on change handlers that push a controller if the controller being pushed is
|
||||
* popped before it has completed.
|
||||
*
|
||||
* @param newHandler the change handler that has caused this push to be aborted
|
||||
* @param newTop the controller that will now be at the top of the backstack
|
||||
*/
|
||||
public void onAbortPush(@NonNull ControllerChangeHandler newHandler, Controller newTop) { }
|
||||
|
||||
final Bundle toBundle() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(KEY_CLASS_NAME, getClass().getName());
|
||||
@@ -88,6 +100,18 @@ public abstract class ControllerChangeHandler {
|
||||
|
||||
public static void executeChange(final Controller to, final Controller from, final boolean isPush, final ViewGroup container, final ControllerChangeHandler inHandler, @NonNull final List<ControllerChangeListener> listeners) {
|
||||
if (container != null) {
|
||||
final ControllerChangeHandler handler = inHandler != null ? inHandler : new SimpleSwapChangeHandler();
|
||||
|
||||
if (isPush) {
|
||||
inProgressPushHandlers.put(to.getInstanceId(), handler);
|
||||
} else if (from != null) {
|
||||
ControllerChangeHandler handlerForPush = inProgressPushHandlers.get(from.getInstanceId());
|
||||
if (handlerForPush != null) {
|
||||
handlerForPush.onAbortPush(handler, to);
|
||||
inProgressPushHandlers.remove(from.getInstanceId());
|
||||
}
|
||||
}
|
||||
|
||||
for (ControllerChangeListener listener : listeners) {
|
||||
listener.onChangeStarted(to, from, isPush, container, inHandler);
|
||||
}
|
||||
@@ -95,7 +119,6 @@ public abstract class ControllerChangeHandler {
|
||||
final ControllerChangeType toChangeType = isPush ? ControllerChangeType.PUSH_ENTER : ControllerChangeType.POP_ENTER;
|
||||
final ControllerChangeType fromChangeType = isPush ? ControllerChangeType.PUSH_EXIT : ControllerChangeType.POP_EXIT;
|
||||
|
||||
final ControllerChangeHandler handler = inHandler != null ? inHandler : new SimpleSwapChangeHandler();
|
||||
final View toView;
|
||||
if (to != null) {
|
||||
toView = to.inflate(container);
|
||||
@@ -120,6 +143,7 @@ public abstract class ControllerChangeHandler {
|
||||
}
|
||||
|
||||
if (to != null) {
|
||||
inProgressPushHandlers.remove(to.getInstanceId());
|
||||
to.changeEnded(handler, toChangeType);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.bluelinelabs.conductor;
|
||||
|
||||
/**
|
||||
* All possible types of {@link Controller} changes to be used in {@link ControllerChangeHandler}s
|
||||
*/
|
||||
public enum ControllerChangeType {
|
||||
/** The Controller is being pushed to the host container */
|
||||
PUSH_ENTER(true, true),
|
||||
|
||||
/** The Controller is being pushed to the backstack as another Controller is pushed to the host container */
|
||||
PUSH_EXIT(true, false),
|
||||
|
||||
/** The Controller is being popped from the backstack and placed in the host container as another Controller is popped */
|
||||
POP_ENTER(false, true),
|
||||
|
||||
/** The Controller is being popped from the host container */
|
||||
POP_EXIT(false, false);
|
||||
|
||||
public boolean isPush;
|
||||
public boolean isEnter;
|
||||
|
||||
ControllerChangeType(boolean isPush, boolean isEnter) {
|
||||
this.isPush = isPush;
|
||||
this.isEnter = isEnter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package com.bluelinelabs.conductor;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class ControllerHostedRouter extends Router {
|
||||
|
||||
private final String KEY_HOST_ID = "ControllerHostedRouter.hostId";
|
||||
private final String KEY_TAG = "ControllerHostedRouter.tag";
|
||||
|
||||
private Controller hostController;
|
||||
|
||||
@IdRes private int hostId;
|
||||
private String tag;
|
||||
|
||||
ControllerHostedRouter() { }
|
||||
|
||||
ControllerHostedRouter(int hostId, String tag) {
|
||||
this.hostId = hostId;
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
final void setHost(@NonNull Controller controller, @NonNull ViewGroup container) {
|
||||
if (hostController != controller || this.container != container) {
|
||||
removeHost();
|
||||
|
||||
if (container instanceof ControllerChangeListener) {
|
||||
addChangeListener((ControllerChangeListener)container);
|
||||
}
|
||||
|
||||
hostController = controller;
|
||||
this.container = container;
|
||||
}
|
||||
}
|
||||
|
||||
final void removeHost() {
|
||||
if (container != null && container instanceof ControllerChangeListener) {
|
||||
removeChangeListener((ControllerChangeListener)container);
|
||||
}
|
||||
|
||||
for (Controller controller : destroyingControllers) {
|
||||
if (controller.getView() != null) {
|
||||
controller.detach(controller.getView(), true);
|
||||
}
|
||||
}
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
if (transaction.controller.getView() != null) {
|
||||
transaction.controller.detach(transaction.controller.getView(), true);
|
||||
}
|
||||
}
|
||||
|
||||
prepareForContainerRemoval();
|
||||
hostController = null;
|
||||
container = null;
|
||||
}
|
||||
|
||||
final void setDetachFrozen(boolean frozen) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
transaction.controller.setDetachFrozen(frozen);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Activity getActivity() {
|
||||
return hostController != null ? hostController.getActivity() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
super.onActivityDestroyed(activity);
|
||||
|
||||
removeHost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (hostController != null && hostController.getRouter() != null) {
|
||||
hostController.getRouter().onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateOptionsMenu() {
|
||||
if (hostController != null && hostController.getRouter() != null) {
|
||||
hostController.getRouter().invalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void startActivity(Intent intent) {
|
||||
if (hostController != null && hostController.getRouter() != null) {
|
||||
hostController.getRouter().startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void startActivityForResult(String instanceId, Intent intent, int requestCode) {
|
||||
if (hostController != null && hostController.getRouter() != null) {
|
||||
hostController.getRouter().startActivityForResult(instanceId, intent, requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void startActivityForResult(String instanceId, Intent intent, int requestCode, Bundle options) {
|
||||
if (hostController != null && hostController.getRouter() != null) {
|
||||
hostController.getRouter().startActivityForResult(instanceId, intent, requestCode, options);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void registerForActivityResult(String instanceId, int requestCode) {
|
||||
if (hostController != null && hostController.getRouter() != null) {
|
||||
hostController.getRouter().registerForActivityResult(instanceId, requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void unregisterForActivityResults(String instanceId) {
|
||||
if (hostController != null && hostController.getRouter() != null) {
|
||||
hostController.getRouter().unregisterForActivityResults(instanceId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void requestPermissions(String instanceId, String[] permissions, int requestCode) {
|
||||
if (hostController != null && hostController.getRouter() != null) {
|
||||
hostController.getRouter().requestPermissions(instanceId, permissions, requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean hasHost() {
|
||||
return hostController != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveInstanceState(Bundle outState) {
|
||||
super.saveInstanceState(outState);
|
||||
|
||||
outState.putInt(KEY_HOST_ID, hostId);
|
||||
outState.putString(KEY_TAG, tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreInstanceState(Bundle savedInstanceState) {
|
||||
super.restoreInstanceState(savedInstanceState);
|
||||
|
||||
hostId = savedInstanceState.getInt(KEY_HOST_ID);
|
||||
tag = savedInstanceState.getString(KEY_TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setControllerRouter(Controller controller) {
|
||||
super.setControllerRouter(controller);
|
||||
controller.setParentController(hostController);
|
||||
}
|
||||
|
||||
int getHostId() {
|
||||
return hostId;
|
||||
}
|
||||
|
||||
String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
List<Router> getSiblingRouters() {
|
||||
List<Router> list = new ArrayList<>();
|
||||
list.addAll(hostController.getChildRouters());
|
||||
list.addAll(hostController.getRouter().getSiblingRouters());
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
package com.bluelinelabs.conductor;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Metadata used to transition between {@link Controller}s.
|
||||
*/
|
||||
public class ControllerTransaction {
|
||||
|
||||
/**
|
||||
* All possible types of {@link Controller} changes to be used in {@link ControllerChangeHandler}s
|
||||
*/
|
||||
public enum ControllerChangeType {
|
||||
/** The Controller is being pushed to the host container */
|
||||
PUSH_ENTER(true, true),
|
||||
|
||||
/** The Controller is being pushed to the backstack as another Controller is pushed to the host container */
|
||||
PUSH_EXIT(true, false),
|
||||
|
||||
/** The Controller is being popped from the backstack and placed in the host container as another Controller is popped */
|
||||
POP_ENTER(false, true),
|
||||
|
||||
/** The Controller is being popped from the host container */
|
||||
POP_EXIT(false, false);
|
||||
|
||||
public boolean isPush;
|
||||
public boolean isEnter;
|
||||
|
||||
ControllerChangeType(boolean isPush, boolean isEnter) {
|
||||
this.isPush = isPush;
|
||||
this.isEnter = isEnter;
|
||||
}
|
||||
}
|
||||
|
||||
private static final String KEY_VIEW_CONTROLLER_BUNDLE = "ControllerTransaction.controller.bundle";
|
||||
private static final String KEY_PUSH_TRANSITION = "ControllerTransaction.pushControllerChangeHandler";
|
||||
private static final String KEY_POP_TRANSITION = "ControllerTransaction.popControllerChangeHandler";
|
||||
private static final String KEY_TAG = "ControllerTransaction.tag";
|
||||
|
||||
public final Controller controller;
|
||||
public final String tag;
|
||||
|
||||
private final ControllerChangeHandler mPushControllerChangeHandler;
|
||||
private final ControllerChangeHandler mPopControllerChangeHandler;
|
||||
|
||||
ControllerTransaction(Builder builder) {
|
||||
controller = builder.controller;
|
||||
tag = builder.tag;
|
||||
mPushControllerChangeHandler = builder.pushControllerChangeHandler;
|
||||
mPopControllerChangeHandler = builder.popControllerChangeHandler;
|
||||
}
|
||||
|
||||
ControllerTransaction(@NonNull Bundle bundle) {
|
||||
controller = Controller.newInstance(bundle.getBundle(KEY_VIEW_CONTROLLER_BUNDLE));
|
||||
mPushControllerChangeHandler = ControllerChangeHandler.fromBundle(bundle.getBundle(KEY_PUSH_TRANSITION));
|
||||
mPopControllerChangeHandler = ControllerChangeHandler.fromBundle(bundle.getBundle(KEY_POP_TRANSITION));
|
||||
tag = bundle.getString(KEY_TAG);
|
||||
}
|
||||
|
||||
public Controller getController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public ControllerChangeHandler getPushControllerChangeHandler() {
|
||||
ControllerChangeHandler handler = controller.getOverriddenPushHandler();
|
||||
if (handler == null) {
|
||||
handler = mPushControllerChangeHandler;
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
public ControllerChangeHandler getPopControllerChangeHandler() {
|
||||
ControllerChangeHandler handler = controller.getOverriddenPopHandler();
|
||||
if (handler == null) {
|
||||
handler = mPopControllerChangeHandler;
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to serialize this transaction into a Bundle
|
||||
*/
|
||||
public Bundle detachAndSaveInstanceState() {
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
bundle.putBundle(KEY_VIEW_CONTROLLER_BUNDLE, controller.detachAndSaveInstanceState());
|
||||
|
||||
if (mPushControllerChangeHandler != null) {
|
||||
bundle.putBundle(KEY_PUSH_TRANSITION, mPushControllerChangeHandler.toBundle());
|
||||
}
|
||||
if (mPopControllerChangeHandler != null) {
|
||||
bundle.putBundle(KEY_POP_TRANSITION, mPopControllerChangeHandler.toBundle());
|
||||
}
|
||||
|
||||
bundle.putString(KEY_TAG, tag);
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder used to create transactions.
|
||||
*/
|
||||
public static class Builder<T extends Builder<T>> {
|
||||
|
||||
final Controller controller;
|
||||
ControllerChangeHandler pushControllerChangeHandler;
|
||||
ControllerChangeHandler popControllerChangeHandler;
|
||||
String tag;
|
||||
|
||||
public Builder(@NonNull Controller controller) {
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link ControllerChangeHandler} that will be used when the {@link Controller} is pushed
|
||||
* to the screen.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T pushChangeHandler(ControllerChangeHandler pushControllerChangeHandler) {
|
||||
this.pushControllerChangeHandler = pushControllerChangeHandler;
|
||||
return (T)this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link ControllerChangeHandler} that will be used when the {@link Controller} is popped
|
||||
* from the screen.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T popChangeHandler(ControllerChangeHandler popControllerChangeHandler) {
|
||||
this.popControllerChangeHandler = popControllerChangeHandler;
|
||||
return (T)this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The tag to use for this transaction. Tags can be used for finding transactions later on.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T tag(String tag) {
|
||||
this.tag = tag;
|
||||
return (T)this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the transaction.
|
||||
*/
|
||||
public ControllerTransaction build() {
|
||||
return new ControllerTransaction(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import android.view.ViewGroup;
|
||||
import com.bluelinelabs.conductor.Controller.LifecycleListener;
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeListener;
|
||||
import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler;
|
||||
import com.bluelinelabs.conductor.internal.LifecycleHandler;
|
||||
import com.bluelinelabs.conductor.internal.NoOpControllerChangeHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -25,20 +24,23 @@ import java.util.List;
|
||||
* to Activity/containing ViewGroup pairs. Routers do not directly render or push Views to the container ViewGroup,
|
||||
* but instead defer this responsibility to the {@link ControllerChangeHandler} specified in a given transaction.
|
||||
*/
|
||||
public class Router {
|
||||
public abstract class Router {
|
||||
|
||||
private final Backstack mBackStack = new Backstack();
|
||||
private LifecycleHandler mLifecycleHandler;
|
||||
private ViewGroup mContainer;
|
||||
private final List<ControllerChangeListener> mChangeListeners = new ArrayList<>();
|
||||
private final List<Controller> mDestroyingControllers = new ArrayList<>();
|
||||
private static final String KEY_BACKSTACK = "Router.backstack";
|
||||
private static final String KEY_POPS_LAST_VIEW = "Router.popsLastView";
|
||||
|
||||
protected final Backstack backStack = new Backstack();
|
||||
private final List<ControllerChangeListener> changeListeners = new ArrayList<>();
|
||||
final List<Controller> destroyingControllers = new ArrayList<>();
|
||||
|
||||
private boolean popsLastView = false;
|
||||
|
||||
ViewGroup container;
|
||||
|
||||
/**
|
||||
* Returns this Router's host Activity
|
||||
*/
|
||||
public Activity getActivity() {
|
||||
return mLifecycleHandler != null ? mLifecycleHandler.getLifecycleActivity() : null;
|
||||
}
|
||||
public abstract Activity getActivity();
|
||||
|
||||
/**
|
||||
* This should be called by the host Activity when its onActivityResult method is called if the instanceId
|
||||
@@ -48,9 +50,7 @@ public class Router {
|
||||
* @param resultCode The Activity's onActivityResult resultCode
|
||||
* @param data The Activity's onActivityResult data
|
||||
*/
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
getLifecycleHandler().onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
public abstract void onActivityResult(int requestCode, int resultCode, Intent data);
|
||||
|
||||
/**
|
||||
* This should be called by the host Activity when its onRequestPermissionsResult method is called. The call will be forwarded
|
||||
@@ -73,8 +73,8 @@ public class Router {
|
||||
* to its top {@link Controller}. If that controller doesn't handle it, then it will be popped.
|
||||
*/
|
||||
public boolean handleBack() {
|
||||
if (!mBackStack.isEmpty()) {
|
||||
if (mBackStack.peek().controller.handleBack()) {
|
||||
if (!backStack.isEmpty()) {
|
||||
if (backStack.peek().controller.handleBack()) {
|
||||
return true;
|
||||
} else if (popCurrentController()) {
|
||||
return true;
|
||||
@@ -90,7 +90,7 @@ public class Router {
|
||||
* @return Whether or not this Router still has controllers remaining on it after popping.
|
||||
*/
|
||||
public boolean popCurrentController() {
|
||||
return popController(mBackStack.peek().controller);
|
||||
return popController(backStack.peek().controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,25 +100,29 @@ public class Router {
|
||||
* @return Whether or not this Router still has controllers remaining on it after popping.
|
||||
*/
|
||||
public boolean popController(Controller controller) {
|
||||
RouterTransaction topController = mBackStack.peek();
|
||||
boolean poppingTopController = topController.controller == controller;
|
||||
RouterTransaction topController = backStack.peek();
|
||||
boolean poppingTopController = topController != null && topController.controller == controller;
|
||||
|
||||
if (poppingTopController) {
|
||||
trackDestroyingController(mBackStack.pop());
|
||||
trackDestroyingController(backStack.pop());
|
||||
} else {
|
||||
for (RouterTransaction transaction : mBackStack) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
if (transaction.controller == controller) {
|
||||
mBackStack.remove(transaction);
|
||||
backStack.remove(transaction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (poppingTopController) {
|
||||
performControllerChange(mBackStack.peek(), topController, false);
|
||||
performControllerChange(backStack.peek(), topController, false);
|
||||
}
|
||||
|
||||
return !mBackStack.isEmpty();
|
||||
if (popsLastView) {
|
||||
return topController != null;
|
||||
} else {
|
||||
return !backStack.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +132,7 @@ public class Router {
|
||||
* and its push and pop {@link ControllerChangeHandler}, and its tag.
|
||||
*/
|
||||
public void pushController(@NonNull RouterTransaction transaction) {
|
||||
RouterTransaction from = mBackStack.peek();
|
||||
RouterTransaction from = backStack.peek();
|
||||
pushToBackstack(transaction);
|
||||
performControllerChange(transaction, from, true);
|
||||
}
|
||||
@@ -140,15 +144,36 @@ public class Router {
|
||||
* and its push and pop {@link ControllerChangeHandler}, and its tag.
|
||||
*/
|
||||
public void replaceTopController(@NonNull RouterTransaction transaction) {
|
||||
RouterTransaction topTransaction = mBackStack.peek();
|
||||
if (!mBackStack.isEmpty()) {
|
||||
trackDestroyingController(mBackStack.pop());
|
||||
RouterTransaction topTransaction = backStack.peek();
|
||||
if (!backStack.isEmpty()) {
|
||||
trackDestroyingController(backStack.pop());
|
||||
}
|
||||
|
||||
pushToBackstack(transaction);
|
||||
performControllerChange(transaction, topTransaction, true);
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
popsLastView = true;
|
||||
List<RouterTransaction> poppedControllers = backStack.popAll();
|
||||
|
||||
if (poppedControllers.size() > 0) {
|
||||
trackDestroyingControllers(poppedControllers);
|
||||
|
||||
performControllerChange(null, poppedControllers.get(0).controller, false, poppedControllers.get(0).popChangeHandler());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to true, this router will handle back presses by performing a change handler on the last controller and view
|
||||
* in the stack. This defaults to false so that the developer can either finish its containing Activity or otherwise
|
||||
* hide its parent view without any strange artifacting.
|
||||
*/
|
||||
public Router setPopsLastView(boolean popsLastView) {
|
||||
this.popsLastView = popsLastView;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops all {@link Controller}s until only the root is left
|
||||
*
|
||||
@@ -165,8 +190,8 @@ public class Router {
|
||||
* @return Whether or not any {@link Controller}s were popped in order to get to the root transaction
|
||||
*/
|
||||
public boolean popToRoot(ControllerChangeHandler changeHandler) {
|
||||
if (mBackStack.size() > 1) {
|
||||
popToTransaction(mBackStack.root(), changeHandler);
|
||||
if (backStack.size() > 1) {
|
||||
popToTransaction(backStack.root(), changeHandler);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -191,8 +216,8 @@ public class Router {
|
||||
* @return Whether or not the {@link Controller} with the passed tag is now at the top
|
||||
*/
|
||||
public boolean popToTag(@NonNull String tag, ControllerChangeHandler changeHandler) {
|
||||
for (RouterTransaction transaction : mBackStack) {
|
||||
if (tag.equals(transaction.tag)) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
if (tag.equals(transaction.tag())) {
|
||||
popToTransaction(transaction, changeHandler);
|
||||
return true;
|
||||
}
|
||||
@@ -200,64 +225,17 @@ public class Router {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the root {@link Controller}. If any {@link Controller}s are currently in the backstack, they will be removed.
|
||||
*
|
||||
* @param controller The new root {@link Controller}
|
||||
*/
|
||||
public void setRoot(@NonNull Controller controller) {
|
||||
setRoot(controller, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the root {@link Controller}. If any {@link Controller}s are currently in the backstack, they will be removed.
|
||||
*
|
||||
* @param controller The new root {@link Controller}
|
||||
* @param tag The tag to use for this {@link Controller}
|
||||
*/
|
||||
public void setRoot(@NonNull Controller controller, String tag) {
|
||||
setRoot(controller, tag, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the root {@link Controller}. If any {@link Controller}s are currently in the backstack, they will be removed.
|
||||
*
|
||||
* @param controller The new root {@link Controller}
|
||||
* @param changeHandler The {@link ControllerChangeHandler} to use for setting the root
|
||||
*/
|
||||
public void setRoot(@NonNull Controller controller, ControllerChangeHandler changeHandler) {
|
||||
setRoot(controller, null, changeHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the root Controller. If any {@link Controller}s are currently in the backstack, they will be removed.
|
||||
*
|
||||
* @param controller The new root {@link Controller}
|
||||
* @param tag The tag to use for this {@link Controller}
|
||||
* @param changeHandler The {@link ControllerChangeHandler} to use for setting the root
|
||||
* @param transaction The transaction detailing what should be pushed, including the {@link Controller},
|
||||
* and its push and pop {@link ControllerChangeHandler}, and its tag.
|
||||
*/
|
||||
public void setRoot(@NonNull Controller controller, String tag, ControllerChangeHandler changeHandler) {
|
||||
RouterTransaction currentTop = mBackStack.peek();
|
||||
public void setRoot(@NonNull RouterTransaction transaction) {
|
||||
RouterTransaction currentTop = backStack.peek();
|
||||
removeAllExceptTopAndUnowned();
|
||||
|
||||
if (currentTop != null && currentTop.controller.getView() != null) {
|
||||
final View fromView = currentTop.controller.getView();
|
||||
|
||||
final int childCount = mContainer.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
final View child = mContainer.getChildAt(i);
|
||||
if (child != fromView) {
|
||||
mContainer.removeView(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trackDestroyingControllers(mBackStack.popAll());
|
||||
|
||||
RouterTransaction transaction = RouterTransaction.builder(controller)
|
||||
.tag(tag)
|
||||
.pushChangeHandler(changeHandler != null ? changeHandler : new SimpleSwapChangeHandler())
|
||||
.popChangeHandler(new SimpleSwapChangeHandler())
|
||||
.build();
|
||||
trackDestroyingControllers(backStack.popAll());
|
||||
|
||||
pushToBackstack(transaction);
|
||||
performControllerChange(transaction, currentTop, true);
|
||||
@@ -270,11 +248,11 @@ public class Router {
|
||||
* @return The matching Controller, if one exists
|
||||
*/
|
||||
public Controller getControllerWithInstanceId(String instanceId) {
|
||||
for (ControllerTransaction transaction : mBackStack) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
Controller controllerWithId = transaction.controller.findController(instanceId);
|
||||
if (controllerWithId != null) {
|
||||
return controllerWithId;
|
||||
}
|
||||
if (controllerWithId != null) {
|
||||
return controllerWithId;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -286,8 +264,8 @@ public class Router {
|
||||
* @return The matching Controller, if one exists
|
||||
*/
|
||||
public Controller getControllerWithTag(String tag) {
|
||||
for (ControllerTransaction transaction : mBackStack) {
|
||||
if (tag.equals(transaction.tag)) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
if (tag.equals(transaction.tag())) {
|
||||
return transaction.controller;
|
||||
}
|
||||
}
|
||||
@@ -298,7 +276,47 @@ public class Router {
|
||||
* Returns the number of {@link Controller}s currently in the backstack
|
||||
*/
|
||||
public int getBackstackSize() {
|
||||
return mBackStack.size();
|
||||
return backStack.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current backstack, ordered from root to most recently pushed.
|
||||
*/
|
||||
public List<RouterTransaction> getBackstack() {
|
||||
List<RouterTransaction> list = new ArrayList<>();
|
||||
Iterator<RouterTransaction> backstackIterator = backStack.reverseIterator();
|
||||
while (backstackIterator.hasNext()) {
|
||||
list.add(backstackIterator.next());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the backstack, transitioning from the current top controller to the top of the new stack (if different)
|
||||
* using the passed {@link ControllerChangeHandler}
|
||||
*
|
||||
* @param backstack The new backstack
|
||||
* @param changeHandler An optional change handler to be used to handle the transition
|
||||
*/
|
||||
public void setBackstack(@NonNull List<RouterTransaction> backstack, ControllerChangeHandler changeHandler) {
|
||||
RouterTransaction oldTopTransaction = backStack.peek();
|
||||
Controller oldTop = oldTopTransaction != null ? oldTopTransaction.controller : null;
|
||||
removeAllExceptTopAndUnowned();
|
||||
|
||||
if (backstack.size() > 0) {
|
||||
Controller newTop = backstack.get(backstack.size() - 1).controller;
|
||||
|
||||
if (newTop != oldTop) {
|
||||
ControllerChangeHandler handler = changeHandler != null ? changeHandler : new SimpleSwapChangeHandler();
|
||||
performControllerChange(newTop, oldTop, true, handler);
|
||||
}
|
||||
}
|
||||
|
||||
for (RouterTransaction transaction : backstack) {
|
||||
transaction.onAttachedToRouter();
|
||||
}
|
||||
|
||||
backStack.setBackstack(backstack);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,8 +332,8 @@ public class Router {
|
||||
* @param changeListener The listener
|
||||
*/
|
||||
public void addChangeListener(ControllerChangeListener changeListener) {
|
||||
if (!mChangeListeners.contains(changeListener)) {
|
||||
mChangeListeners.add(changeListener);
|
||||
if (!changeListeners.contains(changeListener)) {
|
||||
changeListeners.add(changeListener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,14 +343,14 @@ public class Router {
|
||||
* @param changeListener The listener to be removed
|
||||
*/
|
||||
public void removeChangeListener(ControllerChangeListener changeListener) {
|
||||
mChangeListeners.remove(changeListener);
|
||||
changeListeners.remove(changeListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches this Router's existing backstack to its container if one exists.
|
||||
*/
|
||||
void rebindIfNeeded() {
|
||||
Iterator<RouterTransaction> backstackIterator = mBackStack.reverseIterator();
|
||||
public void rebindIfNeeded() {
|
||||
Iterator<RouterTransaction> backstackIterator = backStack.reverseIterator();
|
||||
while (backstackIterator.hasNext()) {
|
||||
RouterTransaction transaction = backstackIterator.next();
|
||||
|
||||
@@ -350,124 +368,164 @@ public class Router {
|
||||
}
|
||||
|
||||
public final void onActivityStarted(Activity activity) {
|
||||
for (RouterTransaction transaction : mBackStack) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
transaction.controller.activityStarted(activity);
|
||||
|
||||
for (Router childRouter : transaction.controller.getChildRouters()) {
|
||||
childRouter.onActivityStarted(activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void onActivityResumed(Activity activity) {
|
||||
for (RouterTransaction transaction : mBackStack) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
transaction.controller.activityResumed(activity);
|
||||
|
||||
for (Router childRouter : transaction.controller.getChildRouters()) {
|
||||
childRouter.onActivityResumed(activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void onActivityPaused(Activity activity) {
|
||||
for (RouterTransaction transaction : mBackStack) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
transaction.controller.activityPaused(activity);
|
||||
|
||||
for (Router childRouter : transaction.controller.getChildRouters()) {
|
||||
childRouter.onActivityPaused(activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void onActivityStopped(Activity activity) {
|
||||
for (RouterTransaction transaction : mBackStack) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
transaction.controller.activityStopped(activity);
|
||||
|
||||
for (Router childRouter : transaction.controller.getChildRouters()) {
|
||||
childRouter.onActivityStopped(activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
for (RouterTransaction transaction : mBackStack) {
|
||||
transaction.controller.prepareForActivityPause();
|
||||
}
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
prepareForContainerRemoval();
|
||||
changeListeners.clear();
|
||||
|
||||
mBackStack.detachAndSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
public final void onActivityDestroyed(Activity activity) {
|
||||
mContainer.setOnHierarchyChangeListener(null);
|
||||
mChangeListeners.clear();
|
||||
|
||||
for (RouterTransaction transaction : mBackStack) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
transaction.controller.activityDestroyed(activity.isChangingConfigurations());
|
||||
|
||||
for (Router childRouter : transaction.controller.getChildRouters()) {
|
||||
childRouter.onActivityDestroyed(activity);
|
||||
}
|
||||
}
|
||||
|
||||
for (Controller controller : mDestroyingControllers) {
|
||||
for (int index = destroyingControllers.size() - 1; index >= 0; index--) {
|
||||
Controller controller = destroyingControllers.get(index);
|
||||
controller.activityDestroyed(activity.isChangingConfigurations());
|
||||
|
||||
for (Router childRouter : controller.getChildRouters()) {
|
||||
childRouter.onActivityDestroyed(activity);
|
||||
}
|
||||
}
|
||||
|
||||
mLifecycleHandler = null;
|
||||
mContainer = null;
|
||||
container = null;
|
||||
}
|
||||
|
||||
public final void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
mBackStack.restoreInstanceState(savedInstanceState);
|
||||
public void prepareForHostDetach() {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
transaction.controller.prepareForHostDetach();
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<RouterTransaction> backstackIterator = mBackStack.reverseIterator();
|
||||
public void saveInstanceState(Bundle outState) {
|
||||
prepareForHostDetach();
|
||||
|
||||
Bundle backstackState = new Bundle();
|
||||
backStack.saveInstanceState(backstackState);
|
||||
|
||||
outState.putParcelable(KEY_BACKSTACK, backstackState);
|
||||
outState.putBoolean(KEY_POPS_LAST_VIEW, popsLastView);
|
||||
}
|
||||
|
||||
public void restoreInstanceState(Bundle savedInstanceState) {
|
||||
Bundle backstackBundle = savedInstanceState.getParcelable(KEY_BACKSTACK);
|
||||
backStack.restoreInstanceState(backstackBundle);
|
||||
popsLastView = savedInstanceState.getBoolean(KEY_POPS_LAST_VIEW);
|
||||
|
||||
Iterator<RouterTransaction> backstackIterator = backStack.reverseIterator();
|
||||
while (backstackIterator.hasNext()) {
|
||||
backstackIterator.next().controller.setRouter(this);
|
||||
setControllerRouter(backstackIterator.next().controller);
|
||||
}
|
||||
}
|
||||
|
||||
public final void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
for (RouterTransaction transaction : mBackStack) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
transaction.controller.createOptionsMenu(menu, inflater);
|
||||
|
||||
for (Router childRouter : transaction.controller.getChildRouters()) {
|
||||
childRouter.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void onPrepareOptionsMenu(Menu menu) {
|
||||
for (RouterTransaction transaction : mBackStack) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
transaction.controller.prepareOptionsMenu(menu);
|
||||
|
||||
for (Router childRouter : transaction.controller.getChildRouters()) {
|
||||
childRouter.onPrepareOptionsMenu(menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean onOptionsItemSelected(MenuItem item) {
|
||||
for (RouterTransaction transaction : mBackStack) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
if (transaction.controller.optionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (Router childRouter : transaction.controller.getChildRouters()) {
|
||||
if (childRouter.onOptionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
final void invalidateOptionsMenu() {
|
||||
if (mLifecycleHandler != null) {
|
||||
mLifecycleHandler.getFragmentManager().invalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
||||
private void popToTransaction(@NonNull RouterTransaction transaction, ControllerChangeHandler changeHandler) {
|
||||
RouterTransaction topTransaction = mBackStack.peek();
|
||||
List<RouterTransaction> poppedTransactions = mBackStack.popTo(transaction);
|
||||
RouterTransaction topTransaction = backStack.peek();
|
||||
List<RouterTransaction> poppedTransactions = backStack.popTo(transaction);
|
||||
trackDestroyingControllers(poppedTransactions);
|
||||
|
||||
if (poppedTransactions.size() > 0) {
|
||||
if (changeHandler == null) {
|
||||
changeHandler = topTransaction.getPopControllerChangeHandler();
|
||||
changeHandler = topTransaction.popChangeHandler();
|
||||
}
|
||||
|
||||
performControllerChange(mBackStack.peek().controller, topTransaction.controller, false, changeHandler);
|
||||
performControllerChange(backStack.peek().controller, topTransaction.controller, false, changeHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public final void setHost(@NonNull LifecycleHandler lifecycleHandler, @NonNull ViewGroup container) {
|
||||
if (mLifecycleHandler != lifecycleHandler || mContainer != container) {
|
||||
if (mContainer != null && mContainer instanceof ControllerChangeListener) {
|
||||
removeChangeListener((ControllerChangeListener)mContainer);
|
||||
}
|
||||
|
||||
if (container instanceof ControllerChangeListener) {
|
||||
addChangeListener((ControllerChangeListener)container);
|
||||
}
|
||||
|
||||
mLifecycleHandler = lifecycleHandler;
|
||||
mContainer = container;
|
||||
void prepareForContainerRemoval() {
|
||||
if (container != null) {
|
||||
container.setOnHierarchyChangeListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
final LifecycleHandler getLifecycleHandler() {
|
||||
return mLifecycleHandler;
|
||||
final List<Controller> getControllers() {
|
||||
List<Controller> controllers = new ArrayList<>();
|
||||
|
||||
Iterator<RouterTransaction> backstackIterator = backStack.reverseIterator();
|
||||
while (backstackIterator.hasNext()) {
|
||||
controllers.add(backstackIterator.next().controller);
|
||||
}
|
||||
|
||||
return controllers;
|
||||
}
|
||||
|
||||
public final Boolean handleRequestedPermission(@NonNull String permission) {
|
||||
for (ControllerTransaction transaction : mBackStack) {
|
||||
for (RouterTransaction transaction : backStack) {
|
||||
if (transaction.controller.didRequestPermission(permission)) {
|
||||
return transaction.controller.shouldShowRequestPermissionRationale(permission);
|
||||
}
|
||||
@@ -476,12 +534,16 @@ public class Router {
|
||||
}
|
||||
|
||||
private void performControllerChange(RouterTransaction to, RouterTransaction from, boolean isPush) {
|
||||
if (isPush && to != null) {
|
||||
to.onAttachedToRouter();
|
||||
}
|
||||
|
||||
ControllerChangeHandler changeHandler;
|
||||
if (isPush) {
|
||||
//noinspection ConstantConditions
|
||||
changeHandler = to.getPushControllerChangeHandler();
|
||||
changeHandler = to.pushChangeHandler();
|
||||
} else if (from != null) {
|
||||
changeHandler = from.getPopControllerChangeHandler();
|
||||
changeHandler = from.popChangeHandler();
|
||||
} else {
|
||||
changeHandler = new SimpleSwapChangeHandler();
|
||||
}
|
||||
@@ -494,31 +556,28 @@ public class Router {
|
||||
|
||||
private void performControllerChange(final Controller to, final Controller from, boolean isPush, @NonNull ControllerChangeHandler changeHandler) {
|
||||
if (to != null) {
|
||||
to.setRouter(this);
|
||||
} else if (mBackStack.size() == 0) {
|
||||
setControllerRouter(to);
|
||||
} else if (backStack.size() == 0 && !popsLastView) {
|
||||
// We're emptying out the backstack. Views get weird if you transition them out, so just no-op it. The hosting
|
||||
// Activity should be handling this by finishing or at least hiding this view.
|
||||
changeHandler = new NoOpControllerChangeHandler();
|
||||
}
|
||||
|
||||
if (mContainer != null) {
|
||||
ControllerChangeHandler.executeChange(to, from, isPush, mContainer, changeHandler, mChangeListeners);
|
||||
}
|
||||
|
||||
ControllerChangeHandler.executeChange(to, from, isPush, container, changeHandler, changeListeners);
|
||||
}
|
||||
|
||||
private void pushToBackstack(@NonNull RouterTransaction entry) {
|
||||
mBackStack.push(entry);
|
||||
void pushToBackstack(@NonNull RouterTransaction entry) {
|
||||
backStack.push(entry);
|
||||
}
|
||||
|
||||
private void trackDestroyingController(RouterTransaction transaction) {
|
||||
if (!transaction.controller.isDestroyed()) {
|
||||
mDestroyingControllers.add(transaction.controller);
|
||||
destroyingControllers.add(transaction.controller);
|
||||
|
||||
transaction.controller.addLifecycleListener(new LifecycleListener() {
|
||||
@Override
|
||||
public void postDestroy(@NonNull Controller controller) {
|
||||
mDestroyingControllers.remove(controller);
|
||||
destroyingControllers.remove(controller);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -530,4 +589,53 @@ public class Router {
|
||||
}
|
||||
}
|
||||
|
||||
private void removeAllExceptTopAndUnowned() {
|
||||
List<View> views = new ArrayList<>();
|
||||
|
||||
RouterTransaction topTransaction = backStack.peek();
|
||||
final View topView = topTransaction != null ? topTransaction.controller.getView() : null;
|
||||
if (topView != null) {
|
||||
views.add(topView);
|
||||
}
|
||||
|
||||
for (Router router : getSiblingRouters()) {
|
||||
if (router.container == container) {
|
||||
addRouterViewsToList(router, views);
|
||||
}
|
||||
}
|
||||
|
||||
final int childCount = container.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
final View child = container.getChildAt(i);
|
||||
if (!views.contains(child)) {
|
||||
container.removeView(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addRouterViewsToList(Router router, List<View> list) {
|
||||
for (Controller controller : router.getControllers()) {
|
||||
if (controller.getView() != null) {
|
||||
list.add(controller.getView());
|
||||
}
|
||||
|
||||
for (Router child : controller.getChildRouters()) {
|
||||
addRouterViewsToList(child, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setControllerRouter(Controller controller) {
|
||||
controller.setRouter(this);
|
||||
}
|
||||
|
||||
abstract void invalidateOptionsMenu();
|
||||
abstract void startActivity(Intent intent);
|
||||
abstract void startActivityForResult(String instanceId, Intent intent, int requestCode);
|
||||
abstract void startActivityForResult(String instanceId, Intent intent, int requestCode, Bundle options);
|
||||
abstract void registerForActivityResult(String instanceId, int requestCode);
|
||||
abstract void unregisterForActivityResults(String instanceId);
|
||||
abstract void requestPermissions(String instanceId, String[] permissions, int requestCode);
|
||||
abstract boolean hasHost();
|
||||
abstract List<Router> getSiblingRouters();
|
||||
}
|
||||
|
||||
@@ -4,41 +4,113 @@ import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* A {@link ControllerTransaction} implementation used for adding {@link Controller}s to a {@link Router}.
|
||||
* Metadata used for adding {@link Controller}s to a {@link Router}.
|
||||
*/
|
||||
public class RouterTransaction extends ControllerTransaction {
|
||||
public class RouterTransaction {
|
||||
|
||||
private RouterTransaction(Builder builder) {
|
||||
super(builder);
|
||||
private static final String KEY_VIEW_CONTROLLER_BUNDLE = "RouterTransaction.controller.bundle";
|
||||
private static final String KEY_PUSH_TRANSITION = "RouterTransaction.pushControllerChangeHandler";
|
||||
private static final String KEY_POP_TRANSITION = "RouterTransaction.popControllerChangeHandler";
|
||||
private static final String KEY_TAG = "RouterTransaction.tag";
|
||||
private static final String KEY_ATTACHED_TO_ROUTER = "RouterTransaction.attachedToRouter";
|
||||
|
||||
@NonNull final Controller controller;
|
||||
private String tag;
|
||||
|
||||
private ControllerChangeHandler pushControllerChangeHandler;
|
||||
private ControllerChangeHandler popControllerChangeHandler;
|
||||
private boolean attachedToRouter;
|
||||
|
||||
public static RouterTransaction with(@NonNull Controller controller) {
|
||||
return new RouterTransaction(controller);
|
||||
}
|
||||
|
||||
private RouterTransaction(@NonNull Controller controller) {
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
RouterTransaction(@NonNull Bundle bundle) {
|
||||
super(bundle);
|
||||
controller = Controller.newInstance(bundle.getBundle(KEY_VIEW_CONTROLLER_BUNDLE));
|
||||
pushControllerChangeHandler = ControllerChangeHandler.fromBundle(bundle.getBundle(KEY_PUSH_TRANSITION));
|
||||
popControllerChangeHandler = ControllerChangeHandler.fromBundle(bundle.getBundle(KEY_POP_TRANSITION));
|
||||
tag = bundle.getString(KEY_TAG);
|
||||
attachedToRouter = bundle.getBoolean(KEY_ATTACHED_TO_ROUTER);
|
||||
}
|
||||
|
||||
void onAttachedToRouter() {
|
||||
attachedToRouter = true;
|
||||
}
|
||||
|
||||
public Controller controller() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
public String tag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public RouterTransaction tag(String tag) {
|
||||
if (!attachedToRouter) {
|
||||
this.tag = tag;
|
||||
return this;
|
||||
} else {
|
||||
throw new RuntimeException(getClass().getSimpleName() + "s can not be modified after being added to a Router.");
|
||||
}
|
||||
}
|
||||
|
||||
public ControllerChangeHandler pushChangeHandler() {
|
||||
ControllerChangeHandler handler = controller.getOverriddenPushHandler();
|
||||
if (handler == null) {
|
||||
handler = pushControllerChangeHandler;
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
public RouterTransaction pushChangeHandler(ControllerChangeHandler handler) {
|
||||
if (!attachedToRouter) {
|
||||
pushControllerChangeHandler = handler;
|
||||
return this;
|
||||
} else {
|
||||
throw new RuntimeException(getClass().getSimpleName() + "s can not be modified after being added to a Router.");
|
||||
}
|
||||
}
|
||||
|
||||
public ControllerChangeHandler popChangeHandler() {
|
||||
ControllerChangeHandler handler = controller.getOverriddenPopHandler();
|
||||
if (handler == null) {
|
||||
handler = popControllerChangeHandler;
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
public RouterTransaction popChangeHandler(ControllerChangeHandler handler) {
|
||||
if (!attachedToRouter) {
|
||||
popControllerChangeHandler = handler;
|
||||
return this;
|
||||
} else {
|
||||
throw new RuntimeException(getClass().getSimpleName() + "s can not be modified after being added to a Router.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Builder
|
||||
*
|
||||
* @param controller The {@link Controller} to add to the {@link Router}
|
||||
* Used to serialize this transaction into a Bundle
|
||||
*/
|
||||
public static Builder builder(@NonNull Controller controller) {
|
||||
return new Builder(controller);
|
||||
}
|
||||
public Bundle saveInstanceState() {
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
/**
|
||||
* A {@link ControllerTransaction.Builder} implementation used for adding {@link Controller}s to a {@link Router}.
|
||||
*/
|
||||
public static class Builder extends ControllerTransaction.Builder<Builder> {
|
||||
bundle.putBundle(KEY_VIEW_CONTROLLER_BUNDLE, controller.saveInstanceState());
|
||||
|
||||
Builder(@NonNull Controller controller) {
|
||||
super(controller);
|
||||
if (pushControllerChangeHandler != null) {
|
||||
bundle.putBundle(KEY_PUSH_TRANSITION, pushControllerChangeHandler.toBundle());
|
||||
}
|
||||
if (popControllerChangeHandler != null) {
|
||||
bundle.putBundle(KEY_POP_TRANSITION, popControllerChangeHandler.toBundle());
|
||||
}
|
||||
|
||||
/** Creates the transaction */
|
||||
public RouterTransaction build() {
|
||||
return new RouterTransaction(this);
|
||||
}
|
||||
bundle.putString(KEY_TAG, tag);
|
||||
bundle.putBoolean(KEY_ATTACHED_TO_ROUTER, attachedToRouter);
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
}
|
||||
+33
-15
@@ -8,6 +8,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
|
||||
/**
|
||||
@@ -20,8 +21,10 @@ public abstract class AnimatorChangeHandler extends ControllerChangeHandler {
|
||||
|
||||
public static final long DEFAULT_ANIMATION_DURATION = -1;
|
||||
|
||||
private long mAnimationDuration;
|
||||
private boolean mRemovesFromViewOnPush;
|
||||
private long animationDuration;
|
||||
private boolean removesFromViewOnPush;
|
||||
private boolean canceled;
|
||||
private Animator animator;
|
||||
|
||||
public AnimatorChangeHandler() {
|
||||
this(DEFAULT_ANIMATION_DURATION, true);
|
||||
@@ -36,30 +39,40 @@ public abstract class AnimatorChangeHandler extends ControllerChangeHandler {
|
||||
}
|
||||
|
||||
public AnimatorChangeHandler(long duration, boolean removesFromViewOnPush) {
|
||||
mAnimationDuration = duration;
|
||||
mRemovesFromViewOnPush = removesFromViewOnPush;
|
||||
animationDuration = duration;
|
||||
this.removesFromViewOnPush = removesFromViewOnPush;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveToBundle(@NonNull Bundle bundle) {
|
||||
super.saveToBundle(bundle);
|
||||
bundle.putLong(KEY_DURATION, mAnimationDuration);
|
||||
bundle.putBoolean(KEY_REMOVES_FROM_ON_PUSH, mRemovesFromViewOnPush);
|
||||
bundle.putLong(KEY_DURATION, animationDuration);
|
||||
bundle.putBoolean(KEY_REMOVES_FROM_ON_PUSH, removesFromViewOnPush);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle(@NonNull Bundle bundle) {
|
||||
super.restoreFromBundle(bundle);
|
||||
mAnimationDuration = bundle.getLong(KEY_DURATION);
|
||||
mRemovesFromViewOnPush = bundle.getBoolean(KEY_REMOVES_FROM_ON_PUSH);
|
||||
animationDuration = bundle.getLong(KEY_DURATION);
|
||||
removesFromViewOnPush = bundle.getBoolean(KEY_REMOVES_FROM_ON_PUSH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAbortPush(@NonNull ControllerChangeHandler newHandler, Controller newTop) {
|
||||
super.onAbortPush(newHandler, newTop);
|
||||
|
||||
canceled = true;
|
||||
if (animator != null) {
|
||||
animator.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public long getAnimationDuration() {
|
||||
return mAnimationDuration;
|
||||
return animationDuration;
|
||||
}
|
||||
|
||||
public boolean removesFromViewOnPush() {
|
||||
return mRemovesFromViewOnPush;
|
||||
return removesFromViewOnPush;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,11 +124,16 @@ public abstract class AnimatorChangeHandler extends ControllerChangeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private void performAnimation(@NonNull final ViewGroup container, final View from, View to, final boolean isPush, final boolean toAddedToContainer, @NonNull final ControllerChangeCompletedListener changeListener) {
|
||||
Animator animator = getAnimator(container, from, to, isPush, toAddedToContainer);
|
||||
private void performAnimation(@NonNull final ViewGroup container, final View from, final View to, final boolean isPush, final boolean toAddedToContainer, @NonNull final ControllerChangeCompletedListener changeListener) {
|
||||
if (canceled) {
|
||||
changeListener.onChangeCompleted();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAnimationDuration > 0) {
|
||||
animator.setDuration(mAnimationDuration);
|
||||
animator = getAnimator(container, from, to, isPush, toAddedToContainer);
|
||||
|
||||
if (animationDuration > 0) {
|
||||
animator.setDuration(animationDuration);
|
||||
}
|
||||
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@@ -126,7 +144,7 @@ public abstract class AnimatorChangeHandler extends ControllerChangeHandler {
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (from != null && (!isPush || mRemovesFromViewOnPush)) {
|
||||
if (from != null && (!isPush || removesFromViewOnPush) && !canceled) {
|
||||
container.removeView(from);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -51,6 +51,6 @@ public class HorizontalChangeHandler extends AnimatorChangeHandler {
|
||||
|
||||
@Override
|
||||
protected void resetFromView(@NonNull View from) {
|
||||
from.setTranslationY(0);
|
||||
from.setTranslationX(0);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -14,31 +14,31 @@ public class SimpleSwapChangeHandler extends ControllerChangeHandler {
|
||||
|
||||
private static final String KEY_REMOVES_FROM_ON_PUSH = "SimpleSwapChangeHandler.removesFromViewOnPush";
|
||||
|
||||
private boolean mRemovesFromViewOnPush;
|
||||
private boolean removesFromViewOnPush;
|
||||
|
||||
public SimpleSwapChangeHandler() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
public SimpleSwapChangeHandler(boolean removesFromViewOnPush) {
|
||||
mRemovesFromViewOnPush = removesFromViewOnPush;
|
||||
this.removesFromViewOnPush = removesFromViewOnPush;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveToBundle(@NonNull Bundle bundle) {
|
||||
super.saveToBundle(bundle);
|
||||
bundle.putBoolean(KEY_REMOVES_FROM_ON_PUSH, mRemovesFromViewOnPush);
|
||||
bundle.putBoolean(KEY_REMOVES_FROM_ON_PUSH, removesFromViewOnPush);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle(@NonNull Bundle bundle) {
|
||||
super.restoreFromBundle(bundle);
|
||||
mRemovesFromViewOnPush = bundle.getBoolean(KEY_REMOVES_FROM_ON_PUSH);
|
||||
removesFromViewOnPush = bundle.getBoolean(KEY_REMOVES_FROM_ON_PUSH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull final ControllerChangeCompletedListener changeListener) {
|
||||
if (from != null && (!isPush || mRemovesFromViewOnPush)) {
|
||||
if (from != null && (!isPush || removesFromViewOnPush)) {
|
||||
container.removeView(from);
|
||||
}
|
||||
|
||||
|
||||
+15
@@ -9,6 +9,7 @@ import android.transition.TransitionManager;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
|
||||
/**
|
||||
@@ -17,6 +18,8 @@ import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public abstract class TransitionChangeHandler extends ControllerChangeHandler {
|
||||
|
||||
private boolean canceled;
|
||||
|
||||
/**
|
||||
* Should be overridden to return the Transition to use while replacing Views.
|
||||
*
|
||||
@@ -28,8 +31,20 @@ public abstract class TransitionChangeHandler extends ControllerChangeHandler {
|
||||
@NonNull
|
||||
protected abstract Transition getTransition(@NonNull ViewGroup container, View from, View to, boolean isPush);
|
||||
|
||||
@Override
|
||||
public void onAbortPush(@NonNull ControllerChangeHandler newHandler, Controller newTop) {
|
||||
super.onAbortPush(newHandler, newTop);
|
||||
|
||||
canceled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performChange(@NonNull final ViewGroup container, View from, View to, boolean isPush, @NonNull final ControllerChangeCompletedListener changeListener) {
|
||||
if (canceled) {
|
||||
changeListener.onChangeCompleted();
|
||||
return;
|
||||
}
|
||||
|
||||
Transition transition = getTransition(container, from, to, isPush);
|
||||
transition.addListener(new TransitionListener() {
|
||||
@Override
|
||||
|
||||
+14
-14
@@ -20,8 +20,8 @@ public class TransitionChangeHandlerCompat extends ControllerChangeHandler {
|
||||
private static final String KEY_TRANSITION_HANDLER_STATE = "TransitionChangeHandlerCompat.transitionChangeHandler.state";
|
||||
private static final String KEY_FALLBACK_HANDLER_STATE = "TransitionChangeHandlerCompat.fallbackChangeHandler.state";
|
||||
|
||||
private TransitionChangeHandler mTransitionChangeHandler;
|
||||
private ControllerChangeHandler mFallbackChangeHandler;
|
||||
private TransitionChangeHandler transitionChangeHandler;
|
||||
private ControllerChangeHandler fallbackChangeHandler;
|
||||
|
||||
public TransitionChangeHandlerCompat() { }
|
||||
|
||||
@@ -33,16 +33,16 @@ public class TransitionChangeHandlerCompat extends ControllerChangeHandler {
|
||||
* @param fallbackChangeHandler The change handler that will be used on APIs below 21
|
||||
*/
|
||||
public TransitionChangeHandlerCompat(TransitionChangeHandler transitionChangeHandler, ControllerChangeHandler fallbackChangeHandler) {
|
||||
mTransitionChangeHandler = transitionChangeHandler;
|
||||
mFallbackChangeHandler = fallbackChangeHandler;
|
||||
this.transitionChangeHandler = transitionChangeHandler;
|
||||
this.fallbackChangeHandler = fallbackChangeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performChange(@NonNull final ViewGroup container, View from, View to, boolean isPush, @NonNull final ControllerChangeCompletedListener changeListener) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
mTransitionChangeHandler.performChange(container, from, to, isPush, changeListener);
|
||||
transitionChangeHandler.performChange(container, from, to, isPush, changeListener);
|
||||
} else {
|
||||
mFallbackChangeHandler.performChange(container, from, to, isPush, changeListener);
|
||||
fallbackChangeHandler.performChange(container, from, to, isPush, changeListener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,15 +50,15 @@ public class TransitionChangeHandlerCompat extends ControllerChangeHandler {
|
||||
public void saveToBundle(@NonNull Bundle bundle) {
|
||||
super.saveToBundle(bundle);
|
||||
|
||||
bundle.putString(KEY_TRANSITION_HANDLER_CLASS, mTransitionChangeHandler.getClass().getName());
|
||||
bundle.putString(KEY_FALLBACK_HANDLER_CLASS, mFallbackChangeHandler.getClass().getName());
|
||||
bundle.putString(KEY_TRANSITION_HANDLER_CLASS, transitionChangeHandler.getClass().getName());
|
||||
bundle.putString(KEY_FALLBACK_HANDLER_CLASS, fallbackChangeHandler.getClass().getName());
|
||||
|
||||
Bundle transitionBundle = new Bundle();
|
||||
mTransitionChangeHandler.saveToBundle(transitionBundle);
|
||||
transitionChangeHandler.saveToBundle(transitionBundle);
|
||||
bundle.putBundle(KEY_TRANSITION_HANDLER_STATE, transitionBundle);
|
||||
|
||||
Bundle fallbackBundle = new Bundle();
|
||||
mFallbackChangeHandler.saveToBundle(fallbackBundle);
|
||||
fallbackChangeHandler.saveToBundle(fallbackBundle);
|
||||
bundle.putBundle(KEY_FALLBACK_HANDLER_STATE, fallbackBundle);
|
||||
}
|
||||
|
||||
@@ -67,14 +67,14 @@ public class TransitionChangeHandlerCompat extends ControllerChangeHandler {
|
||||
super.restoreFromBundle(bundle);
|
||||
|
||||
String transitionClassName = bundle.getString(KEY_TRANSITION_HANDLER_CLASS);
|
||||
mTransitionChangeHandler = ClassUtils.newInstance(transitionClassName);
|
||||
transitionChangeHandler = ClassUtils.newInstance(transitionClassName);
|
||||
//noinspection ConstantConditions
|
||||
mTransitionChangeHandler.restoreFromBundle(bundle.getBundle(KEY_TRANSITION_HANDLER_STATE));
|
||||
transitionChangeHandler.restoreFromBundle(bundle.getBundle(KEY_TRANSITION_HANDLER_STATE));
|
||||
|
||||
String fallbackClassName = bundle.getString(KEY_FALLBACK_HANDLER_CLASS);
|
||||
mFallbackChangeHandler = ClassUtils.newInstance(fallbackClassName);
|
||||
fallbackChangeHandler = ClassUtils.newInstance(fallbackClassName);
|
||||
//noinspection ConstantConditions
|
||||
mFallbackChangeHandler.restoreFromBundle(bundle.getBundle(KEY_FALLBACK_HANDLER_STATE));
|
||||
fallbackChangeHandler.restoreFromBundle(bundle.getBundle(KEY_FALLBACK_HANDLER_STATE));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.Application.ActivityLifecycleCallbacks;
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -14,9 +15,12 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.ActivityHostedRouter;
|
||||
import com.bluelinelabs.conductor.Router;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class LifecycleHandler extends Fragment implements ActivityLifecycleCallbacks {
|
||||
@@ -26,13 +30,14 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
private static final String KEY_PERMISSION_REQUEST_CODES = "LifecycleHandler.permissionRequests";
|
||||
private static final String KEY_ACTIVITY_REQUEST_CODES = "LifecycleHandler.activityRequests";
|
||||
|
||||
private Activity mActivity;
|
||||
private boolean mHasRegisteredCallbacks;
|
||||
private Activity activity;
|
||||
private boolean hasRegisteredCallbacks;
|
||||
private boolean destroyed;
|
||||
|
||||
private SparseArray<String> mPermissionRequestMap = new SparseArray<>();
|
||||
private SparseArray<String> mActivityRequestMap = new SparseArray<>();
|
||||
private SparseArray<String> permissionRequestMap = new SparseArray<>();
|
||||
private SparseArray<String> activityRequestMap = new SparseArray<>();
|
||||
|
||||
private final Map<Integer, Router> mRouterMap = new HashMap<>();
|
||||
private final Map<Integer, ActivityHostedRouter> routerMap = new HashMap<>();
|
||||
|
||||
public LifecycleHandler() {
|
||||
setRetainInstance(true);
|
||||
@@ -58,15 +63,15 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
}
|
||||
|
||||
public Router getRouter(ViewGroup container, Bundle savedInstanceState) {
|
||||
Router router = mRouterMap.get(getRouterHashKey(container));
|
||||
ActivityHostedRouter router = routerMap.get(getRouterHashKey(container));
|
||||
if (router == null) {
|
||||
router = new Router();
|
||||
router = new ActivityHostedRouter();
|
||||
router.setHost(this, container);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
router.onRestoreInstanceState(savedInstanceState);
|
||||
router.restoreInstanceState(savedInstanceState);
|
||||
}
|
||||
mRouterMap.put(getRouterHashKey(container), router);
|
||||
routerMap.put(getRouterHashKey(container), router);
|
||||
} else {
|
||||
router.setHost(this, container);
|
||||
}
|
||||
@@ -74,8 +79,12 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
return router;
|
||||
}
|
||||
|
||||
public List<Router> getRouters() {
|
||||
return new ArrayList<Router>(routerMap.values());
|
||||
}
|
||||
|
||||
public Activity getLifecycleActivity() {
|
||||
return mActivity;
|
||||
return activity;
|
||||
}
|
||||
|
||||
private static int getRouterHashKey(ViewGroup viewGroup) {
|
||||
@@ -83,10 +92,10 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
}
|
||||
|
||||
private void registerActivityListener(Activity activity) {
|
||||
mActivity = activity;
|
||||
this.activity = activity;
|
||||
|
||||
if (!mHasRegisteredCallbacks) {
|
||||
mHasRegisteredCallbacks = true;
|
||||
if (!hasRegisteredCallbacks) {
|
||||
hasRegisteredCallbacks = true;
|
||||
activity.getApplication().registerActivityLifecycleCallbacks(this);
|
||||
}
|
||||
}
|
||||
@@ -97,10 +106,10 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
StringSparseArrayParceler permissionParcel = savedInstanceState.getParcelable(KEY_PERMISSION_REQUEST_CODES);
|
||||
mPermissionRequestMap = permissionParcel != null ? permissionParcel.getStringSparseArray() : null;
|
||||
permissionRequestMap = permissionParcel != null ? permissionParcel.getStringSparseArray() : null;
|
||||
|
||||
StringSparseArrayParceler activityParcel = savedInstanceState.getParcelable(KEY_ACTIVITY_REQUEST_CODES);
|
||||
mActivityRequestMap = activityParcel != null ? activityParcel.getStringSparseArray() : null;
|
||||
activityRequestMap = activityParcel != null ? activityParcel.getStringSparseArray() : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,22 +117,50 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putParcelable(KEY_PERMISSION_REQUEST_CODES, new StringSparseArrayParceler(mPermissionRequestMap));
|
||||
outState.putParcelable(KEY_ACTIVITY_REQUEST_CODES, new StringSparseArrayParceler(mActivityRequestMap));
|
||||
outState.putParcelable(KEY_PERMISSION_REQUEST_CODES, new StringSparseArrayParceler(permissionRequestMap));
|
||||
outState.putParcelable(KEY_ACTIVITY_REQUEST_CODES, new StringSparseArrayParceler(activityRequestMap));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
if (mActivity != null) {
|
||||
mActivity.getApplication().unregisterActivityLifecycleCallbacks(this);
|
||||
if (activity != null) {
|
||||
activity.getApplication().unregisterActivityLifecycleCallbacks(this);
|
||||
destroyRouters();
|
||||
activity = null;
|
||||
}
|
||||
}
|
||||
|
||||
for (Router router : mRouterMap.values()) {
|
||||
router.onActivityDestroyed(mActivity);
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
destroyed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
destroyed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
|
||||
destroyRouters();
|
||||
}
|
||||
|
||||
private void destroyRouters() {
|
||||
if (!destroyed) {
|
||||
destroyed = true;
|
||||
|
||||
if (activity != null) {
|
||||
for (Router router : routerMap.values()) {
|
||||
router.onActivityDestroyed(activity);
|
||||
}
|
||||
}
|
||||
|
||||
mActivity = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,9 +168,9 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
String instanceId = mActivityRequestMap.get(requestCode);
|
||||
String instanceId = activityRequestMap.get(requestCode);
|
||||
if (instanceId != null) {
|
||||
for (Router router : mRouterMap.values()) {
|
||||
for (Router router : routerMap.values()) {
|
||||
router.onActivityResult(instanceId, requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
@@ -143,9 +180,9 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
String instanceId = mPermissionRequestMap.get(requestCode);
|
||||
String instanceId = permissionRequestMap.get(requestCode);
|
||||
if (instanceId != null) {
|
||||
for (Router router : mRouterMap.values()) {
|
||||
for (Router router : routerMap.values()) {
|
||||
router.onRequestPermissionsResult(instanceId, requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
@@ -153,7 +190,7 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
|
||||
@Override
|
||||
public boolean shouldShowRequestPermissionRationale(@NonNull String permission) {
|
||||
for (Router router : mRouterMap.values()) {
|
||||
for (Router router : routerMap.values()) {
|
||||
Boolean handled = router.handleRequestedPermission(permission);
|
||||
if (handled != null) {
|
||||
return handled;
|
||||
@@ -166,7 +203,7 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
||||
for (Router router : mRouterMap.values()) {
|
||||
for (Router router : routerMap.values()) {
|
||||
router.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
}
|
||||
@@ -175,14 +212,14 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
|
||||
for (Router router : mRouterMap.values()) {
|
||||
for (Router router : routerMap.values()) {
|
||||
router.onPrepareOptionsMenu(menu);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
for (Router router : mRouterMap.values()) {
|
||||
for (Router router : routerMap.values()) {
|
||||
if (router.onOptionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
@@ -191,45 +228,45 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
public void registerForActivityRequest(String instanceId, int requestCode) {
|
||||
mActivityRequestMap.put(requestCode, instanceId);
|
||||
public void registerForActivityResult(String instanceId, int requestCode) {
|
||||
activityRequestMap.put(requestCode, instanceId);
|
||||
}
|
||||
|
||||
public void unregisterForActivityRequests(String instanceId) {
|
||||
for (int i = mActivityRequestMap.size() - 1; i >= 0; i--) {
|
||||
if (instanceId.equals(mActivityRequestMap.get(mActivityRequestMap.keyAt(i)))) {
|
||||
mActivityRequestMap.removeAt(i);
|
||||
public void unregisterForActivityResults(String instanceId) {
|
||||
for (int i = activityRequestMap.size() - 1; i >= 0; i--) {
|
||||
if (instanceId.equals(activityRequestMap.get(activityRequestMap.keyAt(i)))) {
|
||||
activityRequestMap.removeAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void startActivityForResult(String instanceId, Intent intent, int requestCode) {
|
||||
registerForActivityRequest(instanceId, requestCode);
|
||||
registerForActivityResult(instanceId, requestCode);
|
||||
startActivityForResult(intent, requestCode);
|
||||
}
|
||||
|
||||
public void startActivityForResult(String instanceId, Intent intent, int requestCode, Bundle options) {
|
||||
registerForActivityRequest(instanceId, requestCode);
|
||||
registerForActivityResult(instanceId, requestCode);
|
||||
startActivityForResult(intent, requestCode, options);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
public void requestPermissions(String instanceId, String[] permissions, int requestCode) {
|
||||
mPermissionRequestMap.put(requestCode, instanceId);
|
||||
permissionRequestMap.put(requestCode, instanceId);
|
||||
requestPermissions(permissions, requestCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
if (mActivity == null && findInActivity(activity) == LifecycleHandler.this) {
|
||||
mActivity = activity;
|
||||
if (this.activity == null && findInActivity(activity) == LifecycleHandler.this) {
|
||||
this.activity = activity;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(Activity activity) {
|
||||
if (mActivity == activity) {
|
||||
for (Router router : mRouterMap.values()) {
|
||||
if (this.activity == activity) {
|
||||
for (Router router : routerMap.values()) {
|
||||
router.onActivityStarted(activity);
|
||||
}
|
||||
}
|
||||
@@ -237,8 +274,8 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
if (mActivity == activity) {
|
||||
for (Router router : mRouterMap.values()) {
|
||||
if (this.activity == activity) {
|
||||
for (Router router : routerMap.values()) {
|
||||
router.onActivityResumed(activity);
|
||||
}
|
||||
}
|
||||
@@ -246,8 +283,8 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
if (mActivity == activity) {
|
||||
for (Router router : mRouterMap.values()) {
|
||||
if (this.activity == activity) {
|
||||
for (Router router : routerMap.values()) {
|
||||
router.onActivityPaused(activity);
|
||||
}
|
||||
}
|
||||
@@ -255,8 +292,8 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(Activity activity) {
|
||||
if (mActivity == activity) {
|
||||
for (Router router : mRouterMap.values()) {
|
||||
if (this.activity == activity) {
|
||||
for (Router router : routerMap.values()) {
|
||||
router.onActivityStopped(activity);
|
||||
}
|
||||
}
|
||||
@@ -264,9 +301,9 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
|
||||
|
||||
@Override
|
||||
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
if (mActivity == activity) {
|
||||
for (Router router : mRouterMap.values()) {
|
||||
router.onActivitySaveInstanceState(activity, outState);
|
||||
if (this.activity == activity) {
|
||||
for (Router router : routerMap.values()) {
|
||||
router.saveInstanceState(outState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -6,24 +6,24 @@ import android.util.SparseArray;
|
||||
|
||||
public class StringSparseArrayParceler implements Parcelable {
|
||||
|
||||
private final SparseArray<String> mStringSparseArray;
|
||||
private final SparseArray<String> stringSparseArray;
|
||||
|
||||
public StringSparseArrayParceler(SparseArray<String> stringSparseArray) {
|
||||
mStringSparseArray = stringSparseArray;
|
||||
this.stringSparseArray = stringSparseArray;
|
||||
}
|
||||
|
||||
private StringSparseArrayParceler(Parcel in) {
|
||||
mStringSparseArray = new SparseArray<>();
|
||||
stringSparseArray = new SparseArray<>();
|
||||
|
||||
final int size = in.readInt();
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
mStringSparseArray.put(in.readInt(), in.readString());
|
||||
stringSparseArray.put(in.readInt(), in.readString());
|
||||
}
|
||||
}
|
||||
|
||||
public SparseArray<String> getStringSparseArray() {
|
||||
return mStringSparseArray;
|
||||
return stringSparseArray;
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
@@ -31,15 +31,15 @@ public class StringSparseArrayParceler implements Parcelable {
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
final int size = mStringSparseArray.size();
|
||||
final int size = stringSparseArray.size();
|
||||
|
||||
out.writeInt(size);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
int key = mStringSparseArray.keyAt(i);
|
||||
int key = stringSparseArray.keyAt(i);
|
||||
|
||||
out.writeInt(key);
|
||||
out.writeString(mStringSparseArray.get(key));
|
||||
out.writeString(stringSparseArray.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,61 +6,61 @@ import org.junit.Test;
|
||||
|
||||
public class BackstackTests {
|
||||
|
||||
private Backstack mBackstack;
|
||||
private Backstack backstack;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mBackstack = new Backstack();
|
||||
backstack = new Backstack();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPush() {
|
||||
Assert.assertEquals(0, mBackstack.size());
|
||||
mBackstack.push(RouterTransaction.builder(new TestController()).build());
|
||||
Assert.assertEquals(1, mBackstack.size());
|
||||
Assert.assertEquals(0, backstack.size());
|
||||
backstack.push(RouterTransaction.with(new TestController()));
|
||||
Assert.assertEquals(1, backstack.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPop() {
|
||||
mBackstack.push(RouterTransaction.builder(new TestController()).build());
|
||||
mBackstack.push(RouterTransaction.builder(new TestController()).build());
|
||||
Assert.assertEquals(2, mBackstack.size());
|
||||
mBackstack.pop();
|
||||
Assert.assertEquals(1, mBackstack.size());
|
||||
mBackstack.pop();
|
||||
Assert.assertEquals(0, mBackstack.size());
|
||||
backstack.push(RouterTransaction.with(new TestController()));
|
||||
backstack.push(RouterTransaction.with(new TestController()));
|
||||
Assert.assertEquals(2, backstack.size());
|
||||
backstack.pop();
|
||||
Assert.assertEquals(1, backstack.size());
|
||||
backstack.pop();
|
||||
Assert.assertEquals(0, backstack.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPeek() {
|
||||
RouterTransaction transaction1 = RouterTransaction.builder(new TestController()).build();
|
||||
RouterTransaction transaction2 = RouterTransaction.builder(new TestController()).build();
|
||||
RouterTransaction transaction1 = RouterTransaction.with(new TestController());
|
||||
RouterTransaction transaction2 = RouterTransaction.with(new TestController());
|
||||
|
||||
mBackstack.push(transaction1);
|
||||
Assert.assertEquals(transaction1, mBackstack.peek());
|
||||
backstack.push(transaction1);
|
||||
Assert.assertEquals(transaction1, backstack.peek());
|
||||
|
||||
mBackstack.push(transaction2);
|
||||
Assert.assertEquals(transaction2, mBackstack.peek());
|
||||
backstack.push(transaction2);
|
||||
Assert.assertEquals(transaction2, backstack.peek());
|
||||
|
||||
mBackstack.pop();
|
||||
Assert.assertEquals(transaction1, mBackstack.peek());
|
||||
backstack.pop();
|
||||
Assert.assertEquals(transaction1, backstack.peek());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPopTo() {
|
||||
RouterTransaction transaction1 = RouterTransaction.builder(new TestController()).build();
|
||||
RouterTransaction transaction2 = RouterTransaction.builder(new TestController()).build();
|
||||
RouterTransaction transaction3 = RouterTransaction.builder(new TestController()).build();
|
||||
RouterTransaction transaction1 = RouterTransaction.with(new TestController());
|
||||
RouterTransaction transaction2 = RouterTransaction.with(new TestController());
|
||||
RouterTransaction transaction3 = RouterTransaction.with(new TestController());
|
||||
|
||||
mBackstack.push(transaction1);
|
||||
mBackstack.push(transaction2);
|
||||
mBackstack.push(transaction3);
|
||||
backstack.push(transaction1);
|
||||
backstack.push(transaction2);
|
||||
backstack.push(transaction3);
|
||||
|
||||
Assert.assertEquals(3, mBackstack.size());
|
||||
Assert.assertEquals(3, backstack.size());
|
||||
|
||||
mBackstack.popTo(transaction1);
|
||||
backstack.popTo(transaction1);
|
||||
|
||||
Assert.assertEquals(1, mBackstack.size());
|
||||
Assert.assertEquals(transaction1, mBackstack.peek());
|
||||
Assert.assertEquals(1, backstack.size());
|
||||
Assert.assertEquals(transaction1, backstack.peek());
|
||||
}
|
||||
}
|
||||
|
||||
+5
-6
@@ -13,14 +13,13 @@ public class ControllerChangeHandlerTests {
|
||||
HorizontalChangeHandler horizontalChangeHandler = new HorizontalChangeHandler();
|
||||
FadeChangeHandler fadeChangeHandler = new FadeChangeHandler(120, false);
|
||||
|
||||
RouterTransaction transaction = RouterTransaction.builder(new TestController())
|
||||
RouterTransaction transaction = RouterTransaction.with(new TestController())
|
||||
.pushChangeHandler(horizontalChangeHandler)
|
||||
.popChangeHandler(fadeChangeHandler)
|
||||
.build();
|
||||
RouterTransaction restoredTransaction = new RouterTransaction(transaction.detachAndSaveInstanceState());
|
||||
.popChangeHandler(fadeChangeHandler);
|
||||
RouterTransaction restoredTransaction = new RouterTransaction(transaction.saveInstanceState());
|
||||
|
||||
ControllerChangeHandler restoredHorizontal = restoredTransaction.getPushControllerChangeHandler();
|
||||
ControllerChangeHandler restoredFade = restoredTransaction.getPopControllerChangeHandler();
|
||||
ControllerChangeHandler restoredHorizontal = restoredTransaction.pushChangeHandler();
|
||||
ControllerChangeHandler restoredFade = restoredTransaction.popChangeHandler();
|
||||
|
||||
Assert.assertEquals(horizontalChangeHandler.getClass(), restoredHorizontal.getClass());
|
||||
Assert.assertEquals(fadeChangeHandler.getClass(), restoredFade.getClass());
|
||||
|
||||
@@ -9,7 +9,6 @@ import android.widget.FrameLayout;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller.LifecycleListener;
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeCompletedListener;
|
||||
import com.bluelinelabs.conductor.ControllerTransaction.ControllerChangeType;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
@@ -24,21 +23,21 @@ import org.robolectric.util.ActivityController;
|
||||
@Config(manifest = Config.NONE)
|
||||
public class ControllerLifecycleTests {
|
||||
|
||||
private ActivityController<TestActivity> mActivityController;
|
||||
private Router mRouter;
|
||||
private ActivityController<TestActivity> activityController;
|
||||
private Router router;
|
||||
|
||||
private CallState mCurrentCallState;
|
||||
private CallState currentCallState;
|
||||
|
||||
public void createActivityController(Bundle savedInstanceState) {
|
||||
mActivityController = Robolectric.buildActivity(TestActivity.class).create(savedInstanceState).start();
|
||||
activityController = Robolectric.buildActivity(TestActivity.class).create(savedInstanceState).start();
|
||||
|
||||
@IdRes int containerId = 4;
|
||||
FrameLayout routerContainer = new FrameLayout(mActivityController.get());
|
||||
FrameLayout routerContainer = new FrameLayout(activityController.get());
|
||||
routerContainer.setId(containerId);
|
||||
|
||||
mRouter = Conductor.attachRouter(mActivityController.get(), routerContainer, savedInstanceState);
|
||||
if (!mRouter.hasRootController()) {
|
||||
mRouter.setRoot(new TestController());
|
||||
router = Conductor.attachRouter(activityController.get(), routerContainer, savedInstanceState);
|
||||
if (!router.hasRootController()) {
|
||||
router.setRoot(RouterTransaction.with(new TestController()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +45,7 @@ public class ControllerLifecycleTests {
|
||||
public void setup() {
|
||||
createActivityController(null);
|
||||
|
||||
mCurrentCallState = new CallState();
|
||||
currentCallState = new CallState();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -57,15 +56,13 @@ public class ControllerLifecycleTests {
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(controller)
|
||||
router.pushController(RouterTransaction.with(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller))
|
||||
.popChangeHandler(getPopHandler(expectedCallState, controller))
|
||||
.build()
|
||||
);
|
||||
.popChangeHandler(getPopHandler(expectedCallState, controller)));
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mRouter.popCurrentController();
|
||||
router.popCurrentController();
|
||||
|
||||
Assert.assertNull(controller.getView());
|
||||
|
||||
@@ -80,22 +77,20 @@ public class ControllerLifecycleTests {
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller))
|
||||
.build()
|
||||
);
|
||||
router.pushController(RouterTransaction.with(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller)));
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.pause();
|
||||
activityController.pause();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.stop();
|
||||
activityController.stop();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.destroy();
|
||||
activityController.destroy();
|
||||
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.destroyViewCalls++;
|
||||
@@ -111,36 +106,34 @@ public class ControllerLifecycleTests {
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(controller)
|
||||
router.pushController(RouterTransaction.with(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller))
|
||||
.tag("root")
|
||||
.build()
|
||||
);
|
||||
.tag("root"));
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.get().isChangingConfigurations = true;
|
||||
activityController.get().isChangingConfigurations = true;
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
mActivityController.saveInstanceState(bundle);
|
||||
activityController.saveInstanceState(bundle);
|
||||
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.saveViewStateCalls++;
|
||||
expectedCallState.saveInstanceStateCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.pause();
|
||||
activityController.pause();
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.stop();
|
||||
activityController.stop();
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.destroy();
|
||||
activityController.destroy();
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.destroyViewCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
createActivityController(bundle);
|
||||
controller = (TestController)mRouter.getControllerWithTag("root");
|
||||
controller = (TestController)router.getControllerWithTag("root");
|
||||
|
||||
expectedCallState.restoreInstanceStateCalls++;
|
||||
expectedCallState.restoreViewStateCalls++;
|
||||
@@ -149,15 +142,15 @@ public class ControllerLifecycleTests {
|
||||
expectedCallState.createViewCalls++;
|
||||
|
||||
// Lifecycle listener isn't attached during restore, grab the current views from the controller for this stuff...
|
||||
mCurrentCallState.restoreInstanceStateCalls = controller.currentCallState.restoreInstanceStateCalls;
|
||||
mCurrentCallState.restoreViewStateCalls = controller.currentCallState.restoreViewStateCalls;
|
||||
mCurrentCallState.changeStartCalls = controller.currentCallState.changeStartCalls;
|
||||
mCurrentCallState.changeEndCalls = controller.currentCallState.changeEndCalls;
|
||||
mCurrentCallState.createViewCalls = controller.currentCallState.createViewCalls;
|
||||
currentCallState.restoreInstanceStateCalls = controller.currentCallState.restoreInstanceStateCalls;
|
||||
currentCallState.restoreViewStateCalls = controller.currentCallState.restoreViewStateCalls;
|
||||
currentCallState.changeStartCalls = controller.currentCallState.changeStartCalls;
|
||||
currentCallState.changeEndCalls = controller.currentCallState.changeEndCalls;
|
||||
currentCallState.createViewCalls = controller.currentCallState.createViewCalls;
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.resume();
|
||||
activityController.resume();
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
|
||||
@@ -169,26 +162,21 @@ public class ControllerLifecycleTests {
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller))
|
||||
.build()
|
||||
);
|
||||
router.pushController(RouterTransaction.with(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller)));
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.pause();
|
||||
activityController.pause();
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
mActivityController.saveInstanceState(bundle);
|
||||
activityController.saveInstanceState(bundle);
|
||||
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.saveInstanceStateCalls++;
|
||||
expectedCallState.saveViewStateCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.resume();
|
||||
expectedCallState.createViewCalls++;
|
||||
expectedCallState.restoreViewStateCalls++;
|
||||
activityController.resume();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -388,7 +376,7 @@ public class ControllerLifecycleTests {
|
||||
}
|
||||
});
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(testController)
|
||||
router.pushController(RouterTransaction.with(testController)
|
||||
.pushChangeHandler(new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
@@ -404,10 +392,9 @@ public class ControllerLifecycleTests {
|
||||
ViewUtils.setAttached(from, false);
|
||||
changeListener.onChangeCompleted();
|
||||
}
|
||||
}))
|
||||
.build());
|
||||
})));
|
||||
|
||||
mRouter.popController(testController);
|
||||
router.popController(testController);
|
||||
|
||||
Assert.assertEquals(2, callState.createViewCalls);
|
||||
Assert.assertEquals(2, callState.attachCalls);
|
||||
@@ -419,7 +406,7 @@ public class ControllerLifecycleTests {
|
||||
@Test
|
||||
public void testChildLifecycle() {
|
||||
Controller parent = new TestController();
|
||||
mRouter.pushController(RouterTransaction.builder(parent)
|
||||
router.pushController(RouterTransaction.with(parent)
|
||||
.pushChangeHandler(new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
@@ -427,8 +414,7 @@ public class ControllerLifecycleTests {
|
||||
ViewUtils.setAttached(to, true);
|
||||
changeListener.onChangeCompleted();
|
||||
}
|
||||
}))
|
||||
.build());
|
||||
})));
|
||||
|
||||
TestController child = new TestController();
|
||||
attachLifecycleListener(child);
|
||||
@@ -437,15 +423,15 @@ public class ControllerLifecycleTests {
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
|
||||
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, child))
|
||||
.popChangeHandler(getPopHandler(expectedCallState, child))
|
||||
.build()
|
||||
);
|
||||
Router childRouter = parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.VIEW_ID), null);
|
||||
childRouter
|
||||
.setRoot(RouterTransaction.with(child)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, child))
|
||||
.popChangeHandler(getPopHandler(expectedCallState, child)));
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
|
||||
parent.removeChildController(child);
|
||||
parent.removeChildRouter(childRouter);
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
}
|
||||
@@ -453,7 +439,7 @@ public class ControllerLifecycleTests {
|
||||
@Test
|
||||
public void testChildLifecycle2() {
|
||||
Controller parent = new TestController();
|
||||
mRouter.pushController(RouterTransaction.builder(parent)
|
||||
router.pushController(RouterTransaction.with(parent)
|
||||
.pushChangeHandler(new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
@@ -469,8 +455,7 @@ public class ControllerLifecycleTests {
|
||||
ViewUtils.setAttached(from, false);
|
||||
changeListener.onChangeCompleted();
|
||||
}
|
||||
}))
|
||||
.build());
|
||||
})));
|
||||
|
||||
TestController child = new TestController();
|
||||
attachLifecycleListener(child);
|
||||
@@ -479,20 +464,16 @@ public class ControllerLifecycleTests {
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
|
||||
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, child))
|
||||
.popChangeHandler(getPopHandler(expectedCallState, child))
|
||||
.build()
|
||||
);
|
||||
Router childRouter = parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.VIEW_ID), null);
|
||||
childRouter
|
||||
.setRoot(RouterTransaction.with(child)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, child))
|
||||
.popChangeHandler(getPopHandler(expectedCallState, child)));
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
|
||||
mRouter.popCurrentController();
|
||||
ViewUtils.setAttached(child.getView(), false);
|
||||
router.popCurrentController();
|
||||
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.destroyViewCalls++;
|
||||
expectedCallState.destroyCalls++;
|
||||
assertCalls(expectedCallState, child);
|
||||
}
|
||||
|
||||
@@ -542,64 +523,64 @@ public class ControllerLifecycleTests {
|
||||
|
||||
private void assertCalls(CallState callState, TestController controller) {
|
||||
Assert.assertEquals("Expected call counts and controller call counts do not match.", callState, controller.currentCallState);
|
||||
Assert.assertEquals("Expected call counts and lifecycle call counts do not match.", callState, mCurrentCallState);
|
||||
Assert.assertEquals("Expected call counts and lifecycle call counts do not match.", callState, currentCallState);
|
||||
}
|
||||
|
||||
private void attachLifecycleListener(Controller controller) {
|
||||
controller.addLifecycleListener(new LifecycleListener() {
|
||||
@Override
|
||||
public void onChangeStart(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
mCurrentCallState.changeStartCalls++;
|
||||
currentCallState.changeStartCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeEnd(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
mCurrentCallState.changeEndCalls++;
|
||||
currentCallState.changeEndCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postCreateView(@NonNull Controller controller, @NonNull View view) {
|
||||
mCurrentCallState.createViewCalls++;
|
||||
currentCallState.createViewCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postAttach(@NonNull Controller controller, @NonNull View view) {
|
||||
mCurrentCallState.attachCalls++;
|
||||
currentCallState.attachCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDestroyView(@NonNull Controller controller) {
|
||||
mCurrentCallState.destroyViewCalls++;
|
||||
currentCallState.destroyViewCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDetach(@NonNull Controller controller, @NonNull View view) {
|
||||
mCurrentCallState.detachCalls++;
|
||||
currentCallState.detachCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDestroy(@NonNull Controller controller) {
|
||||
mCurrentCallState.destroyCalls++;
|
||||
currentCallState.destroyCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Controller controller, @NonNull Bundle outState) {
|
||||
mCurrentCallState.saveInstanceStateCalls++;
|
||||
currentCallState.saveInstanceStateCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(@NonNull Controller controller, @NonNull Bundle savedInstanceState) {
|
||||
mCurrentCallState.restoreInstanceStateCalls++;
|
||||
currentCallState.restoreInstanceStateCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveViewState(@NonNull Controller controller, @NonNull Bundle outState) {
|
||||
mCurrentCallState.saveViewStateCalls++;
|
||||
currentCallState.saveViewStateCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreViewState(@NonNull Controller controller, @NonNull Bundle savedViewState) {
|
||||
mCurrentCallState.restoreViewStateCalls++;
|
||||
currentCallState.restoreViewStateCalls++;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -610,17 +591,17 @@ public class ControllerLifecycleTests {
|
||||
|
||||
public static class ChangeHandler extends ControllerChangeHandler {
|
||||
|
||||
private ChangeHandlerListener mListener;
|
||||
private ChangeHandlerListener listener;
|
||||
|
||||
public ChangeHandler() { }
|
||||
|
||||
public ChangeHandler(ChangeHandlerListener listener) {
|
||||
mListener = listener;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
mListener.performChange(container, from, to, isPush, changeListener);
|
||||
listener.performChange(container, from, to, isPush, changeListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller.RetainViewMode;
|
||||
@@ -22,19 +23,19 @@ import org.robolectric.util.ActivityController;
|
||||
@Config(manifest = Config.NONE)
|
||||
public class ControllerTests {
|
||||
|
||||
private ActivityController<TestActivity> mActivityController;
|
||||
private Router mRouter;
|
||||
private ActivityController<TestActivity> activityController;
|
||||
private Router router;
|
||||
|
||||
public void createActivityController(Bundle savedInstanceState) {
|
||||
mActivityController = Robolectric.buildActivity(TestActivity.class).create(savedInstanceState).start();
|
||||
activityController = Robolectric.buildActivity(TestActivity.class).create(savedInstanceState).start();
|
||||
|
||||
@IdRes int containerId = 4;
|
||||
FrameLayout routerContainer = new FrameLayout(mActivityController.get());
|
||||
FrameLayout routerContainer = new FrameLayout(activityController.get());
|
||||
routerContainer.setId(containerId);
|
||||
|
||||
mRouter = Conductor.attachRouter(mActivityController.get(), routerContainer, savedInstanceState);
|
||||
if (!mRouter.hasRootController()) {
|
||||
mRouter.setRoot(new TestController());
|
||||
router = Conductor.attachRouter(activityController.get(), routerContainer, savedInstanceState);
|
||||
if (!router.hasRootController()) {
|
||||
router.setRoot(RouterTransaction.with(new TestController()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +51,7 @@ public class ControllerTests {
|
||||
// Test View getting released w/ RELEASE_DETACH
|
||||
controller.setRetainViewMode(RetainViewMode.RELEASE_DETACH);
|
||||
Assert.assertNull(controller.getView());
|
||||
View view = controller.inflate(new FrameLayout(mRouter.getActivity()));
|
||||
View view = controller.inflate(new FrameLayout(router.getActivity()));
|
||||
Assert.assertNotNull(controller.getView());
|
||||
ViewUtils.setAttached(view, true);
|
||||
Assert.assertNotNull(controller.getView());
|
||||
@@ -59,7 +60,7 @@ public class ControllerTests {
|
||||
|
||||
// Test View getting retained w/ RETAIN_DETACH
|
||||
controller.setRetainViewMode(RetainViewMode.RETAIN_DETACH);
|
||||
view = controller.inflate(new FrameLayout(mRouter.getActivity()));
|
||||
view = controller.inflate(new FrameLayout(router.getActivity()));
|
||||
Assert.assertNotNull(controller.getView());
|
||||
ViewUtils.setAttached(view, true);
|
||||
Assert.assertNotNull(controller.getView());
|
||||
@@ -76,22 +77,22 @@ public class ControllerTests {
|
||||
TestController controller = new TestController();
|
||||
CallState expectedCallState = new CallState(true);
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller).build());
|
||||
router.pushController(RouterTransaction.with(controller));
|
||||
ViewUtils.setAttached(controller.getView(), true);
|
||||
|
||||
// Ensure that calling onActivityResult w/o requesting a result doesn't do anything
|
||||
mRouter.onActivityResult(1, Activity.RESULT_OK, null);
|
||||
router.onActivityResult(1, Activity.RESULT_OK, null);
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
// Ensure starting an activity for result gets us the result back
|
||||
controller.startActivityForResult(new Intent("action"), 1);
|
||||
mRouter.onActivityResult(1, Activity.RESULT_OK, null);
|
||||
router.onActivityResult(1, Activity.RESULT_OK, null);
|
||||
expectedCallState.onActivityResultCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
// Ensure requesting a result w/o calling startActivityForResult works
|
||||
controller.registerForActivityResult(2);
|
||||
mRouter.onActivityResult(2, Activity.RESULT_OK, null);
|
||||
router.onActivityResult(2, Activity.RESULT_OK, null);
|
||||
expectedCallState.onActivityResultCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
@@ -101,29 +102,30 @@ public class ControllerTests {
|
||||
TestController parent = new TestController();
|
||||
TestController child = new TestController();
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(parent).build());
|
||||
router.pushController(RouterTransaction.with(parent));
|
||||
ViewUtils.setAttached(parent.getView(), true);
|
||||
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID).build());
|
||||
parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.VIEW_ID), null)
|
||||
.setRoot(RouterTransaction.with(child));
|
||||
ViewUtils.setAttached(child.getView(), true);
|
||||
|
||||
CallState childExpectedCallState = new CallState(true);
|
||||
CallState parentExpectedCallState = new CallState(true);
|
||||
|
||||
// Ensure that calling onActivityResult w/o requesting a result doesn't do anything
|
||||
mRouter.onActivityResult(1, Activity.RESULT_OK, null);
|
||||
router.onActivityResult(1, Activity.RESULT_OK, null);
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
// Ensure starting an activity for result gets us the result back
|
||||
child.startActivityForResult(new Intent("action"), 1);
|
||||
mRouter.onActivityResult(1, Activity.RESULT_OK, null);
|
||||
router.onActivityResult(1, Activity.RESULT_OK, null);
|
||||
childExpectedCallState.onActivityResultCalls++;
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
// Ensure requesting a result w/o calling startActivityForResult works
|
||||
child.registerForActivityResult(2);
|
||||
mRouter.onActivityResult(2, Activity.RESULT_OK, null);
|
||||
router.onActivityResult(2, Activity.RESULT_OK, null);
|
||||
childExpectedCallState.onActivityResultCalls++;
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
@@ -136,11 +138,11 @@ public class ControllerTests {
|
||||
TestController controller = new TestController();
|
||||
CallState expectedCallState = new CallState(true);
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller).build());
|
||||
router.pushController(RouterTransaction.with(controller));
|
||||
ViewUtils.setAttached(controller.getView(), true);
|
||||
|
||||
// Ensure that calling handleRequestedPermission w/o requesting a result doesn't do anything
|
||||
mRouter.onRequestPermissionsResult("anotherId", 1, requestedPermissions, new int[] {1});
|
||||
router.onRequestPermissionsResult("anotherId", 1, requestedPermissions, new int[] {1});
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
// Ensure requesting the permission gets us the result back
|
||||
@@ -148,7 +150,7 @@ public class ControllerTests {
|
||||
controller.requestPermissions(requestedPermissions, 1);
|
||||
} catch (NoSuchMethodError ignored) { }
|
||||
|
||||
mRouter.onRequestPermissionsResult(controller.getInstanceId(), 1, requestedPermissions, new int[] {1});
|
||||
router.onRequestPermissionsResult(controller.getInstanceId(), 1, requestedPermissions, new int[] {1});
|
||||
expectedCallState.onRequestPermissionsResultCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
@@ -160,16 +162,17 @@ public class ControllerTests {
|
||||
TestController parent = new TestController();
|
||||
TestController child = new TestController();
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(parent).build());
|
||||
router.pushController(RouterTransaction.with(parent));
|
||||
ViewUtils.setAttached(parent.getView(), true);
|
||||
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID).build());
|
||||
parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.VIEW_ID), null)
|
||||
.setRoot(RouterTransaction.with(child));
|
||||
ViewUtils.setAttached(child.getView(), true);
|
||||
|
||||
CallState childExpectedCallState = new CallState(true);
|
||||
CallState parentExpectedCallState = new CallState(true);
|
||||
|
||||
// Ensure that calling handleRequestedPermission w/o requesting a result doesn't do anything
|
||||
mRouter.onRequestPermissionsResult("anotherId", 1, requestedPermissions, new int[] {1});
|
||||
router.onRequestPermissionsResult("anotherId", 1, requestedPermissions, new int[] {1});
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
@@ -178,7 +181,7 @@ public class ControllerTests {
|
||||
child.requestPermissions(requestedPermissions, 1);
|
||||
} catch (NoSuchMethodError ignored) { }
|
||||
|
||||
mRouter.onRequestPermissionsResult(child.getInstanceId(), 1, requestedPermissions, new int[] {1});
|
||||
router.onRequestPermissionsResult(child.getInstanceId(), 1, requestedPermissions, new int[] {1});
|
||||
childExpectedCallState.onRequestPermissionsResultCalls++;
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
@@ -189,35 +192,35 @@ public class ControllerTests {
|
||||
TestController controller = new TestController();
|
||||
CallState expectedCallState = new CallState(true);
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller).build());
|
||||
router.pushController(RouterTransaction.with(controller));
|
||||
ViewUtils.setAttached(controller.getView(), true);
|
||||
|
||||
// Ensure that calling onCreateOptionsMenu w/o declaring that we have one doesn't do anything
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
router.onCreateOptionsMenu(null, null);
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
// Ensure calling onCreateOptionsMenu with a menu works
|
||||
controller.setHasOptionsMenu(true);
|
||||
|
||||
// Ensure it'll still get called back next time onCreateOptionsMenu is called
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
router.onCreateOptionsMenu(null, null);
|
||||
expectedCallState.createOptionsMenuCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
// Ensure we stop getting them when we hide it
|
||||
controller.setOptionsMenuHidden(true);
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
router.onCreateOptionsMenu(null, null);
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
// Ensure we get the callback them when we un-hide it
|
||||
controller.setOptionsMenuHidden(false);
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
router.onCreateOptionsMenu(null, null);
|
||||
expectedCallState.createOptionsMenuCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
// Ensure we don't get the callback when we no longer have a menu
|
||||
controller.setHasOptionsMenu(false);
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
router.onCreateOptionsMenu(null, null);
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
|
||||
@@ -226,16 +229,17 @@ public class ControllerTests {
|
||||
TestController parent = new TestController();
|
||||
TestController child = new TestController();
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(parent).build());
|
||||
router.pushController(RouterTransaction.with(parent));
|
||||
ViewUtils.setAttached(parent.getView(), true);
|
||||
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID).build());
|
||||
parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.VIEW_ID), null)
|
||||
.setRoot(RouterTransaction.with(child));
|
||||
ViewUtils.setAttached(child.getView(), true);
|
||||
|
||||
CallState childExpectedCallState = new CallState(true);
|
||||
CallState parentExpectedCallState = new CallState(true);
|
||||
|
||||
// Ensure that calling onCreateOptionsMenu w/o declaring that we have one doesn't do anything
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
router.onCreateOptionsMenu(null, null);
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
@@ -243,31 +247,130 @@ public class ControllerTests {
|
||||
child.setHasOptionsMenu(true);
|
||||
|
||||
// Ensure it'll still get called back next time onCreateOptionsMenu is called
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
router.onCreateOptionsMenu(null, null);
|
||||
childExpectedCallState.createOptionsMenuCalls++;
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
// Ensure we stop getting them when we hide it
|
||||
child.setOptionsMenuHidden(true);
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
router.onCreateOptionsMenu(null, null);
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
// Ensure we get the callback them when we un-hide it
|
||||
child.setOptionsMenuHidden(false);
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
router.onCreateOptionsMenu(null, null);
|
||||
childExpectedCallState.createOptionsMenuCalls++;
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
// Ensure we don't get the callback when we no longer have a menu
|
||||
child.setHasOptionsMenu(false);
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
router.onCreateOptionsMenu(null, null);
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddRemoveChildControllers() {
|
||||
TestController parent = new TestController();
|
||||
TestController child1 = new TestController();
|
||||
TestController child2 = new TestController();
|
||||
|
||||
router.pushController(RouterTransaction.with(parent));
|
||||
|
||||
Assert.assertEquals(0, parent.getChildRouters().size());
|
||||
Assert.assertNull(child1.getParentController());
|
||||
Assert.assertNull(child2.getParentController());
|
||||
|
||||
Router childRouter = parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.VIEW_ID), null);
|
||||
childRouter.setRoot(RouterTransaction.with(child1));
|
||||
|
||||
Assert.assertEquals(1, parent.getChildRouters().size());
|
||||
Assert.assertEquals(childRouter, parent.getChildRouters().get(0));
|
||||
Assert.assertEquals(1, childRouter.getBackstackSize());
|
||||
Assert.assertEquals(child1, childRouter.getControllers().get(0));
|
||||
Assert.assertEquals(parent, child1.getParentController());
|
||||
Assert.assertNull(child2.getParentController());
|
||||
|
||||
childRouter = parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.VIEW_ID), null);
|
||||
childRouter.pushController(RouterTransaction.with(child2));
|
||||
|
||||
Assert.assertEquals(1, parent.getChildRouters().size());
|
||||
Assert.assertEquals(childRouter, parent.getChildRouters().get(0));
|
||||
Assert.assertEquals(2, childRouter.getBackstackSize());
|
||||
Assert.assertEquals(child1, childRouter.getControllers().get(0));
|
||||
Assert.assertEquals(child2, childRouter.getControllers().get(1));
|
||||
Assert.assertEquals(parent, child1.getParentController());
|
||||
Assert.assertEquals(parent, child2.getParentController());
|
||||
|
||||
childRouter.popController(child2);
|
||||
|
||||
Assert.assertEquals(1, parent.getChildRouters().size());
|
||||
Assert.assertEquals(childRouter, parent.getChildRouters().get(0));
|
||||
Assert.assertEquals(1, childRouter.getBackstackSize());
|
||||
Assert.assertEquals(child1, childRouter.getControllers().get(0));
|
||||
Assert.assertEquals(parent, child1.getParentController());
|
||||
Assert.assertNull(child2.getParentController());
|
||||
|
||||
childRouter.popController(child1);
|
||||
|
||||
Assert.assertEquals(1, parent.getChildRouters().size());
|
||||
Assert.assertEquals(childRouter, parent.getChildRouters().get(0));
|
||||
Assert.assertEquals(0, childRouter.getBackstackSize());
|
||||
Assert.assertNull(child1.getParentController());
|
||||
Assert.assertNull(child2.getParentController());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddRemoveChildRouters() {
|
||||
TestController parent = new TestController();
|
||||
|
||||
TestController child1 = new TestController();
|
||||
TestController child2 = new TestController();
|
||||
|
||||
router.pushController(RouterTransaction.with(parent));
|
||||
|
||||
Assert.assertEquals(0, parent.getChildRouters().size());
|
||||
Assert.assertNull(child1.getParentController());
|
||||
Assert.assertNull(child2.getParentController());
|
||||
|
||||
Router childRouter1 = parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.CHILD_VIEW_ID_1), null);
|
||||
Router childRouter2 = parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.CHILD_VIEW_ID_2), null);
|
||||
|
||||
childRouter1.setRoot(RouterTransaction.with(child1));
|
||||
childRouter2.setRoot(RouterTransaction.with(child2));
|
||||
|
||||
Assert.assertEquals(2, parent.getChildRouters().size());
|
||||
Assert.assertEquals(childRouter1, parent.getChildRouters().get(0));
|
||||
Assert.assertEquals(childRouter2, parent.getChildRouters().get(1));
|
||||
Assert.assertEquals(1, childRouter1.getBackstackSize());
|
||||
Assert.assertEquals(1, childRouter2.getBackstackSize());
|
||||
Assert.assertEquals(child1, childRouter1.getControllers().get(0));
|
||||
Assert.assertEquals(child2, childRouter2.getControllers().get(0));
|
||||
Assert.assertEquals(parent, child1.getParentController());
|
||||
Assert.assertEquals(parent, child2.getParentController());
|
||||
|
||||
parent.removeChildRouter(childRouter2);
|
||||
|
||||
Assert.assertEquals(1, parent.getChildRouters().size());
|
||||
Assert.assertEquals(childRouter1, parent.getChildRouters().get(0));
|
||||
Assert.assertEquals(1, childRouter1.getBackstackSize());
|
||||
Assert.assertEquals(0, childRouter2.getBackstackSize());
|
||||
Assert.assertEquals(child1, childRouter1.getControllers().get(0));
|
||||
Assert.assertEquals(parent, child1.getParentController());
|
||||
Assert.assertNull(child2.getParentController());
|
||||
|
||||
parent.removeChildRouter(childRouter1);
|
||||
|
||||
Assert.assertEquals(0, parent.getChildRouters().size());
|
||||
Assert.assertEquals(0, childRouter1.getBackstackSize());
|
||||
Assert.assertEquals(0, childRouter2.getBackstackSize());
|
||||
Assert.assertNull(child1.getParentController());
|
||||
Assert.assertNull(child2.getParentController());
|
||||
}
|
||||
|
||||
private void assertCalls(CallState callState, TestController controller) {
|
||||
Assert.assertEquals("Expected call counts and controller call counts do not match.", callState, controller.currentCallState);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.bluelinelabs.conductor;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
|
||||
@@ -14,39 +13,19 @@ public class ControllerTransactionTests {
|
||||
|
||||
@Test
|
||||
public void testRouterSaveRestore() {
|
||||
RouterTransaction transaction = RouterTransaction.builder(new TestController())
|
||||
RouterTransaction transaction = RouterTransaction.with(new TestController())
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new VerticalChangeHandler())
|
||||
.tag("Test Tag")
|
||||
.build();
|
||||
.tag("Test Tag");
|
||||
|
||||
Bundle bundle = transaction.detachAndSaveInstanceState();
|
||||
Bundle bundle = transaction.saveInstanceState();
|
||||
|
||||
RouterTransaction restoredTransaction = new RouterTransaction(bundle);
|
||||
|
||||
Assert.assertEquals(transaction.getController().getClass(), restoredTransaction.getController().getClass());
|
||||
Assert.assertEquals(transaction.getPushControllerChangeHandler().getClass(), restoredTransaction.getPushControllerChangeHandler().getClass());
|
||||
Assert.assertEquals(transaction.getPopControllerChangeHandler().getClass(), restoredTransaction.getPopControllerChangeHandler().getClass());
|
||||
Assert.assertEquals(transaction.getTag(), restoredTransaction.getTag());
|
||||
Assert.assertEquals(transaction.controller.getClass(), restoredTransaction.controller.getClass());
|
||||
Assert.assertEquals(transaction.pushChangeHandler().getClass(), restoredTransaction.pushChangeHandler().getClass());
|
||||
Assert.assertEquals(transaction.popChangeHandler().getClass(), restoredTransaction.popChangeHandler().getClass());
|
||||
Assert.assertEquals(transaction.tag(), restoredTransaction.tag());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChildSaveRestore() {
|
||||
@IdRes int layoutId = 234;
|
||||
ChildControllerTransaction transaction = ChildControllerTransaction.builder(new TestController(), layoutId)
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new VerticalChangeHandler())
|
||||
.tag("Test Tag")
|
||||
.build();
|
||||
|
||||
Bundle bundle = transaction.detachAndSaveInstanceState();
|
||||
|
||||
ChildControllerTransaction restoredTransaction = new ChildControllerTransaction(bundle);
|
||||
|
||||
Assert.assertEquals(transaction.containerId, restoredTransaction.containerId);
|
||||
Assert.assertEquals(transaction.getController().getClass(), restoredTransaction.getController().getClass());
|
||||
Assert.assertEquals(transaction.getPushControllerChangeHandler().getClass(), restoredTransaction.getPushControllerChangeHandler().getClass());
|
||||
Assert.assertEquals(transaction.getPopControllerChangeHandler().getClass(), restoredTransaction.getPopControllerChangeHandler().getClass());
|
||||
Assert.assertEquals(transaction.getTag(), restoredTransaction.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
package com.bluelinelabs.conductor;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeCompletedListener;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ActivityController;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(manifest = Config.NONE)
|
||||
public class ReattachCaseTests {
|
||||
|
||||
private ActivityController<TestActivity> activityController;
|
||||
private Router router;
|
||||
|
||||
public void createActivityController(Bundle savedInstanceState) {
|
||||
activityController = Robolectric.buildActivity(TestActivity.class).create(savedInstanceState).start();
|
||||
|
||||
@IdRes int containerId = 4;
|
||||
FrameLayout routerContainer = new FrameLayout(activityController.get());
|
||||
routerContainer.setId(containerId);
|
||||
|
||||
router = Conductor.attachRouter(activityController.get(), routerContainer, savedInstanceState);
|
||||
if (!router.hasRootController()) {
|
||||
router.setRoot(RouterTransaction.with(new TestController()));
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
createActivityController(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNeedsAttachingOnPauseAndOrientation() {
|
||||
final TestController controllerA = new TestController();
|
||||
final TestController controllerB = new TestController();
|
||||
|
||||
router.pushController(RouterTransaction.with(controllerA)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Assert.assertTrue(controllerA.isAttached());
|
||||
Assert.assertFalse(controllerB.isAttached());
|
||||
|
||||
sleepWakeDevice();
|
||||
|
||||
Assert.assertTrue(controllerA.isAttached());
|
||||
Assert.assertFalse(controllerB.isAttached());
|
||||
|
||||
router.pushController(RouterTransaction.with(controllerB)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
|
||||
rotateDevice();
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChildNeedsAttachOnPauseAndOrientation() {
|
||||
final TestController controllerA = new TestController();
|
||||
final TestController childController = new TestController();
|
||||
final TestController controllerB = new TestController();
|
||||
|
||||
router.pushController(RouterTransaction.with(controllerA)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Router childRouter = controllerA.getChildRouter((ViewGroup)controllerA.getView().findViewById(TestController.VIEW_ID), null);
|
||||
childRouter.pushController(RouterTransaction.with(childController)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Assert.assertTrue(controllerA.isAttached());
|
||||
Assert.assertTrue(childController.isAttached());
|
||||
Assert.assertFalse(controllerB.isAttached());
|
||||
|
||||
sleepWakeDevice();
|
||||
|
||||
Assert.assertTrue(controllerA.isAttached());
|
||||
Assert.assertTrue(childController.isAttached());
|
||||
Assert.assertFalse(controllerB.isAttached());
|
||||
|
||||
router.pushController(RouterTransaction.with(controllerB)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertFalse(childController.isAttached());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
|
||||
rotateDevice();
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertFalse(childController.isAttached());
|
||||
Assert.assertTrue(childController.getNeedsAttach());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChildHandleBackOnOrientation() {
|
||||
final TestController controllerA = new TestController();
|
||||
final TestController controllerB = new TestController();
|
||||
final TestController childController = new TestController();
|
||||
|
||||
router.pushController(RouterTransaction.with(controllerA)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Assert.assertTrue(controllerA.isAttached());
|
||||
Assert.assertFalse(controllerB.isAttached());
|
||||
Assert.assertFalse(childController.isAttached());
|
||||
|
||||
router.pushController(RouterTransaction.with(controllerB)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Router childRouter = controllerB.getChildRouter((ViewGroup)controllerB.getView().findViewById(TestController.VIEW_ID), null);
|
||||
childRouter.setPopsLastView(true);
|
||||
childRouter.pushController(RouterTransaction.with(childController)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
Assert.assertTrue(childController.isAttached());
|
||||
|
||||
rotateDevice();
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
Assert.assertTrue(childController.isAttached());
|
||||
|
||||
router.handleBack();
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
Assert.assertFalse(childController.isAttached());
|
||||
|
||||
router.handleBack();
|
||||
|
||||
Assert.assertTrue(controllerA.isAttached());
|
||||
Assert.assertFalse(controllerB.isAttached());
|
||||
Assert.assertFalse(childController.isAttached());
|
||||
}
|
||||
|
||||
// Attempt to test https://github.com/bluelinelabs/Conductor/issues/86#issuecomment-231381271
|
||||
@Test
|
||||
public void testReusedChildRouterHandleBackOnOrientation() {
|
||||
TestController controllerA = new TestController();
|
||||
TestController controllerB = new TestController();
|
||||
TestController childController = new TestController();
|
||||
|
||||
router.pushController(RouterTransaction.with(controllerA)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Assert.assertTrue(controllerA.isAttached());
|
||||
Assert.assertFalse(controllerB.isAttached());
|
||||
Assert.assertFalse(childController.isAttached());
|
||||
|
||||
router.pushController(RouterTransaction.with(controllerB)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Router childRouter = controllerB.getChildRouter((ViewGroup)controllerB.getView().findViewById(TestController.VIEW_ID), null);
|
||||
childRouter.setPopsLastView(true);
|
||||
childRouter.pushController(RouterTransaction.with(childController)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
Assert.assertTrue(childController.isAttached());
|
||||
|
||||
router.handleBack();
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
Assert.assertFalse(childController.isAttached());
|
||||
|
||||
childController = new TestController();
|
||||
childRouter.pushController(RouterTransaction.with(childController)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
Assert.assertTrue(childController.isAttached());
|
||||
|
||||
rotateDevice();
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
Assert.assertTrue(childController.isAttached());
|
||||
|
||||
router.handleBack();
|
||||
|
||||
childController = new TestController();
|
||||
childRouter.pushController(RouterTransaction.with(childController)
|
||||
.pushChangeHandler(getPushHandler())
|
||||
.popChangeHandler(getPopHandler()));
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
Assert.assertTrue(childController.isAttached());
|
||||
|
||||
router.handleBack();
|
||||
|
||||
Assert.assertFalse(controllerA.isAttached());
|
||||
Assert.assertTrue(controllerB.isAttached());
|
||||
Assert.assertFalse(childController.isAttached());
|
||||
|
||||
router.handleBack();
|
||||
|
||||
Assert.assertTrue(controllerA.isAttached());
|
||||
Assert.assertFalse(controllerB.isAttached());
|
||||
Assert.assertFalse(childController.isAttached());
|
||||
}
|
||||
|
||||
private void sleepWakeDevice() {
|
||||
activityController.saveInstanceState(new Bundle()).pause();
|
||||
activityController.resume();
|
||||
}
|
||||
|
||||
private void rotateDevice() {
|
||||
@IdRes int containerId = 4;
|
||||
FrameLayout routerContainer = new FrameLayout(activityController.get());
|
||||
routerContainer.setId(containerId);
|
||||
|
||||
activityController.get().isChangingConfigurations = true;
|
||||
activityController.get().recreate();
|
||||
router.rebindIfNeeded();
|
||||
}
|
||||
|
||||
private ChangeHandler getPushHandler() {
|
||||
return new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
container.addView(to);
|
||||
ViewUtils.setAttached(to, true);
|
||||
|
||||
if (from != null) {
|
||||
container.removeView(from);
|
||||
ViewUtils.setAttached(from, false);
|
||||
}
|
||||
|
||||
changeListener.onChangeCompleted();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private ChangeHandler getPopHandler() {
|
||||
return new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
container.removeView(from);
|
||||
ViewUtils.setAttached(from, false);
|
||||
changeListener.onChangeCompleted();
|
||||
|
||||
if (to != null) {
|
||||
container.addView(to);
|
||||
ViewUtils.setAttached(to, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
interface ChangeHandlerListener {
|
||||
void performChange(@NonNull ViewGroup container, View from, View to, @NonNull ControllerChangeCompletedListener changeListener);
|
||||
}
|
||||
|
||||
public static class ChangeHandler extends ControllerChangeHandler {
|
||||
|
||||
private ChangeHandlerListener listener;
|
||||
|
||||
public ChangeHandler() { }
|
||||
|
||||
public ChangeHandler(ChangeHandlerListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
listener.performChange(container, from, to, changeListener);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,12 +15,12 @@ import org.robolectric.annotation.Config;
|
||||
@Config(manifest = Config.NONE)
|
||||
public class RouterTests {
|
||||
|
||||
private Router mRouter;
|
||||
private Router router;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
Activity activity = Robolectric.buildActivity(TestActivity.class).create().get();
|
||||
mRouter = Conductor.attachRouter(activity, new FrameLayout(activity), null);
|
||||
router = Conductor.attachRouter(activity, new FrameLayout(activity), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -29,13 +29,13 @@ public class RouterTests {
|
||||
|
||||
Controller rootController = new TestController();
|
||||
|
||||
Assert.assertFalse(mRouter.hasRootController());
|
||||
Assert.assertFalse(router.hasRootController());
|
||||
|
||||
mRouter.setRoot(rootController, rootTag);
|
||||
router.setRoot(RouterTransaction.with(rootController).tag(rootTag));
|
||||
|
||||
Assert.assertTrue(mRouter.hasRootController());
|
||||
Assert.assertTrue(router.hasRootController());
|
||||
|
||||
Assert.assertEquals(rootController, mRouter.getControllerWithTag(rootTag));
|
||||
Assert.assertEquals(rootController, router.getControllerWithTag(rootTag));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -46,21 +46,21 @@ public class RouterTests {
|
||||
Controller oldRootController = new TestController();
|
||||
Controller newRootController = new TestController();
|
||||
|
||||
mRouter.setRoot(oldRootController, oldRootTag);
|
||||
mRouter.setRoot(newRootController, newRootTag);
|
||||
router.setRoot(RouterTransaction.with(oldRootController).tag(oldRootTag));
|
||||
router.setRoot(RouterTransaction.with(newRootController).tag(newRootTag));
|
||||
|
||||
Assert.assertNull(mRouter.getControllerWithTag(oldRootTag));
|
||||
Assert.assertEquals(newRootController, mRouter.getControllerWithTag(newRootTag));
|
||||
Assert.assertNull(router.getControllerWithTag(oldRootTag));
|
||||
Assert.assertEquals(newRootController, router.getControllerWithTag(newRootTag));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByInstanceId() {
|
||||
Controller controller = new TestController();
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller).build());
|
||||
router.pushController(RouterTransaction.with(controller));
|
||||
|
||||
Assert.assertEquals(controller, mRouter.getControllerWithInstanceId(controller.getInstanceId()));
|
||||
Assert.assertNull(mRouter.getControllerWithInstanceId("fake id"));
|
||||
Assert.assertEquals(controller, router.getControllerWithInstanceId(controller.getInstanceId()));
|
||||
Assert.assertNull(router.getControllerWithInstanceId("fake id"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,16 +71,14 @@ public class RouterTests {
|
||||
Controller controller1 = new TestController();
|
||||
Controller controller2 = new TestController();
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller1)
|
||||
.tag(controller1Tag)
|
||||
.build());
|
||||
router.pushController(RouterTransaction.with(controller1)
|
||||
.tag(controller1Tag));
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller2)
|
||||
.tag(controller2Tag)
|
||||
.build());
|
||||
router.pushController(RouterTransaction.with(controller2)
|
||||
.tag(controller2Tag));
|
||||
|
||||
Assert.assertEquals(controller1, mRouter.getControllerWithTag(controller1Tag));
|
||||
Assert.assertEquals(controller2, mRouter.getControllerWithTag(controller2Tag));
|
||||
Assert.assertEquals(controller1, router.getControllerWithTag(controller1Tag));
|
||||
Assert.assertEquals(controller2, router.getControllerWithTag(controller2Tag));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -91,31 +89,29 @@ public class RouterTests {
|
||||
Controller controller1 = new TestController();
|
||||
Controller controller2 = new TestController();
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller1)
|
||||
.tag(controller1Tag)
|
||||
.build());
|
||||
router.pushController(RouterTransaction.with(controller1)
|
||||
.tag(controller1Tag));
|
||||
|
||||
Assert.assertEquals(1, mRouter.getBackstackSize());
|
||||
Assert.assertEquals(1, router.getBackstackSize());
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller2)
|
||||
.tag(controller2Tag)
|
||||
.build());
|
||||
router.pushController(RouterTransaction.with(controller2)
|
||||
.tag(controller2Tag));
|
||||
|
||||
Assert.assertEquals(2, mRouter.getBackstackSize());
|
||||
Assert.assertEquals(2, router.getBackstackSize());
|
||||
|
||||
mRouter.popCurrentController();
|
||||
router.popCurrentController();
|
||||
|
||||
Assert.assertEquals(1, mRouter.getBackstackSize());
|
||||
Assert.assertEquals(1, router.getBackstackSize());
|
||||
|
||||
Assert.assertEquals(controller1, mRouter.getControllerWithTag(controller1Tag));
|
||||
Assert.assertNull(mRouter.getControllerWithTag(controller2Tag));
|
||||
Assert.assertEquals(controller1, router.getControllerWithTag(controller1Tag));
|
||||
Assert.assertNull(router.getControllerWithTag(controller2Tag));
|
||||
|
||||
mRouter.popCurrentController();
|
||||
router.popCurrentController();
|
||||
|
||||
Assert.assertEquals(0, mRouter.getBackstackSize());
|
||||
Assert.assertEquals(0, router.getBackstackSize());
|
||||
|
||||
Assert.assertNull(mRouter.getControllerWithTag(controller1Tag));
|
||||
Assert.assertNull(mRouter.getControllerWithTag(controller2Tag));
|
||||
Assert.assertNull(router.getControllerWithTag(controller1Tag));
|
||||
Assert.assertNull(router.getControllerWithTag(controller2Tag));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -130,29 +126,25 @@ public class RouterTests {
|
||||
Controller controller3 = new TestController();
|
||||
Controller controller4 = new TestController();
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller1)
|
||||
.tag(controller1Tag)
|
||||
.build());
|
||||
router.pushController(RouterTransaction.with(controller1)
|
||||
.tag(controller1Tag));
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller2)
|
||||
.tag(controller2Tag)
|
||||
.build());
|
||||
router.pushController(RouterTransaction.with(controller2)
|
||||
.tag(controller2Tag));
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller3)
|
||||
.tag(controller3Tag)
|
||||
.build());
|
||||
router.pushController(RouterTransaction.with(controller3)
|
||||
.tag(controller3Tag));
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller4)
|
||||
.tag(controller4Tag)
|
||||
.build());
|
||||
router.pushController(RouterTransaction.with(controller4)
|
||||
.tag(controller4Tag));
|
||||
|
||||
mRouter.popToTag(controller2Tag);
|
||||
router.popToTag(controller2Tag);
|
||||
|
||||
Assert.assertEquals(2, mRouter.getBackstackSize());
|
||||
Assert.assertEquals(controller1, mRouter.getControllerWithTag(controller1Tag));
|
||||
Assert.assertEquals(controller2, mRouter.getControllerWithTag(controller2Tag));
|
||||
Assert.assertNull(mRouter.getControllerWithTag(controller3Tag));
|
||||
Assert.assertNull(mRouter.getControllerWithTag(controller4Tag));
|
||||
Assert.assertEquals(2, router.getBackstackSize());
|
||||
Assert.assertEquals(controller1, router.getControllerWithTag(controller1Tag));
|
||||
Assert.assertEquals(controller2, router.getControllerWithTag(controller2Tag));
|
||||
Assert.assertNull(router.getControllerWithTag(controller3Tag));
|
||||
Assert.assertNull(router.getControllerWithTag(controller4Tag));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -165,24 +157,21 @@ public class RouterTests {
|
||||
Controller controller2 = new TestController();
|
||||
Controller controller3 = new TestController();
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller1)
|
||||
.tag(controller1Tag)
|
||||
.build());
|
||||
router.pushController(RouterTransaction.with(controller1)
|
||||
.tag(controller1Tag));
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller2)
|
||||
.tag(controller2Tag)
|
||||
.build());
|
||||
router.pushController(RouterTransaction.with(controller2)
|
||||
.tag(controller2Tag));
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller3)
|
||||
.tag(controller3Tag)
|
||||
.build());
|
||||
router.pushController(RouterTransaction.with(controller3)
|
||||
.tag(controller3Tag));
|
||||
|
||||
mRouter.popController(controller2);
|
||||
router.popController(controller2);
|
||||
|
||||
Assert.assertEquals(2, mRouter.getBackstackSize());
|
||||
Assert.assertEquals(controller1, mRouter.getControllerWithTag(controller1Tag));
|
||||
Assert.assertNull(mRouter.getControllerWithTag(controller2Tag));
|
||||
Assert.assertEquals(controller3, mRouter.getControllerWithTag(controller3Tag));
|
||||
Assert.assertEquals(2, router.getBackstackSize());
|
||||
Assert.assertEquals(controller1, router.getControllerWithTag(controller1Tag));
|
||||
Assert.assertNull(router.getControllerWithTag(controller2Tag));
|
||||
Assert.assertEquals(controller3, router.getControllerWithTag(controller3Tag));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.bluelinelabs.conductor.ControllerTransaction.ControllerChangeType;
|
||||
|
||||
public class TestController extends Controller {
|
||||
|
||||
@IdRes public static final int VIEW_ID = 2342;
|
||||
@IdRes public static final int CHILD_VIEW_ID_1 = 2343;
|
||||
@IdRes public static final int CHILD_VIEW_ID_2 = 2344;
|
||||
|
||||
private static final String KEY_CALL_STATE = "TestController.currentCallState";
|
||||
|
||||
@@ -29,8 +29,17 @@ public class TestController extends Controller {
|
||||
@Override
|
||||
protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
currentCallState.createViewCalls++;
|
||||
View view = new FrameLayout(inflater.getContext());
|
||||
FrameLayout view = new FrameLayout(inflater.getContext());
|
||||
view.setId(VIEW_ID);
|
||||
|
||||
FrameLayout childContainer1 = new FrameLayout(inflater.getContext());
|
||||
childContainer1.setId(CHILD_VIEW_ID_1);
|
||||
view.addView(childContainer1);
|
||||
|
||||
FrameLayout childContainer2 = new FrameLayout(inflater.getContext());
|
||||
childContainer2.setId(CHILD_VIEW_ID_2);
|
||||
view.addView(childContainer2);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.List;
|
||||
|
||||
public class ViewUtils {
|
||||
|
||||
static void setAttached(View view, boolean attached) {
|
||||
public static void setAttached(View view, boolean attached) {
|
||||
Object listenerInfo = ReflectionHelpers.callInstanceMethod(view, "getListenerInfo");
|
||||
List<OnAttachStateChangeListener> listeners = ReflectionHelpers.getField(listenerInfo, "mOnAttachStateChangeListeners");
|
||||
|
||||
|
||||
@@ -43,7 +43,9 @@ dependencies {
|
||||
compile rootProject.ext.supportV4
|
||||
compile rootProject.ext.supportDesign
|
||||
|
||||
apt rootProject.ext.butterknifeCompiler
|
||||
compile rootProject.ext.butterknife
|
||||
compile rootProject.ext.picasso
|
||||
|
||||
compile project(':conductor-support')
|
||||
compile project(':conductor-rxlifecycle')
|
||||
|
||||
@@ -7,36 +7,39 @@ import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.Conductor;
|
||||
import com.bluelinelabs.conductor.Router;
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.demo.controllers.HomeController;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements ActionBarProvider {
|
||||
|
||||
@Bind(R.id.toolbar) Toolbar mToolbar;
|
||||
@Bind(R.id.controller_container) ViewGroup mContainer;
|
||||
@BindView(R.id.toolbar) Toolbar toolbar;
|
||||
@BindView(R.id.controller_container) ViewGroup container;
|
||||
|
||||
private Router mRouter;
|
||||
private Router router;
|
||||
private Unbinder unbinder;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
ButterKnife.bind(this);
|
||||
unbinder = ButterKnife.bind(this);
|
||||
|
||||
setSupportActionBar(mToolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
mRouter = Conductor.attachRouter(this, mContainer, savedInstanceState);
|
||||
if (!mRouter.hasRootController()) {
|
||||
mRouter.setRoot(new HomeController());
|
||||
router = Conductor.attachRouter(this, container, savedInstanceState);
|
||||
if (!router.hasRootController()) {
|
||||
router.setRoot(RouterTransaction.with(new HomeController()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (!mRouter.handleBack()) {
|
||||
if (!router.handleBack()) {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
@@ -44,7 +47,7 @@ public class MainActivity extends AppCompatActivity implements ActionBarProvider
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
ButterKnife.unbind(this);
|
||||
unbinder.unbind();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-13
@@ -20,8 +20,8 @@ public class CircularRevealChangeHandler extends AnimatorChangeHandler {
|
||||
private static final String KEY_CX = "CircularRevealChangeHandler.cx";
|
||||
private static final String KEY_CY = "CircularRevealChangeHandler.cy";
|
||||
|
||||
private int mCx;
|
||||
private int mCy;
|
||||
private int cx;
|
||||
private int cy;
|
||||
|
||||
public CircularRevealChangeHandler() { }
|
||||
|
||||
@@ -73,8 +73,8 @@ public class CircularRevealChangeHandler extends AnimatorChangeHandler {
|
||||
int relativeLeft = fromLocation[0] - containerLocation[0];
|
||||
int relativeTop = fromLocation[1] - containerLocation[1];
|
||||
|
||||
mCx = fromView.getWidth() / 2 + relativeLeft;
|
||||
mCy = fromView.getHeight() / 2 + relativeTop;
|
||||
cx = fromView.getWidth() / 2 + relativeLeft;
|
||||
cy = fromView.getHeight() / 2 + relativeTop;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,18 +116,18 @@ public class CircularRevealChangeHandler extends AnimatorChangeHandler {
|
||||
*/
|
||||
public CircularRevealChangeHandler(int cx, int cy, long duration, boolean removesFromViewOnPush) {
|
||||
super(duration, removesFromViewOnPush);
|
||||
mCx = cx;
|
||||
mCy = cy;
|
||||
this.cx = cx;
|
||||
this.cy = cy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Animator getAnimator(@NonNull ViewGroup container, View from, View to, boolean isPush, boolean toAddedToContainer) {
|
||||
final float radius = (float) Math.hypot(mCx, mCy);
|
||||
final float radius = (float) Math.hypot(cx, cy);
|
||||
Animator animator = null;
|
||||
if (isPush && to != null) {
|
||||
animator = ViewAnimationUtils.createCircularReveal(to, mCx, mCy, 0, radius);
|
||||
animator = ViewAnimationUtils.createCircularReveal(to, cx, cy, 0, radius);
|
||||
} else if (!isPush && from != null) {
|
||||
animator = ViewAnimationUtils.createCircularReveal(from, mCx, mCy, radius, 0);
|
||||
animator = ViewAnimationUtils.createCircularReveal(from, cx, cy, radius, 0);
|
||||
}
|
||||
return animator;
|
||||
}
|
||||
@@ -138,14 +138,14 @@ public class CircularRevealChangeHandler extends AnimatorChangeHandler {
|
||||
@Override
|
||||
public void saveToBundle(@NonNull Bundle bundle) {
|
||||
super.saveToBundle(bundle);
|
||||
bundle.putInt(KEY_CX, mCx);
|
||||
bundle.putInt(KEY_CY, mCy);
|
||||
bundle.putInt(KEY_CX, cx);
|
||||
bundle.putInt(KEY_CY, cy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle(@NonNull Bundle bundle) {
|
||||
super.restoreFromBundle(bundle);
|
||||
mCx = bundle.getInt(KEY_CX);
|
||||
mCy = bundle.getInt(KEY_CY);
|
||||
cx = bundle.getInt(KEY_CX);
|
||||
cy = bundle.getInt(KEY_CY);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -32,8 +32,8 @@ public class FlipChangeHandler extends AnimatorChangeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private final long mAnimationDuration;
|
||||
private final FlipDirection mFlipDirection;
|
||||
private final long animationDuration;
|
||||
private final FlipDirection flipDirection;
|
||||
|
||||
public FlipChangeHandler() {
|
||||
this(FlipDirection.RIGHT);
|
||||
@@ -48,8 +48,8 @@ public class FlipChangeHandler extends AnimatorChangeHandler {
|
||||
}
|
||||
|
||||
public FlipChangeHandler(FlipDirection flipDirection, long animationDuration) {
|
||||
mFlipDirection = flipDirection;
|
||||
mAnimationDuration = animationDuration;
|
||||
this.flipDirection = flipDirection;
|
||||
this.animationDuration = animationDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,22 +59,22 @@ public class FlipChangeHandler extends AnimatorChangeHandler {
|
||||
if (to != null) {
|
||||
to.setAlpha(0);
|
||||
|
||||
ObjectAnimator rotation = ObjectAnimator.ofFloat(to, mFlipDirection.property, mFlipDirection.inStartRotation, 0).setDuration(mAnimationDuration);
|
||||
ObjectAnimator rotation = ObjectAnimator.ofFloat(to, flipDirection.property, flipDirection.inStartRotation, 0).setDuration(animationDuration);
|
||||
rotation.setInterpolator(new AccelerateDecelerateInterpolator());
|
||||
animatorSet.play(rotation);
|
||||
|
||||
Animator alpha = ObjectAnimator.ofFloat(to, View.ALPHA, 1).setDuration(mAnimationDuration / 2);
|
||||
alpha.setStartDelay(mAnimationDuration / 3);
|
||||
Animator alpha = ObjectAnimator.ofFloat(to, View.ALPHA, 1).setDuration(animationDuration / 2);
|
||||
alpha.setStartDelay(animationDuration / 3);
|
||||
animatorSet.play(alpha);
|
||||
}
|
||||
|
||||
if (from != null) {
|
||||
ObjectAnimator rotation = ObjectAnimator.ofFloat(from, mFlipDirection.property, 0, mFlipDirection.outEndRotation).setDuration(mAnimationDuration);
|
||||
ObjectAnimator rotation = ObjectAnimator.ofFloat(from, flipDirection.property, 0, flipDirection.outEndRotation).setDuration(animationDuration);
|
||||
rotation.setInterpolator(new AccelerateDecelerateInterpolator());
|
||||
animatorSet.play(rotation);
|
||||
|
||||
Animator alpha = ObjectAnimator.ofFloat(from, View.ALPHA, 0).setDuration(mAnimationDuration / 2);
|
||||
alpha.setStartDelay(mAnimationDuration / 3);
|
||||
Animator alpha = ObjectAnimator.ofFloat(from, View.ALPHA, 0).setDuration(animationDuration / 2);
|
||||
alpha.setStartDelay(animationDuration / 3);
|
||||
animatorSet.play(alpha);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public class FlipChangeHandler extends AnimatorChangeHandler {
|
||||
protected void resetFromView(@NonNull View from) {
|
||||
from.setAlpha(1);
|
||||
|
||||
switch (mFlipDirection) {
|
||||
switch (flipDirection) {
|
||||
case LEFT:
|
||||
case RIGHT:
|
||||
from.setRotationY(0);
|
||||
|
||||
@@ -8,11 +8,11 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class ChildController extends BaseController {
|
||||
|
||||
@@ -20,7 +20,7 @@ public class ChildController extends BaseController {
|
||||
private static final String KEY_BG_COLOR = "ChildController.bgColor";
|
||||
private static final String KEY_COLOR_IS_RES = "ChildController.colorIsResId";
|
||||
|
||||
@Bind(R.id.tv_title) TextView mTvTitle;
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
|
||||
public ChildController(String title, int backgroundColor, boolean colorIsResId) {
|
||||
this(new BundleBuilder(new Bundle())
|
||||
@@ -44,7 +44,7 @@ public class ChildController extends BaseController {
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
|
||||
mTvTitle.setText(getArgs().getString(KEY_TITLE));
|
||||
tvTitle.setText(getArgs().getString(KEY_TITLE));
|
||||
|
||||
int bgColor = getArgs().getInt(KEY_BG_COLOR);
|
||||
if (getArgs().getBoolean(KEY_COLOR_IS_RES)) {
|
||||
|
||||
+6
-6
@@ -14,14 +14,14 @@ import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.demo.widget.ElasticDragDismissFrameLayout;
|
||||
import com.bluelinelabs.conductor.demo.widget.ElasticDragDismissFrameLayout.ElasticDragDismissCallback;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.BindView;
|
||||
|
||||
@TargetApi(VERSION_CODES.LOLLIPOP)
|
||||
public class DragDismissController extends BaseController {
|
||||
|
||||
@Bind(R.id.tv_lorem_ipsum) TextView mTvLoremIpsum;
|
||||
@BindView(R.id.tv_lorem_ipsum) TextView tvLoremIpsum;
|
||||
|
||||
private final ElasticDragDismissCallback mDragDismissListener = new ElasticDragDismissCallback() {
|
||||
private final ElasticDragDismissCallback dragDismissListener = new ElasticDragDismissCallback() {
|
||||
@Override
|
||||
public void onDragDismissed() {
|
||||
overridePopHandler(new ScaleFadeChangeHandler());
|
||||
@@ -37,9 +37,9 @@ public class DragDismissController extends BaseController {
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
((ElasticDragDismissFrameLayout)view).addListener(mDragDismissListener);
|
||||
((ElasticDragDismissFrameLayout)view).addListener(dragDismissListener);
|
||||
|
||||
mTvLoremIpsum.setText("Lorem ipsum dolor sit amet, volutpat lacus egestas integer vitae, tempus potenti posuere dolore, elit cras ut vulputate pede eros. Pharetra curabitur, cum ultrices nisi nulla, non a est diamlorem in pede. Feugiat vivamus id, leo massa, pede ligula libero wisi, posuere nec interdum risus. Mauris eros. Scelerisque etiam dignissim, sem odio magna posuere libero in. Eget non posuere, rutrum nunc ut, ipsum ornare, vestibulum nisl turpis, urna interdum. Arcu mi velit. Sem dolor amet sed hymenaeos tempor. Cras felis.\n" +
|
||||
tvLoremIpsum.setText("Lorem ipsum dolor sit amet, volutpat lacus egestas integer vitae, tempus potenti posuere dolore, elit cras ut vulputate pede eros. Pharetra curabitur, cum ultrices nisi nulla, non a est diamlorem in pede. Feugiat vivamus id, leo massa, pede ligula libero wisi, posuere nec interdum risus. Mauris eros. Scelerisque etiam dignissim, sem odio magna posuere libero in. Eget non posuere, rutrum nunc ut, ipsum ornare, vestibulum nisl turpis, urna interdum. Arcu mi velit. Sem dolor amet sed hymenaeos tempor. Cras felis.\n" +
|
||||
"Tempus risus vehicula, mauris nulla interdum purus sodales suspendisse, morbi ultrices tempus vitae vestibulum porttitor, vel mus enim tellus non massa in, quis nec fermentum scelerisque sem congue dolores. Accumsan lacinia urna eu feugiat, habitasse wisi cras id nonummy sapien, a pede. Turpis ac donec, adipiscing ut faucibus, odio ut morbi, habitant volutpat lacinia. At vitae ipsum, porttitor wisi hendrerit pellentesque sapien, suspendisse pellentesque praesent sit tellus varius. At in ligula neque imperdiet eget, viverra lectus risus est sem feugiat. Diam amet non phasellus, sed enim ante etiam lorem id at, feugiat eu urna, urna posuere. Amet vel, vehicula ac in fermentum id, elit mauris dolor, eget orci in nec non in vestibulum. Tortor risus mattis, massa vel condimentum non ornare, pede nunc curabitur dui, eu dolorum luctus duis pellentesque. Nec in imperdiet ac tortor pulvinar bibendum. Parturient lacus luctus posuere, quis luctus sociis tellus iaculis.\n" +
|
||||
"Eu nec, nulla ut neque ac suspendisse, ac purus mattis pretium orci orci, penatibus sollicitudin pellentesque massa, felis et molestie natoque justo vitae. Laoreet nunc nulla augue semper, nulla ridiculus elit in quis bibendum ultrices, integer duis. Dolor ut donec ligula vehicula odio, in lacinia mattis ut quos, semper libero nulla, et euismod ut, nec curabitur turpis aliquet mauris sit a. Tellus interdum dignissim felis. Ultrices dignissim ut, enim urna adipiscing, nunc accumsan justo odio fringilla magna penatibus. Amet integer metus sollicitudin tristique libero dolor, augue nulla pellentesque, massa in suspendisse, adipiscing donec neque nunc. Malesuada non, luctus vestibulum, et at taciti orci felis. Aliquam dolor nibh erat in tincidunt in, risus suscipit integer, quis dolor quis quam. Ultrices dictum, dignissim interdum aenean pede ornare pretium, vehicula adipiscing enim nec magna mollis duis. Imperdiet dolor velit phasellus, laoreet sed ridiculus sollicitudin sit viverra metus, integer sit nunc fusce nonummy augue. Maecenas adipiscing porttitor eu risus nunc malesuada, quo vitae blandit amet feugiat nunc. Pede hac duis in.\n" +
|
||||
"Lorem posuere ridiculus donec, volutpat vehicula erat nunc ut, justo occaecati vivamus aliquam massa, felis etiam, sed feugiat molestie eu. Et leo non dignissim nam. Fringilla pretium suspendisse vitae nascetur massa hymenaeos, lectus ut senectus amet, a enim. Pellentesque integer erat, mauris morbi pellentesque, sodales phasellus turpis purus nulla porta, massa vulputate consectetuer habitasse malesuada pulvinar, vehicula in elit eros interdum ut. Et enim vulputate, aliquam donec ullamcorper et, vel consequat tincidunt. Ipsum quam sed ante quis at, ultrices eget. Rutrum qui et velit possimus in, odio amet ut adipiscing sed nec, a tellus ut, quam molestie. Nisl adipiscing euismod nec, eget facilisis ac sit. Suspendisse elit amet consequat dolor senectus vivamus, at scelerisque erat, odio doloribus velit et felis neque, turpis adipiscing, arcu varius placerat leo.");
|
||||
@@ -49,7 +49,7 @@ public class DragDismissController extends BaseController {
|
||||
protected void onDestroyView(View view) {
|
||||
super.onDestroyView(view);
|
||||
|
||||
((ElasticDragDismissFrameLayout)view).removeListener(mDragDismissListener);
|
||||
((ElasticDragDismissFrameLayout)view).removeListener(dragDismissListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+60
-52
@@ -22,15 +22,14 @@ import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bluelinelabs.conductor.ChildControllerTransaction;
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
import com.bluelinelabs.conductor.ControllerTransaction.ControllerChangeType;
|
||||
import com.bluelinelabs.conductor.ControllerChangeType;
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler;
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
@@ -39,12 +38,14 @@ public class HomeController extends BaseController {
|
||||
public enum HomeDemoModel {
|
||||
NAVIGATION("Navigation Demos", R.color.red_300),
|
||||
TRANSITIONS("Transition Demos", R.color.blue_grey_300),
|
||||
OVERLAY("Overlay Controller", R.color.purple_300),
|
||||
CHILD_CONTROLLERS("Child Controllers", R.color.orange_300),
|
||||
VIEW_PAGER("ViewPager", R.color.green_300),
|
||||
TARGET_CONTROLLER("Target Controller", R.color.pink_300),
|
||||
MULTIPLE_CHILD_ROUTERS("Multiple Child Routers", R.color.deep_orange_300),
|
||||
MASTER_DETAIL("Master Detail", R.color.grey_300),
|
||||
DRAG_DISMISS("Drag Dismiss", R.color.lime_300),
|
||||
RX_LIFECYCLE("Rx Lifecycle", R.color.teal_300);
|
||||
RX_LIFECYCLE("Rx Lifecycle", R.color.teal_300),
|
||||
OVERLAY("Overlay Controller", R.color.purple_300);
|
||||
|
||||
String title;
|
||||
@ColorRes int color;
|
||||
@@ -55,7 +56,8 @@ public class HomeController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
@Bind(R.id.recycler_view) RecyclerView mRecyclerView;
|
||||
@BindView(R.id.recycler_view) RecyclerView recyclerView;
|
||||
@BindView(R.id.overlay_root) ViewGroup overlayRoot;
|
||||
|
||||
public HomeController() {
|
||||
setHasOptionsMenu(true);
|
||||
@@ -71,15 +73,15 @@ public class HomeController extends BaseController {
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
|
||||
mRecyclerView.setHasFixedSize(true);
|
||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
|
||||
mRecyclerView.setAdapter(new HomeAdapter(LayoutInflater.from(view.getContext()), HomeDemoModel.values()));
|
||||
recyclerView.setHasFixedSize(true);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
|
||||
recyclerView.setAdapter(new HomeAdapter(LayoutInflater.from(view.getContext()), HomeDemoModel.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
inflater.inflate(R.menu.home, menu);
|
||||
inflater.inflate(R.menu.home, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,11 +115,11 @@ public class HomeController extends BaseController {
|
||||
content.append("\n\n");
|
||||
content.append(link);
|
||||
|
||||
addChildController(ChildControllerTransaction.builder(new OverlayController(content), R.id.home_root)
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler())
|
||||
.addToLocalBackstack(true)
|
||||
.build());
|
||||
getChildRouter(overlayRoot, null)
|
||||
.setPopsLastView(true)
|
||||
.setRoot(RouterTransaction.with(new OverlayController(content))
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
@@ -131,85 +133,91 @@ public class HomeController extends BaseController {
|
||||
void onModelRowClick(HomeDemoModel model) {
|
||||
switch (model) {
|
||||
case NAVIGATION:
|
||||
getRouter().pushController(RouterTransaction.builder(new NavigationDemoController(0))
|
||||
getRouter().pushController(RouterTransaction.with(new NavigationDemoController(0, true))
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler())
|
||||
.tag(NavigationDemoController.TAG_UP_TRANSACTION)
|
||||
.build());
|
||||
);
|
||||
break;
|
||||
case TRANSITIONS:
|
||||
getRouter().pushController(TransitionDemoController.getRouterTransaction(0, this));
|
||||
break;
|
||||
case TARGET_CONTROLLER:
|
||||
getRouter().pushController(RouterTransaction.builder(new TargetDisplayController())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler())
|
||||
.build());
|
||||
getRouter().pushController(
|
||||
RouterTransaction.with(new TargetDisplayController())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case VIEW_PAGER:
|
||||
getRouter().pushController(RouterTransaction.builder(new PagerController())
|
||||
getRouter().pushController(RouterTransaction.with(new PagerController())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler())
|
||||
.build());
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case CHILD_CONTROLLERS:
|
||||
getRouter().pushController(RouterTransaction.builder(new ParentController())
|
||||
getRouter().pushController(RouterTransaction.with(new ParentController())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler())
|
||||
.build());
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case OVERLAY:
|
||||
addChildController(ChildControllerTransaction.builder(new OverlayController("I'm an Overlay!"), R.id.home_root)
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler())
|
||||
.addToLocalBackstack(true)
|
||||
.build());
|
||||
getChildRouter(overlayRoot, null)
|
||||
.setPopsLastView(true)
|
||||
.setRoot(RouterTransaction.with(new OverlayController("I'm an overlay!"))
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case DRAG_DISMISS:
|
||||
getRouter().pushController(RouterTransaction.builder(new DragDismissController())
|
||||
getRouter().pushController(RouterTransaction.with(new DragDismissController())
|
||||
.pushChangeHandler(new FadeChangeHandler(false))
|
||||
.popChangeHandler(new FadeChangeHandler())
|
||||
.build());
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case RX_LIFECYCLE:
|
||||
getRouter().pushController(RouterTransaction.builder(new RxLifecycleController())
|
||||
getRouter().pushController(RouterTransaction.with(new RxLifecycleController())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler())
|
||||
.build());
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case MULTIPLE_CHILD_ROUTERS:
|
||||
getRouter().pushController(RouterTransaction.with(new MultipleChildRouterController())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case MASTER_DETAIL:
|
||||
getRouter().pushController(RouterTransaction.with(new MasterDetailListController())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.ViewHolder> {
|
||||
|
||||
private final LayoutInflater mInflater;
|
||||
private final HomeDemoModel[] mItems;
|
||||
private final LayoutInflater inflater;
|
||||
private final HomeDemoModel[] items;
|
||||
|
||||
public HomeAdapter(LayoutInflater inflater, HomeDemoModel[] items) {
|
||||
mInflater = inflater;
|
||||
mItems = items;
|
||||
this.inflater = inflater;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(mInflater.inflate(R.layout.row_home, parent, false));
|
||||
return new ViewHolder(inflater.inflate(R.layout.row_home, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
holder.bind(mItems[position]);
|
||||
holder.bind(items[position]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mItems.length;
|
||||
return items.length;
|
||||
}
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
@Bind(R.id.tv_title) TextView mTvTitle;
|
||||
@Bind(R.id.img_dot) ImageView mImgDot;
|
||||
private HomeDemoModel mModel;
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
@BindView(R.id.img_dot) ImageView imgDot;
|
||||
private HomeDemoModel model;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
@@ -217,14 +225,14 @@ public class HomeController extends BaseController {
|
||||
}
|
||||
|
||||
void bind(HomeDemoModel item) {
|
||||
mModel = item;
|
||||
mTvTitle.setText(item.title);
|
||||
mImgDot.getDrawable().setColorFilter(ContextCompat.getColor(getActivity(), item.color), Mode.SRC_ATOP);
|
||||
model = item;
|
||||
tvTitle.setText(item.title);
|
||||
imgDot.getDrawable().setColorFilter(ContextCompat.getColor(getActivity(), item.color), Mode.SRC_ATOP);
|
||||
}
|
||||
|
||||
@OnClick(R.id.row_root)
|
||||
void onRowClick() {
|
||||
onModelRowClick(mModel);
|
||||
onModelRowClick(model);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class MasterDetailListController extends BaseController {
|
||||
|
||||
private static final String KEY_SELECTED_INDEX = "MasterDetailListController.selectedIndex";
|
||||
|
||||
public enum DetailItemModel {
|
||||
ONE("Item 1", "This is a quick demo of master/detail flow using Conductor. In portrait mode you'll see a standard list. In landscape, you'll see a two-pane layout.", R.color.green_300),
|
||||
TWO("Item 2", "This is another item.", R.color.cyan_300),
|
||||
THREE("Item 3", "Wow, a 3rd item!", R.color.deep_purple_300);
|
||||
|
||||
String title;
|
||||
String detail;
|
||||
int backgroundColor;
|
||||
|
||||
DetailItemModel(String title, String detail, int backgroundColor) {
|
||||
this.title = title;
|
||||
this.detail = detail;
|
||||
this.backgroundColor = backgroundColor;
|
||||
}
|
||||
}
|
||||
|
||||
@BindView(R.id.recycler_view) RecyclerView recyclerView;
|
||||
@Nullable @BindView(R.id.detail_container) ViewGroup detailContainer;
|
||||
|
||||
private int selectedIndex;
|
||||
private boolean twoPaneView;
|
||||
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_master_detail_list, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
|
||||
recyclerView.setHasFixedSize(true);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
|
||||
recyclerView.setAdapter(new DetailItemAdapter(LayoutInflater.from(view.getContext()), DetailItemModel.values()));
|
||||
|
||||
twoPaneView = (detailContainer != null);
|
||||
if (twoPaneView) {
|
||||
onRowSelected(selectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putInt(KEY_SELECTED_INDEX, selectedIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
|
||||
selectedIndex = savedInstanceState.getInt(KEY_SELECTED_INDEX);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "Master/Detail Flow";
|
||||
}
|
||||
|
||||
void onRowSelected(int index) {
|
||||
selectedIndex = index;
|
||||
|
||||
DetailItemModel model = DetailItemModel.values()[index];
|
||||
ChildController controller = new ChildController(model.detail, model.backgroundColor, true);
|
||||
|
||||
if (twoPaneView) {
|
||||
getChildRouter(detailContainer, null).setRoot(RouterTransaction.with(controller));
|
||||
} else {
|
||||
getRouter().pushController(RouterTransaction.with(controller)
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
}
|
||||
|
||||
class DetailItemAdapter extends RecyclerView.Adapter<DetailItemAdapter.ViewHolder> {
|
||||
|
||||
private final LayoutInflater inflater;
|
||||
private final DetailItemModel[] items;
|
||||
|
||||
public DetailItemAdapter(LayoutInflater inflater, DetailItemModel[] items) {
|
||||
this.inflater = inflater;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(inflater.inflate(R.layout.row_detail_item, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
holder.bind(items[position], position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.length;
|
||||
}
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
@BindView(R.id.row_root) View root;
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
private int position;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
|
||||
void bind(DetailItemModel item, int position) {
|
||||
tvTitle.setText(item.title);
|
||||
this.position = position;
|
||||
|
||||
if (twoPaneView && position == selectedIndex) {
|
||||
root.setBackgroundColor(ContextCompat.getColor(root.getContext(), R.color.grey_400));
|
||||
} else {
|
||||
root.setBackgroundColor(ContextCompat.getColor(root.getContext(), android.R.color.transparent));
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.row_root)
|
||||
void onRowClick() {
|
||||
onRowSelected(position);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.Router;
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
|
||||
import butterknife.BindViews;
|
||||
|
||||
public class MultipleChildRouterController extends BaseController {
|
||||
|
||||
@BindViews({R.id.container_0, R.id.container_1, R.id.container_2}) ViewGroup[] childContainers;
|
||||
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_multiple_child_routers, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
|
||||
for (ViewGroup childContainer : childContainers) {
|
||||
Router childRouter = getChildRouter(childContainer, null).setPopsLastView(false);
|
||||
if (!childRouter.hasRootController()) {
|
||||
childRouter.setRoot(RouterTransaction.with(new NavigationDemoController(0, false)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "Child Router Demo";
|
||||
}
|
||||
|
||||
}
|
||||
+17
-11
@@ -14,7 +14,7 @@ import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
import com.bluelinelabs.conductor.demo.util.ColorUtil;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class NavigationDemoController extends BaseController {
|
||||
@@ -22,20 +22,24 @@ public class NavigationDemoController extends BaseController {
|
||||
public static final String TAG_UP_TRANSACTION = "NavigationDemoController.up";
|
||||
|
||||
private static final String KEY_INDEX = "NavigationDemoController.index";
|
||||
private static final String KEY_DISPLAY_UP = "NavigationDemoController.displayUp";
|
||||
|
||||
@Bind(R.id.tv_title) TextView mTvTitle;
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
|
||||
private int mIndex;
|
||||
private int index;
|
||||
private boolean displayUp;
|
||||
|
||||
public NavigationDemoController(int index) {
|
||||
public NavigationDemoController(int index, boolean displayUpButton) {
|
||||
this(new BundleBuilder(new Bundle())
|
||||
.putInt(KEY_INDEX, index)
|
||||
.putBoolean(KEY_DISPLAY_UP, displayUpButton)
|
||||
.build());
|
||||
}
|
||||
|
||||
public NavigationDemoController(Bundle args) {
|
||||
super(args);
|
||||
mIndex = args.getInt(KEY_INDEX);
|
||||
index = args.getInt(KEY_INDEX);
|
||||
displayUp = args.getBoolean(KEY_DISPLAY_UP);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -48,8 +52,12 @@ public class NavigationDemoController extends BaseController {
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
|
||||
view.setBackgroundColor(ColorUtil.getMaterialColor(getResources(), mIndex));
|
||||
mTvTitle.setText(getResources().getString(R.string.navigation_title, mIndex));
|
||||
if (!displayUp) {
|
||||
view.findViewById(R.id.btn_up).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
view.setBackgroundColor(ColorUtil.getMaterialColor(getResources(), index));
|
||||
tvTitle.setText(getResources().getString(R.string.navigation_title, index));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,11 +66,9 @@ public class NavigationDemoController extends BaseController {
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_next) void onNextClicked() {
|
||||
getRouter().pushController(RouterTransaction.builder(new NavigationDemoController(mIndex + 1))
|
||||
getRouter().pushController(RouterTransaction.with(new NavigationDemoController(index + 1, displayUp))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler())
|
||||
.build()
|
||||
);
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_up) void onUpClicked() {
|
||||
|
||||
+4
-4
@@ -12,13 +12,13 @@ import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class OverlayController extends BaseController {
|
||||
|
||||
private static final String KEY_TEXT = "OverlayController.text";
|
||||
|
||||
@Bind(R.id.text_view) TextView mTextView;
|
||||
@BindView(R.id.text_view) TextView textView;
|
||||
|
||||
public OverlayController(CharSequence text) {
|
||||
this(new BundleBuilder(new Bundle())
|
||||
@@ -39,8 +39,8 @@ public class OverlayController extends BaseController {
|
||||
@Override
|
||||
public void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
mTextView.setText(getArgs().getCharSequence(KEY_TEXT));
|
||||
mTextView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
textView.setText(getArgs().getCharSequence(KEY_TEXT));
|
||||
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-25
@@ -2,9 +2,6 @@ package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.design.widget.TabLayout.OnTabSelectedListener;
|
||||
import android.support.design.widget.TabLayout.Tab;
|
||||
import android.support.design.widget.TabLayout.TabLayoutOnPageChangeListener;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -15,19 +12,19 @@ import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.support.ControllerPagerAdapter;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class PagerController extends BaseController {
|
||||
|
||||
private int[] PAGE_COLORS = new int[]{R.color.green_300, R.color.cyan_300, R.color.deep_purple_300, R.color.lime_300, R.color.red_300};
|
||||
|
||||
@Bind(R.id.tab_layout) TabLayout mTabLayout;
|
||||
@Bind(R.id.view_pager) ViewPager mViewPager;
|
||||
@BindView(R.id.tab_layout) TabLayout tabLayout;
|
||||
@BindView(R.id.view_pager) ViewPager viewPager;
|
||||
|
||||
private final ControllerPagerAdapter mPagerAdapter;
|
||||
private final ControllerPagerAdapter pagerAdapter;
|
||||
|
||||
public PagerController() {
|
||||
mPagerAdapter = new ControllerPagerAdapter(this) {
|
||||
pagerAdapter = new ControllerPagerAdapter(this, false) {
|
||||
@Override
|
||||
public Controller getItem(int position) {
|
||||
return new ChildController(String.format("Child #%d (Swipe to see more)", position), PAGE_COLORS[position], true);
|
||||
@@ -48,27 +45,13 @@ public class PagerController extends BaseController {
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
mTabLayout.setTabsFromPagerAdapter(mPagerAdapter);
|
||||
mViewPager.setAdapter(mPagerAdapter);
|
||||
|
||||
mViewPager.addOnPageChangeListener(new TabLayoutOnPageChangeListener(mTabLayout));
|
||||
mTabLayout.setOnTabSelectedListener(new OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(Tab tab) {
|
||||
mViewPager.setCurrentItem(tab.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(Tab tab) { }
|
||||
|
||||
@Override
|
||||
public void onTabReselected(Tab tab) { }
|
||||
});
|
||||
viewPager.setAdapter(pagerAdapter);
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroyView(View view) {
|
||||
mViewPager.setAdapter(null);
|
||||
viewPager.setAdapter(null);
|
||||
super.onDestroyView(view);
|
||||
}
|
||||
|
||||
|
||||
+40
-37
@@ -1,14 +1,16 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.ChildControllerTransaction;
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
import com.bluelinelabs.conductor.ControllerTransaction.ControllerChangeType;
|
||||
import com.bluelinelabs.conductor.ControllerChangeType;
|
||||
import com.bluelinelabs.conductor.Router;
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler;
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
@@ -17,7 +19,7 @@ import com.bluelinelabs.conductor.demo.util.ColorUtil;
|
||||
public class ParentController extends BaseController {
|
||||
|
||||
private static final int NUMBER_OF_CHILDREN = 5;
|
||||
private boolean mFinishing;
|
||||
private boolean finishing;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
@@ -35,31 +37,53 @@ public class ParentController extends BaseController {
|
||||
}
|
||||
|
||||
private void addChild(final int index) {
|
||||
String tag = Integer.toString(index);
|
||||
|
||||
if (getChildController(tag) == null) {
|
||||
int frameId = getResources().getIdentifier("child_content_" + (index + 1), "id", getActivity().getPackageName());
|
||||
@IdRes final int frameId = getResources().getIdentifier("child_content_" + (index + 1), "id", getActivity().getPackageName());
|
||||
final ViewGroup container = (ViewGroup)getView().findViewById(frameId);
|
||||
final Router childRouter = getChildRouter(container, null).setPopsLastView(true);
|
||||
|
||||
if (!childRouter.hasRootController()) {
|
||||
ChildController childController = new ChildController("Child Controller #" + index, ColorUtil.getMaterialColor(getResources(), index), false);
|
||||
addChildController(ChildControllerTransaction.builder(childController, frameId)
|
||||
|
||||
childController.addLifecycleListener(new LifecycleListener() {
|
||||
@Override
|
||||
public void onChangeEnd(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
if (changeType == ControllerChangeType.PUSH_ENTER && index < NUMBER_OF_CHILDREN - 1) {
|
||||
addChild(index + 1);
|
||||
} else if (changeType == ControllerChangeType.POP_EXIT) {
|
||||
if (index > 0) {
|
||||
removeChild(index - 1);
|
||||
} else {
|
||||
getRouter().popController(ParentController.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
childRouter.setRoot(RouterTransaction.with(childController)
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler())
|
||||
.tag(tag)
|
||||
.build());
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
}
|
||||
}
|
||||
|
||||
private void removeChild(int index) {
|
||||
removeChildController(getChildControllers().get(index));
|
||||
removeChildRouter(getChildRouters().get(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleBack() {
|
||||
if (getChildControllers().size() == NUMBER_OF_CHILDREN && !mFinishing) {
|
||||
mFinishing = true;
|
||||
removeChild(getChildControllers().size() - 1);
|
||||
int childControllers = 0;
|
||||
for (Router childRouter : getChildRouters()) {
|
||||
if (childRouter.hasRootController()) {
|
||||
childControllers++;
|
||||
}
|
||||
}
|
||||
|
||||
if (childControllers != NUMBER_OF_CHILDREN || finishing) {
|
||||
return true;
|
||||
} else {
|
||||
finishing = true;
|
||||
return super.handleBack();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,25 +91,4 @@ public class ParentController extends BaseController {
|
||||
return "Parent/Child Demo";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChildController(ChildControllerTransaction transaction) {
|
||||
final int index = Integer.parseInt(transaction.tag);
|
||||
|
||||
transaction.controller.addLifecycleListener(new LifecycleListener() {
|
||||
@Override
|
||||
public void onChangeEnd(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
if (changeType == ControllerChangeType.PUSH_ENTER && index < NUMBER_OF_CHILDREN - 1) {
|
||||
addChild(index + 1);
|
||||
} else if (changeType == ControllerChangeType.POP_EXIT) {
|
||||
if (index > 0) {
|
||||
removeChild(index - 1);
|
||||
} else {
|
||||
getRouter().popController(ParentController.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
super.addChildController(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-11
@@ -15,7 +15,7 @@ import com.bluelinelabs.conductor.rxlifecycle.ControllerEvent;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
import rx.Observable;
|
||||
import rx.functions.Action0;
|
||||
@@ -27,7 +27,7 @@ public class RxLifecycleController extends BaseController {
|
||||
|
||||
private static final String TAG = "RxLifecycleController";
|
||||
|
||||
@Bind(R.id.tv_title) TextView mTvTitle;
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
|
||||
public RxLifecycleController() {
|
||||
|
||||
@@ -51,7 +51,7 @@ public class RxLifecycleController extends BaseController {
|
||||
public void onViewBound(@NonNull View view) {
|
||||
Log.i(TAG, "onCreateView() called");
|
||||
|
||||
mTvTitle.setText(getResources().getString(R.string.rxlifecycle_title, TAG));
|
||||
tvTitle.setText(getResources().getString(R.string.rxlifecycle_title, TAG));
|
||||
|
||||
Observable.interval(1, TimeUnit.SECONDS)
|
||||
.doOnUnsubscribe(new Action0() {
|
||||
@@ -126,20 +126,16 @@ public class RxLifecycleController extends BaseController {
|
||||
@OnClick(R.id.btn_next_release_view) void onNextWithReleaseClicked() {
|
||||
setRetainViewMode(RetainViewMode.RELEASE_DETACH);
|
||||
|
||||
getRouter().pushController(RouterTransaction.builder(new TextController("Logcat should now report that the observables from onAttach() and onViewBound() have been unsubscribed from, while the constructor observable is still running."))
|
||||
getRouter().pushController(RouterTransaction.with(new TextController("Logcat should now report that the observables from onAttach() and onViewBound() have been unsubscribed from, while the constructor observable is still running."))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler())
|
||||
.build()
|
||||
);
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_next_retain_view) void onNextWithRetainClicked() {
|
||||
setRetainViewMode(RetainViewMode.RETAIN_DETACH);
|
||||
|
||||
getRouter().pushController(RouterTransaction.builder(new TextController("Logcat should now report that the observables from onAttach() has been unsubscribed from, while the constructor and onViewBound() observables are still running."))
|
||||
getRouter().pushController(RouterTransaction.with(new TextController("Logcat should now report that the observables from onAttach() has been unsubscribed from, while the constructor and onViewBound() observables are still running."))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler())
|
||||
.build()
|
||||
);
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
}
|
||||
|
||||
+23
-19
@@ -18,8 +18,9 @@ import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.TargetTitleEntryController.TargetTitleEntryControllerListener;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class TargetDisplayController extends BaseController implements TargetTitleEntryControllerListener {
|
||||
@@ -29,11 +30,11 @@ public class TargetDisplayController extends BaseController implements TargetTit
|
||||
private static final String KEY_SELECTED_TEXT = "TargetDisplayController.selectedText";
|
||||
private static final String KEY_SELECTED_IMAGE = "TargetDisplayController.selectedImage";
|
||||
|
||||
@Bind(R.id.tv_selection) TextView mTvSelection;
|
||||
@Bind(R.id.image_view) ImageView mImageView;
|
||||
@BindView(R.id.tv_selection) TextView tvSelection;
|
||||
@BindView(R.id.image_view) ImageView imageView;
|
||||
|
||||
private String mSelectedText;
|
||||
private Uri mImageUri;
|
||||
private String selectedText;
|
||||
private Uri imageUri;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
@@ -42,10 +43,9 @@ public class TargetDisplayController extends BaseController implements TargetTit
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_pick_title) void launchTitlePicker() {
|
||||
getRouter().pushController(RouterTransaction.builder(new TargetTitleEntryController(this))
|
||||
getRouter().pushController(RouterTransaction.with(new TargetTitleEntryController(this))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler())
|
||||
.build());
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_pick_image) void launchImagePicker() {
|
||||
@@ -57,14 +57,14 @@ public class TargetDisplayController extends BaseController implements TargetTit
|
||||
|
||||
@Override
|
||||
public void onTitlePicked(String option) {
|
||||
mSelectedText = option;
|
||||
selectedText = option;
|
||||
setTextView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == REQUEST_SELECT_IMAGE && resultCode == Activity.RESULT_OK) {
|
||||
mImageUri = data.getData();
|
||||
imageUri = data.getData();
|
||||
setImageView();
|
||||
}
|
||||
}
|
||||
@@ -79,18 +79,18 @@ public class TargetDisplayController extends BaseController implements TargetTit
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString(KEY_SELECTED_TEXT, mSelectedText);
|
||||
outState.putString(KEY_SELECTED_IMAGE, mImageUri != null ? mImageUri.toString() : null);
|
||||
outState.putString(KEY_SELECTED_TEXT, selectedText);
|
||||
outState.putString(KEY_SELECTED_IMAGE, imageUri != null ? imageUri.toString() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
mSelectedText = savedInstanceState.getString(KEY_SELECTED_TEXT);
|
||||
selectedText = savedInstanceState.getString(KEY_SELECTED_TEXT);
|
||||
|
||||
String uriString = savedInstanceState.getString(KEY_SELECTED_IMAGE);
|
||||
if (!TextUtils.isEmpty(uriString)) {
|
||||
mImageUri = Uri.parse(uriString);
|
||||
imageUri = Uri.parse(uriString);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,15 +100,19 @@ public class TargetDisplayController extends BaseController implements TargetTit
|
||||
}
|
||||
|
||||
private void setImageView() {
|
||||
mImageView.setImageURI(mImageUri);
|
||||
Picasso.with(getActivity())
|
||||
.load(imageUri)
|
||||
.fit()
|
||||
.centerCrop()
|
||||
.into(imageView);
|
||||
}
|
||||
|
||||
private void setTextView() {
|
||||
if (mTvSelection != null) {
|
||||
if (!TextUtils.isEmpty(mSelectedText)) {
|
||||
mTvSelection.setText(mSelectedText);
|
||||
if (tvSelection != null) {
|
||||
if (!TextUtils.isEmpty(selectedText)) {
|
||||
tvSelection.setText(selectedText);
|
||||
} else {
|
||||
mTvSelection.setText("Press pick title to set this title, or pick image to fill in the image view.");
|
||||
tvSelection.setText("Press pick title to set this title, or pick image to fill in the image view.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-3
@@ -1,16 +1,18 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class TargetTitleEntryController extends BaseController {
|
||||
@@ -19,7 +21,7 @@ public class TargetTitleEntryController extends BaseController {
|
||||
void onTitlePicked(String option);
|
||||
}
|
||||
|
||||
@Bind(R.id.edit_text) EditText mEditText;
|
||||
@BindView(R.id.edit_text) EditText editText;
|
||||
|
||||
public <T extends Controller & TargetTitleEntryControllerListener> TargetTitleEntryController(T targetController) {
|
||||
setTargetController(targetController);
|
||||
@@ -27,6 +29,12 @@ public class TargetTitleEntryController extends BaseController {
|
||||
|
||||
public TargetTitleEntryController() { }
|
||||
|
||||
@Override
|
||||
protected void onDetach(@NonNull View view) {
|
||||
InputMethodManager imm = (InputMethodManager) editText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
@@ -41,7 +49,7 @@ public class TargetTitleEntryController extends BaseController {
|
||||
@OnClick(R.id.btn_use_title) void optionPicked() {
|
||||
Controller targetController = getTargetController();
|
||||
if (targetController != null) {
|
||||
((TargetTitleEntryControllerListener)targetController).onTitlePicked(mEditText.getText().toString());
|
||||
((TargetTitleEntryControllerListener)targetController).onTitlePicked(editText.getText().toString());
|
||||
getRouter().popController(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,17 +7,17 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class TextController extends BaseController {
|
||||
|
||||
private static final String KEY_TEXT = "TextController.text";
|
||||
|
||||
@Bind(R.id.text_view) TextView mTextView;
|
||||
@BindView(R.id.text_view) TextView textView;
|
||||
|
||||
public TextController(String text) {
|
||||
this(new BundleBuilder(new Bundle())
|
||||
@@ -39,7 +39,7 @@ public class TextController extends BaseController {
|
||||
@Override
|
||||
public void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
mTextView.setText(getArgs().getString(KEY_TEXT));
|
||||
textView.setText(getArgs().getString(KEY_TEXT));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+18
-20
@@ -25,7 +25,7 @@ import com.bluelinelabs.conductor.demo.changehandler.FlipChangeHandler;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
@@ -56,11 +56,11 @@ public class TransitionDemoController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
@Bind(R.id.tv_title) TextView mTvTitle;
|
||||
@Bind(R.id.btn_next) FloatingActionButton mBtnNext;
|
||||
@Bind(R.id.transition_root) View mContainerView;
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
@BindView(R.id.btn_next) FloatingActionButton btnNext;
|
||||
@BindView(R.id.transition_root) View containerView;
|
||||
|
||||
private TransitionDemo mTransitionDemo;
|
||||
private TransitionDemo transitionDemo;
|
||||
|
||||
public TransitionDemoController(int index) {
|
||||
this(new BundleBuilder(new Bundle())
|
||||
@@ -70,13 +70,13 @@ public class TransitionDemoController extends BaseController {
|
||||
|
||||
public TransitionDemoController(Bundle args) {
|
||||
super(args);
|
||||
mTransitionDemo = TransitionDemo.fromIndex(args.getInt(KEY_INDEX));
|
||||
transitionDemo = TransitionDemo.fromIndex(args.getInt(KEY_INDEX));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(mTransitionDemo.layoutId, container, false);
|
||||
return inflater.inflate(transitionDemo.layoutId, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,11 +84,11 @@ public class TransitionDemoController extends BaseController {
|
||||
super.onViewBound(view);
|
||||
|
||||
View bgView = ButterKnife.findById(view, R.id.bg_view);
|
||||
if (mTransitionDemo.colorId != 0 && bgView != null) {
|
||||
bgView.setBackgroundColor(ContextCompat.getColor(getActivity(), mTransitionDemo.colorId));
|
||||
if (transitionDemo.colorId != 0 && bgView != null) {
|
||||
bgView.setBackgroundColor(ContextCompat.getColor(getActivity(), transitionDemo.colorId));
|
||||
}
|
||||
|
||||
final int nextIndex = mTransitionDemo.ordinal() + 1;
|
||||
final int nextIndex = transitionDemo.ordinal() + 1;
|
||||
int buttonColor = 0;
|
||||
if (nextIndex < TransitionDemo.values().length) {
|
||||
buttonColor = TransitionDemo.fromIndex(nextIndex).colorId;
|
||||
@@ -97,8 +97,8 @@ public class TransitionDemoController extends BaseController {
|
||||
buttonColor = TransitionDemo.fromIndex(0).colorId;
|
||||
}
|
||||
|
||||
mBtnNext.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(getActivity(), buttonColor)));
|
||||
mTvTitle.setText(mTransitionDemo.title);
|
||||
btnNext.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(getActivity(), buttonColor)));
|
||||
tvTitle.setText(transitionDemo.title);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,7 +107,7 @@ public class TransitionDemoController extends BaseController {
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_next) void onNextClicked() {
|
||||
final int nextIndex = mTransitionDemo.ordinal() + 1;
|
||||
final int nextIndex = transitionDemo.ordinal() + 1;
|
||||
|
||||
if (nextIndex < TransitionDemo.values().length) {
|
||||
getRouter().pushController(getRouterTransaction(nextIndex, this));
|
||||
@@ -117,12 +117,12 @@ public class TransitionDemoController extends BaseController {
|
||||
}
|
||||
|
||||
public ControllerChangeHandler getChangeHandler(Controller from) {
|
||||
switch (mTransitionDemo) {
|
||||
switch (transitionDemo) {
|
||||
case VERTICAL:
|
||||
return new VerticalChangeHandler();
|
||||
case CIRCULAR:
|
||||
TransitionDemoController demoController = (TransitionDemoController)from;
|
||||
return new CircularRevealChangeHandlerCompat(demoController.mBtnNext, demoController.mContainerView);
|
||||
return new CircularRevealChangeHandlerCompat(demoController.btnNext, demoController.containerView);
|
||||
case FADE:
|
||||
return new FadeChangeHandler();
|
||||
case FLIP:
|
||||
@@ -140,12 +140,10 @@ public class TransitionDemoController extends BaseController {
|
||||
|
||||
public static RouterTransaction getRouterTransaction(int index, Controller fromController) {
|
||||
TransitionDemoController toController = new TransitionDemoController(index);
|
||||
ControllerChangeHandler changeHandler = toController.getChangeHandler(fromController);
|
||||
|
||||
return RouterTransaction.builder(toController)
|
||||
.pushChangeHandler(changeHandler)
|
||||
.popChangeHandler(changeHandler)
|
||||
.build();
|
||||
return RouterTransaction.with(toController)
|
||||
.pushChangeHandler(toController.getChangeHandler(fromController))
|
||||
.popChangeHandler(toController.getChangeHandler(fromController));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
@@ -5,6 +5,7 @@ import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.view.View;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.bluelinelabs.conductor.demo.ActionBarProvider;
|
||||
|
||||
public abstract class BaseController extends RefWatchingController {
|
||||
@@ -29,6 +30,14 @@ public abstract class BaseController extends RefWatchingController {
|
||||
}
|
||||
|
||||
protected void setTitle() {
|
||||
Controller parentController = getParentController();
|
||||
while (parentController != null) {
|
||||
if (parentController instanceof BaseController && ((BaseController)parentController).getTitle() != null) {
|
||||
return;
|
||||
}
|
||||
parentController = parentController.getParentController();
|
||||
}
|
||||
|
||||
String title = getTitle();
|
||||
ActionBar actionBar = getActionBar();
|
||||
if (title != null && actionBar != null) {
|
||||
|
||||
+5
-2
@@ -9,9 +9,12 @@ import android.view.ViewGroup;
|
||||
import com.bluelinelabs.conductor.rxlifecycle.RxController;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public abstract class ButterKnifeController extends RxController {
|
||||
|
||||
private Unbinder unbinder;
|
||||
|
||||
protected ButterKnifeController() { }
|
||||
protected ButterKnifeController(Bundle args) {
|
||||
super(args);
|
||||
@@ -23,7 +26,7 @@ public abstract class ButterKnifeController extends RxController {
|
||||
@Override
|
||||
protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
View view = inflateView(inflater, container);
|
||||
ButterKnife.bind(this, view);
|
||||
unbinder = ButterKnife.bind(this, view);
|
||||
onViewBound(view);
|
||||
return view;
|
||||
}
|
||||
@@ -33,7 +36,7 @@ public abstract class ButterKnifeController extends RxController {
|
||||
@Override
|
||||
protected void onDestroyView(View view) {
|
||||
super.onDestroyView(view);
|
||||
ButterKnife.unbind(this);
|
||||
unbinder.unbind();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,164 +9,164 @@ import java.util.ArrayList;
|
||||
|
||||
public class BundleBuilder {
|
||||
|
||||
private final Bundle mBundle;
|
||||
private final Bundle bundle;
|
||||
|
||||
public BundleBuilder(Bundle bundle) {
|
||||
mBundle = bundle;
|
||||
this.bundle = bundle;
|
||||
}
|
||||
|
||||
public BundleBuilder putAll(Bundle bundle) {
|
||||
mBundle.putAll(bundle);
|
||||
this.bundle.putAll(bundle);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putBoolean(String key, boolean value) {
|
||||
mBundle.putBoolean(key, value);
|
||||
bundle.putBoolean(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putBooleanArray(String key, boolean[] value) {
|
||||
mBundle.putBooleanArray(key, value);
|
||||
bundle.putBooleanArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putDouble(String key, double value) {
|
||||
mBundle.putDouble(key, value);
|
||||
bundle.putDouble(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putDoubleArray(String key, double[] value) {
|
||||
mBundle.putDoubleArray(key, value);
|
||||
bundle.putDoubleArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putLong(String key, long value) {
|
||||
mBundle.putLong(key, value);
|
||||
bundle.putLong(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putLongArray(String key, long[] value) {
|
||||
mBundle.putLongArray(key, value);
|
||||
bundle.putLongArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putString(String key, String value) {
|
||||
mBundle.putString(key, value);
|
||||
bundle.putString(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putStringArray(String key, String[] value) {
|
||||
mBundle.putStringArray(key, value);
|
||||
bundle.putStringArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putBundle(String key, Bundle value) {
|
||||
mBundle.putBundle(key, value);
|
||||
bundle.putBundle(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putByte(String key, byte value) {
|
||||
mBundle.putByte(key, value);
|
||||
bundle.putByte(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putByteArray(String key, byte[] value) {
|
||||
mBundle.putByteArray(key, value);
|
||||
bundle.putByteArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putChar(String key, char value) {
|
||||
mBundle.putChar(key, value);
|
||||
bundle.putChar(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putCharArray(String key, char[] value) {
|
||||
mBundle.putCharArray(key, value);
|
||||
bundle.putCharArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putCharSequence(String key, CharSequence value) {
|
||||
mBundle.putCharSequence(key, value);
|
||||
bundle.putCharSequence(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putCharSequenceArray(String key, CharSequence[] value) {
|
||||
mBundle.putCharSequenceArray(key, value);
|
||||
bundle.putCharSequenceArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putCharSequenceArrayList(String key, ArrayList<CharSequence> value) {
|
||||
mBundle.putCharSequenceArrayList(key, value);
|
||||
bundle.putCharSequenceArrayList(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putInt(String key, int value) {
|
||||
mBundle.putInt(key, value);
|
||||
bundle.putInt(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putIntArray(String key, int[] value) {
|
||||
mBundle.putIntArray(key, value);
|
||||
bundle.putIntArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putFloat(String key, float value) {
|
||||
mBundle.putFloat(key, value);
|
||||
bundle.putFloat(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putFloatArray(String key, float[] value) {
|
||||
mBundle.putFloatArray(key, value);
|
||||
bundle.putFloatArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putIntegerArrayList(String key, ArrayList<Integer> value) {
|
||||
mBundle.putIntegerArrayList(key, value);
|
||||
bundle.putIntegerArrayList(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putParcelable(String key, Parcelable value) {
|
||||
mBundle.putParcelable(key, value);
|
||||
bundle.putParcelable(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putParcelableArray(String key, Parcelable[] value) {
|
||||
mBundle.putParcelableArray(key, value);
|
||||
bundle.putParcelableArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putParcelableArrayList(String key, ArrayList<? extends Parcelable> value) {
|
||||
mBundle.putParcelableArrayList(key, value);
|
||||
bundle.putParcelableArrayList(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putSerializable(String key, Serializable value) {
|
||||
mBundle.putSerializable(key, value);
|
||||
bundle.putSerializable(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putShort(String key, short value) {
|
||||
mBundle.putShort(key, value);
|
||||
bundle.putShort(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putShortArray(String key, short[] value) {
|
||||
mBundle.putShortArray(key, value);
|
||||
bundle.putShortArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putSparseParcelableArray(String key, SparseArray<? extends Parcelable> value) {
|
||||
mBundle.putSparseParcelableArray(key, value);
|
||||
bundle.putSparseParcelableArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putStringArrayList(String key, ArrayList<String> value) {
|
||||
mBundle.putStringArrayList(key, value);
|
||||
bundle.putStringArrayList(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Bundle build() {
|
||||
return mBundle;
|
||||
return bundle;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M16,11c1.66,0 2.99,-1.34 2.99,-3S17.66,5 16,5c-1.66,0 -3,1.34 -3,3s1.34,3 3,3zM8,11c1.66,0 2.99,-1.34 2.99,-3S9.66,5 8,5C6.34,5 5,6.34 5,8s1.34,3 3,3zM8,13c-2.33,0 -7,1.17 -7,3.5L1,19h14v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5zM16,13c-0.29,0 -0.62,0.02 -0.97,0.05 1.16,0.84 1.97,1.97 1.97,3.45L17,19h6v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/grey_300"
|
||||
/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/detail_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/home_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
@@ -11,4 +10,10 @@
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/overlay_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="24dp"
|
||||
android:background="@color/grey_300"
|
||||
android:text="@string/rotate_for_two_pane"
|
||||
/>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/container_0"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/container_1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/container_2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
@@ -7,10 +7,11 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:textSize="20sp"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
@@ -48,4 +49,4 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
@@ -3,8 +3,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#88000000"
|
||||
android:clickable="true">
|
||||
android:background="#88000000" >
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
android:id="@+id/row_root"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="24dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
style="@style/Base.TextAppearance.AppCompat.Large"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -25,5 +25,6 @@
|
||||
<color name="deep_orange_300">#ff8a65</color>
|
||||
<color name="cyan_300">#4dd0e1</color>
|
||||
<color name="grey_300">#e0e0e0</color>
|
||||
<color name="grey_400">#78909C</color>
|
||||
|
||||
</resources>
|
||||
@@ -34,4 +34,7 @@
|
||||
<string name="next_controller_retain">Push Controller, retaining this View</string>
|
||||
<string name="next_controller_release">Push Controller, releasing this View</string>
|
||||
|
||||
<!-- Master/Detail Demo -->
|
||||
<string name="rotate_for_two_pane">Rotate your device for a two pane view.</string>
|
||||
|
||||
</resources>
|
||||
|
||||
+4
-1
@@ -9,7 +9,10 @@ ext {
|
||||
supportAnnotations = 'com.android.support:support-annotations:23.1.1'
|
||||
supportAppCompat = 'com.android.support:appcompat-v7:23.1.1'
|
||||
|
||||
butterknife = 'com.jakewharton:butterknife:7.0.1'
|
||||
butterknife = 'com.jakewharton:butterknife:8.0.1'
|
||||
butterknifeCompiler = 'com.jakewharton:butterknife-compiler:8.0.1'
|
||||
|
||||
picasso = 'com.squareup.picasso:picasso:2.5.2'
|
||||
|
||||
leakCanary = 'com.squareup.leakcanary:leakcanary-android:1.4-beta2'
|
||||
leakCanaryNoOp = 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 77 KiB |
+1
-1
@@ -1,4 +1,4 @@
|
||||
VERSION_NAME=1.1.6-SNAPSHOT
|
||||
VERSION_NAME=2.0.2-SNAPSHOT
|
||||
VERSION_CODE=2
|
||||
GROUP=com.bluelinelabs
|
||||
|
||||
|
||||
Reference in New Issue
Block a user