Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a87a4140e | |||
| ad81c4819b | |||
| 49018ed84c | |||
| fbfe3ce2e9 | |||
| 5a1746b2d3 | |||
| 2ffafaee79 | |||
| eabfc005d0 | |||
| a90ca5180e | |||
| 4d4d8bfbd1 | |||
| f69fab6062 | |||
| 590debf975 |
@@ -8,11 +8,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK 11
|
||||
- name: set up JDK 17
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
java-version: '17'
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Test with Gradle
|
||||
@@ -24,11 +24,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK 11
|
||||
- name: set up JDK 17
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
java-version: '17'
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Release with Gradle
|
||||
|
||||
@@ -36,16 +36,10 @@ implementation "com.bluelinelabs:conductor-viewpager:$conductorVersion"
|
||||
|
||||
// ViewPager2 Adapter:
|
||||
implementation "com.bluelinelabs:conductor-viewpager2:$conductorVersion"
|
||||
|
||||
// RxJava2 Autodispose support:
|
||||
implementation "com.bluelinelabs:conductor-autodispose:$conductorVersion"
|
||||
|
||||
// Lifecycle-aware Controllers (architecture components):
|
||||
implementation "com.bluelinelabs:conductor-archlifecycle:$conductorVersion"
|
||||
```
|
||||
|
||||
### 4.0 Preview
|
||||
Use `4.0.0-preview-1` as your version number in any of the dependencies above.
|
||||
Use `4.0.0-preview-4` as your version number in any of the dependencies above.
|
||||
|
||||
### SNAPSHOT
|
||||
Use `4.0.0-SNAPSHOT` as your version number in any of the dependencies above and add the url to the snapshot repository:
|
||||
|
||||
@@ -4,7 +4,12 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion libs.versions.compilesdk.get() as Integer
|
||||
compileSdk libs.versions.compilesdk.get() as Integer
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion libs.versions.minsdk.get()
|
||||
@@ -12,6 +17,8 @@ android {
|
||||
versionCode Integer.parseInt(project.VERSION_CODE)
|
||||
versionName project.VERSION_NAME
|
||||
}
|
||||
|
||||
namespace "com.bluelinelabs.conductor.androidxtransition"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<manifest package="com.bluelinelabs.conductor.androidxtransition">
|
||||
<application />
|
||||
</manifest>
|
||||
@@ -1,23 +0,0 @@
|
||||
plugins {
|
||||
id("com.android.library")
|
||||
alias(libs.plugins.mvnpublish)
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion libs.versions.compilesdk.get() as Integer
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion libs.versions.minsdk.get()
|
||||
targetSdkVersion libs.versions.targetsdk.get()
|
||||
versionCode Integer.parseInt(project.VERSION_CODE)
|
||||
versionName project.VERSION_NAME
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':conductor')
|
||||
|
||||
api libs.androidx.lifecycle.runtime
|
||||
}
|
||||
|
||||
ext.artifactId = 'conductor-arch-components-lifecycle'
|
||||
@@ -1,3 +0,0 @@
|
||||
POM_NAME=Conductor Architecture Components Lifecycle Extensions
|
||||
POM_ARTIFACT_ID=conductor-archlifecycle
|
||||
POM_PACKAGING=aar
|
||||
@@ -1,3 +0,0 @@
|
||||
<manifest package="com.bluelinelabs.conductor.archlifecycle">
|
||||
<application />
|
||||
</manifest>
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
package com.bluelinelabs.conductor.archlifecycle;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.Lifecycle.Event;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LifecycleRegistry;
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.view.View;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.bluelinelabs.conductor.Controller.LifecycleListener;
|
||||
|
||||
public class ControllerLifecycleOwner implements LifecycleOwner {
|
||||
|
||||
private final LifecycleRegistry lifecycleRegistry;
|
||||
|
||||
public <T extends Controller & LifecycleOwner> ControllerLifecycleOwner(@NonNull T lifecycleController) {
|
||||
lifecycleRegistry = new LifecycleRegistry(lifecycleController); // --> State.INITIALIZED
|
||||
|
||||
lifecycleController.addLifecycleListener(new LifecycleListener() {
|
||||
@Override
|
||||
public void postContextAvailable(@NonNull Controller controller, @NonNull Context context) {
|
||||
lifecycleRegistry.handleLifecycleEvent(Event.ON_CREATE); // --> State.CREATED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postCreateView(@NonNull Controller controller, @NonNull View view) {
|
||||
lifecycleRegistry.handleLifecycleEvent(Event.ON_START); // --> State.STARTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postAttach(@NonNull Controller controller, @NonNull View view) {
|
||||
lifecycleRegistry.handleLifecycleEvent(Event.ON_RESUME); // --> State.RESUMED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDetach(@NonNull Controller controller, @NonNull View view) {
|
||||
lifecycleRegistry.handleLifecycleEvent(Event.ON_PAUSE); // --> State.STARTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDestroyView(@NonNull Controller controller, @NonNull View view) {
|
||||
lifecycleRegistry.handleLifecycleEvent(Event.ON_STOP); // --> State.CREATED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preContextUnavailable(@NonNull Controller controller, @NonNull Context context) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDestroy(@NonNull Controller controller) {
|
||||
// Only act on Controllers that have had at least the onContextAvailable call made on them.
|
||||
if (lifecycleRegistry.getCurrentState() != Lifecycle.State.INITIALIZED) {
|
||||
lifecycleRegistry.handleLifecycleEvent(Event.ON_DESTROY); // --> State.DESTROYED;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override @NonNull
|
||||
public Lifecycle getLifecycle() {
|
||||
return lifecycleRegistry;
|
||||
}
|
||||
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package com.bluelinelabs.conductor.archlifecycle;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
|
||||
public abstract class LifecycleController extends Controller implements LifecycleOwner {
|
||||
|
||||
private final ControllerLifecycleOwner lifecycleOwner = new ControllerLifecycleOwner(this);
|
||||
|
||||
public LifecycleController() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LifecycleController(@Nullable Bundle args) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
@Override @NonNull
|
||||
public Lifecycle getLifecycle() {
|
||||
return lifecycleOwner.getLifecycle();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
plugins {
|
||||
id("com.android.library")
|
||||
alias(libs.plugins.mvnpublish)
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion libs.versions.compilesdk.get() as Integer
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion libs.versions.minsdk.get()
|
||||
targetSdkVersion libs.versions.targetsdk.get()
|
||||
versionCode Integer.parseInt(project.VERSION_CODE)
|
||||
versionName project.VERSION_NAME
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api libs.rxjava2
|
||||
api libs.autodispose
|
||||
api libs.autodispose.lifecycle
|
||||
|
||||
implementation project(':conductor')
|
||||
}
|
||||
|
||||
ext.artifactId = 'conductor-autodispose'
|
||||
@@ -1,3 +0,0 @@
|
||||
POM_NAME=Conductor AutoDispose Extensions
|
||||
POM_ARTIFACT_ID=conductor-autodispose
|
||||
POM_PACKAGING=aar
|
||||
@@ -1,3 +0,0 @@
|
||||
<manifest package="com.bluelinelabs.conductor.autodispose">
|
||||
<application />
|
||||
</manifest>
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
package com.bluelinelabs.conductor.autodispose;
|
||||
|
||||
public enum ControllerEvent {
|
||||
|
||||
CREATE,
|
||||
CONTEXT_AVAILABLE,
|
||||
CREATE_VIEW,
|
||||
ATTACH,
|
||||
DETACH,
|
||||
DESTROY_VIEW,
|
||||
CONTEXT_UNAVAILABLE,
|
||||
DESTROY
|
||||
|
||||
}
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
package com.bluelinelabs.conductor.autodispose;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.view.View;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.uber.autodispose.OutsideScopeException;
|
||||
|
||||
import io.reactivex.subjects.BehaviorSubject;
|
||||
|
||||
public class ControllerLifecycleSubjectHelper {
|
||||
private ControllerLifecycleSubjectHelper() { }
|
||||
|
||||
@NonNull
|
||||
public static BehaviorSubject<ControllerEvent> create(@NonNull Controller controller) {
|
||||
ControllerEvent initialState;
|
||||
if (controller.isBeingDestroyed() || controller.isDestroyed()) {
|
||||
throw new OutsideScopeException("Cannot bind to Controller lifecycle when outside of it.");
|
||||
} else if (controller.isAttached()) {
|
||||
initialState = ControllerEvent.ATTACH;
|
||||
} else if (controller.getView() != null) {
|
||||
initialState = ControllerEvent.CREATE_VIEW;
|
||||
} else if (controller.getActivity() != null) {
|
||||
initialState = ControllerEvent.CONTEXT_AVAILABLE;
|
||||
} else {
|
||||
initialState = ControllerEvent.CREATE;
|
||||
}
|
||||
|
||||
final BehaviorSubject<ControllerEvent> subject = BehaviorSubject.createDefault(initialState);
|
||||
|
||||
controller.addLifecycleListener(new Controller.LifecycleListener() {
|
||||
@Override
|
||||
public void preContextAvailable(@NonNull Controller controller) {
|
||||
subject.onNext(ControllerEvent.CONTEXT_AVAILABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCreateView(@NonNull Controller controller) {
|
||||
subject.onNext(ControllerEvent.CREATE_VIEW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preAttach(@NonNull Controller controller, @NonNull View view) {
|
||||
subject.onNext(ControllerEvent.ATTACH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDetach(@NonNull Controller controller, @NonNull View view) {
|
||||
subject.onNext(ControllerEvent.DETACH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDestroyView(@NonNull Controller controller, @NonNull View view) {
|
||||
subject.onNext(ControllerEvent.DESTROY_VIEW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preContextUnavailable(@NonNull Controller controller, @NonNull Context context) {
|
||||
subject.onNext(ControllerEvent.CONTEXT_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDestroy(@NonNull Controller controller) {
|
||||
subject.onNext(ControllerEvent.DESTROY);
|
||||
}
|
||||
});
|
||||
|
||||
return subject;
|
||||
}
|
||||
}
|
||||
-81
@@ -1,81 +0,0 @@
|
||||
package com.bluelinelabs.conductor.autodispose;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.uber.autodispose.OutsideScopeException;
|
||||
import com.uber.autodispose.lifecycle.LifecycleScopeProvider;
|
||||
import com.uber.autodispose.lifecycle.LifecycleScopes;
|
||||
import com.uber.autodispose.lifecycle.CorrespondingEventsFunction;
|
||||
|
||||
import io.reactivex.CompletableSource;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.subjects.BehaviorSubject;
|
||||
|
||||
public class ControllerScopeProvider implements LifecycleScopeProvider<ControllerEvent> {
|
||||
private static final CorrespondingEventsFunction<ControllerEvent> CORRESPONDING_EVENTS =
|
||||
new CorrespondingEventsFunction<ControllerEvent>() {
|
||||
@Override
|
||||
public ControllerEvent apply(ControllerEvent lastEvent) throws OutsideScopeException {
|
||||
switch (lastEvent) {
|
||||
case CREATE:
|
||||
return ControllerEvent.DESTROY;
|
||||
case CONTEXT_AVAILABLE:
|
||||
return ControllerEvent.CONTEXT_UNAVAILABLE;
|
||||
case CREATE_VIEW:
|
||||
return ControllerEvent.DESTROY_VIEW;
|
||||
case ATTACH:
|
||||
return ControllerEvent.DETACH;
|
||||
case DETACH:
|
||||
return ControllerEvent.DESTROY;
|
||||
default:
|
||||
throw new OutsideScopeException("Cannot bind to Controller lifecycle when outside of it.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull private final BehaviorSubject<ControllerEvent> lifecycleSubject;
|
||||
@NonNull private final CorrespondingEventsFunction<ControllerEvent> correspondingEventsFunction;
|
||||
|
||||
public static ControllerScopeProvider from(@NonNull Controller controller) {
|
||||
return new ControllerScopeProvider(controller, CORRESPONDING_EVENTS);
|
||||
}
|
||||
|
||||
public static ControllerScopeProvider from(@NonNull Controller controller, @NonNull final ControllerEvent untilEvent) {
|
||||
return new ControllerScopeProvider(controller, new CorrespondingEventsFunction<ControllerEvent>() {
|
||||
@Override
|
||||
public ControllerEvent apply(ControllerEvent controllerEvent) {
|
||||
return untilEvent;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static ControllerScopeProvider from(@NonNull Controller controller, @NonNull final CorrespondingEventsFunction<ControllerEvent> correspondingEventsFunction) {
|
||||
return new ControllerScopeProvider(controller, correspondingEventsFunction);
|
||||
}
|
||||
|
||||
private ControllerScopeProvider(@NonNull Controller controller, @NonNull CorrespondingEventsFunction<ControllerEvent> correspondingEventsFunction) {
|
||||
lifecycleSubject = ControllerLifecycleSubjectHelper.create(controller);
|
||||
this.correspondingEventsFunction = correspondingEventsFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Observable<ControllerEvent> lifecycle() {
|
||||
return lifecycleSubject.hide();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CorrespondingEventsFunction<ControllerEvent> correspondingEvents() {
|
||||
return correspondingEventsFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControllerEvent peekLifecycle() {
|
||||
return lifecycleSubject.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableSource requestScope() throws Exception {
|
||||
return LifecycleScopes.resolveScopeFromLifecycle(this);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,16 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion libs.versions.compilesdk.get() as Integer
|
||||
compileSdk libs.versions.compilesdk.get() as Integer
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion libs.versions.minsdk.get()
|
||||
@@ -13,6 +22,8 @@ android {
|
||||
versionCode Integer.parseInt(project.VERSION_CODE)
|
||||
versionName project.VERSION_NAME
|
||||
}
|
||||
|
||||
namespace "com.bluelinelabs.conductor.viewpager"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<manifest package="com.bluelinelabs.conductor.viewpager">
|
||||
<application />
|
||||
</manifest>
|
||||
@@ -6,7 +6,16 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion libs.versions.compilesdk.get() as Integer
|
||||
compileSdk libs.versions.compilesdk.get() as Integer
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion libs.versions.minsdk.get()
|
||||
@@ -20,6 +29,8 @@ android {
|
||||
includeAndroidResources = true
|
||||
}
|
||||
}
|
||||
|
||||
namespace "com.bluelinelabs.conductor.viewpager2"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<manifest package="com.bluelinelabs.conductor.viewpager2">
|
||||
<application />
|
||||
</manifest>
|
||||
+12
-1
@@ -6,7 +6,16 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion libs.versions.compilesdk.get() as Integer
|
||||
compileSdk libs.versions.compilesdk.get() as Integer
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion libs.versions.minsdk.get()
|
||||
@@ -15,6 +24,8 @@ android {
|
||||
versionName project.VERSION_NAME
|
||||
consumerProguardFiles 'proguard-rules.txt'
|
||||
}
|
||||
|
||||
namespace "com.bluelinelabs.conductor"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<manifest package="com.bluelinelabs.conductor">
|
||||
<application />
|
||||
</manifest>
|
||||
@@ -21,6 +21,10 @@ public class ActivityHostedRouter extends Router {
|
||||
private LifecycleHandler lifecycleHandler;
|
||||
private final TransactionIndexer transactionIndexer = new TransactionIndexer();
|
||||
|
||||
public ActivityHostedRouter() {
|
||||
popRootControllerMode = PopRootControllerMode.NEVER;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -16,11 +16,11 @@ internal class Backstack : Iterable<RouterTransaction> {
|
||||
|
||||
fun root(): RouterTransaction? = backstack.lastOrNull()
|
||||
|
||||
override fun iterator(): MutableIterator<RouterTransaction> {
|
||||
return backstack.iterator()
|
||||
}
|
||||
override fun iterator(): Iterator<RouterTransaction> = backstack.toTypedArray().iterator()
|
||||
|
||||
fun reverseIterator(): Iterator<RouterTransaction> = backstack.descendingIterator()
|
||||
fun reverseIterator(): Iterator<RouterTransaction> = backstack.reversed().iterator()
|
||||
|
||||
fun remove(transaction: RouterTransaction) = backstack.remove(transaction)
|
||||
|
||||
fun popTo(transaction: RouterTransaction): List<RouterTransaction> {
|
||||
if (transaction in backstack) {
|
||||
@@ -99,4 +99,4 @@ internal class Backstack : Iterable<RouterTransaction> {
|
||||
companion object {
|
||||
private const val KEY_ENTRIES = "Backstack.entries"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,5 +36,6 @@ object Conductor {
|
||||
return LifecycleHandler.install(activity, allowAndroidXBacking = allowExperimentalAndroidXBacking)
|
||||
.getRouter(container, savedInstanceState)
|
||||
.also { it.rebindIfNeeded() }
|
||||
.setPopRootControllerMode(Router.PopRootControllerMode.NEVER)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
@@ -16,14 +17,19 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.activity.BackEventCompat;
|
||||
import androidx.activity.ComponentActivity;
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.activity.OnBackPressedDispatcher;
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.bluelinelabs.conductor.internal.BackGestureControllerView;
|
||||
import com.bluelinelabs.conductor.internal.BackGestureViewState;
|
||||
import com.bluelinelabs.conductor.internal.ClassUtils;
|
||||
import com.bluelinelabs.conductor.internal.ControllerLifecycleOwner;
|
||||
import com.bluelinelabs.conductor.internal.OwnViewTreeLifecycleAndRegistry;
|
||||
import com.bluelinelabs.conductor.internal.RouterRequiringFunc;
|
||||
import com.bluelinelabs.conductor.internal.ViewAttachHandler;
|
||||
@@ -95,6 +101,9 @@ public abstract class Controller {
|
||||
private boolean isContextAvailable;
|
||||
|
||||
final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) {
|
||||
ControllerChangeHandler.ChangeTransaction popTransaction = null;
|
||||
BackGestureViewState backGestureViewState = null;
|
||||
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
// Root-level routers should have PopRootControllerMode.NEVER, and so should never return false here.
|
||||
@@ -109,8 +118,120 @@ public abstract class Controller {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleOnBackStarted(@NonNull BackEventCompat backEvent) {
|
||||
Log.d("KUCK", "it has begun");
|
||||
ControllerChangeHandler.ChangeTransaction transaction = getPopTransaction();
|
||||
if (transaction != null && transaction.changeHandler != null && transaction.changeHandler.getEnableOnBackGestureCallbacks()) {
|
||||
List<BackGestureControllerView> toViews;
|
||||
if (transaction.to != null && transaction.to.view == null) {
|
||||
toViews = toViewsForGesture(transaction, new ArrayList<>());
|
||||
} else {
|
||||
toViews = Collections.emptyList();
|
||||
}
|
||||
|
||||
for (int i = toViews.size() - 1; i > 0; i--) {
|
||||
transaction.container.addView(toViews.get(i).getView());
|
||||
}
|
||||
|
||||
backGestureViewState = new BackGestureViewState(transaction.from.view, toViews);
|
||||
|
||||
transaction.changeHandler.handleOnBackStarted(
|
||||
transaction.container,
|
||||
getToView(),
|
||||
backGestureViewState.getFromView(),
|
||||
backEvent
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleOnBackProgressed(@NonNull BackEventCompat backEvent) {
|
||||
Log.d("KUCK", "it has progressed");
|
||||
|
||||
ControllerChangeHandler.ChangeTransaction transaction = getPopTransaction();
|
||||
if (transaction != null && transaction.changeHandler != null && transaction.changeHandler.getEnableOnBackGestureCallbacks()) {
|
||||
transaction.changeHandler.handleOnBackProgressed(
|
||||
transaction.container,
|
||||
getToView(),
|
||||
backGestureViewState.getFromView(),
|
||||
backEvent
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleOnBackCancelled() {
|
||||
Log.d("KUCK", "it has canceled");
|
||||
|
||||
ControllerChangeHandler.ChangeTransaction transaction = getPopTransaction();
|
||||
if (transaction != null && transaction.changeHandler != null && transaction.changeHandler.getEnableOnBackGestureCallbacks()) {
|
||||
transaction.changeHandler.handleOnBackCancelled(
|
||||
transaction.container,
|
||||
getToView(),
|
||||
backGestureViewState.getFromView()
|
||||
);
|
||||
|
||||
for (int i = 0; i < backGestureViewState.getToViews().size(); i++) {
|
||||
BackGestureControllerView state = backGestureViewState.getToViews().get(i);
|
||||
ViewGroup parent = (ViewGroup) state.getView().getParent();
|
||||
if (parent != null) {
|
||||
parent.removeView(state.getView());
|
||||
}
|
||||
|
||||
if (state.getInflatedForGesture()) {
|
||||
state.getController().removeViewReference(state.getView().getContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backGestureViewState = null;
|
||||
}
|
||||
|
||||
private ControllerChangeHandler.ChangeTransaction getPopTransaction() {
|
||||
if (popTransaction == null) {
|
||||
popTransaction = router.popTransaction(Controller.this);
|
||||
}
|
||||
return popTransaction;
|
||||
}
|
||||
|
||||
private List<BackGestureControllerView> toViewsForGesture(
|
||||
ControllerChangeHandler.ChangeTransaction transaction,
|
||||
List<BackGestureControllerView> aggregator
|
||||
) {
|
||||
if (transaction.to != null) {
|
||||
View view = transaction.to.view;
|
||||
boolean inflated = false;
|
||||
if (view == null) {
|
||||
view = transaction.to.inflate(transaction.container);
|
||||
inflated = true;
|
||||
} else if (view.getParent() != null) {
|
||||
return aggregator;
|
||||
}
|
||||
|
||||
aggregator.add(new BackGestureControllerView(transaction.to, view, inflated));
|
||||
|
||||
if (!transaction.changeHandler.getRemovesFromViewOnPush()) {
|
||||
toViewsForGesture(router.popTransaction(transaction.to), aggregator);
|
||||
}
|
||||
}
|
||||
|
||||
return aggregator;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private View getToView() {
|
||||
if (backGestureViewState.getToViews().size() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return backGestureViewState.getToViews().get(0).getView();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public final LifecycleOwner lifecycleOwner = new ControllerLifecycleOwner(this);
|
||||
|
||||
@NonNull
|
||||
static Controller newInstance(@NonNull Bundle bundle) {
|
||||
final String className = bundle.getString(KEY_CLASS_NAME);
|
||||
@@ -1383,11 +1504,17 @@ public abstract class Controller {
|
||||
if (isDetachFrozen != frozen) {
|
||||
isDetachFrozen = frozen;
|
||||
|
||||
boolean detach = !frozen && view != null && viewWasDetached;
|
||||
|
||||
for (ControllerHostedRouter router : childRouters) {
|
||||
if (detach) {
|
||||
router.prepareForHostDetach();
|
||||
}
|
||||
|
||||
router.setDetachFrozen(frozen);
|
||||
}
|
||||
|
||||
if (!frozen && view != null && viewWasDetached) {
|
||||
if (detach) {
|
||||
View aView = view;
|
||||
detach(view, false, false);
|
||||
if (view == null && aView.getParent() == router.container) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.bluelinelabs.conductor
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.BackEventCompat
|
||||
import androidx.annotation.RestrictTo
|
||||
import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler
|
||||
import com.bluelinelabs.conductor.internal.ClassUtils
|
||||
@@ -23,10 +24,35 @@ abstract class ControllerChangeHandler {
|
||||
*/
|
||||
open val isReusable: Boolean = false
|
||||
|
||||
/**
|
||||
* Returns whether or not this handler removes the `from` view from the container when performing a push.
|
||||
*
|
||||
* If this is true:
|
||||
* - This handler's implementation of [performChange] should remove `from` from `container`
|
||||
* before calling `changeListener.onChangeCompleted()`
|
||||
* - When a controller is pushed, the previous controller will be detached and its view will be destroyed
|
||||
*
|
||||
* If this is false:
|
||||
* - This handler's implementation of [performChange] should only remove `from` from `container`
|
||||
* when `isPush` is false
|
||||
* - When a controller is pushed, the previous controller will stay attached and its view will remain created
|
||||
* - When a view is recreated (e.g. after a configuration change), any controllers underneath a transaction
|
||||
* using this handler will have their view recreated and attached, even though they're not the top-most
|
||||
* controller
|
||||
*
|
||||
* If a controller pushed onto the backstack will completely cover the previous controller,
|
||||
* using a change handler with [removesFromViewOnPush] true should result in no visual interruption
|
||||
* to the user, while allowing the previous controller's view to be destroyed to reclaim resources.
|
||||
* If instead, the previous controller should still be visible after the new controller is pushed,
|
||||
* using a change handler with [removesFromViewOnPush] false will keep the previous controller's
|
||||
* view in the view hierarchy, where it can still be seen (and even interacted with).
|
||||
*/
|
||||
open val removesFromViewOnPush: Boolean = true
|
||||
|
||||
private var hasBeenUsed = false
|
||||
|
||||
open val enableOnBackGestureCallbacks = false
|
||||
|
||||
init {
|
||||
try {
|
||||
javaClass.getConstructor()
|
||||
@@ -89,9 +115,9 @@ abstract class ControllerChangeHandler {
|
||||
*/
|
||||
open fun copy(): ControllerChangeHandler = fromBundle(toBundle())!!
|
||||
|
||||
open fun handleOnBackStarted(container: ViewGroup, to: View?, from: View, swipeEdge: Int) {}
|
||||
open fun handleOnBackStarted(container: ViewGroup, to: View?, from: View, event: BackEventCompat) {}
|
||||
|
||||
open fun handleOnBackProgressed(container: ViewGroup, to: View?, from: View, progress: Float, swipeEdge: Int) {}
|
||||
open fun handleOnBackProgressed(container: ViewGroup, to: View?, from: View, event: BackEventCompat) {}
|
||||
|
||||
open fun handleOnBackCancelled(container: ViewGroup, to: View?, from: View) {}
|
||||
|
||||
|
||||
@@ -32,9 +32,12 @@ class ControllerHostedRouter extends Router {
|
||||
private boolean isDetachFrozen;
|
||||
private boolean boundToContainer;
|
||||
|
||||
ControllerHostedRouter() { }
|
||||
ControllerHostedRouter() {
|
||||
popRootControllerMode = PopRootControllerMode.POP_ROOT_CONTROLLER_BUT_NOT_VIEW;
|
||||
}
|
||||
|
||||
ControllerHostedRouter(int hostId, @Nullable String tag, boolean boundToContainer) {
|
||||
this();
|
||||
if (!boundToContainer && tag == null) {
|
||||
throw new IllegalStateException("ControllerHostedRouter can't be created without a tag if not bounded to its container");
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public abstract class Router {
|
||||
private final List<ChangeTransaction> pendingControllerChanges = new ArrayList<>();
|
||||
final List<Controller> destroyingControllers = new ArrayList<>();
|
||||
|
||||
PopRootControllerMode popRootControllerMode = PopRootControllerMode.POP_ROOT_CONTROLLER_BUT_NOT_VIEW;
|
||||
PopRootControllerMode popRootControllerMode;
|
||||
boolean onBackPressedDispatcherEnabled;
|
||||
boolean containerFullyAttached = false;
|
||||
boolean isActivityStopped = false;
|
||||
@@ -193,7 +193,7 @@ public abstract class Router {
|
||||
RouterTransaction transaction = iterator.next();
|
||||
if (transaction.controller() == controller) {
|
||||
trackDestroyingController(transaction);
|
||||
iterator.remove();
|
||||
backstack.remove(transaction);
|
||||
removedTransaction = transaction;
|
||||
} else if (removedTransaction != null) {
|
||||
if (needsNextTransactionAttach && !transaction.controller().isAttached()) {
|
||||
@@ -320,7 +320,7 @@ public abstract class Router {
|
||||
|
||||
/**
|
||||
* Sets the method this router will use to handle back presses when there is only one controller left in the backstack.
|
||||
* Defaults to POP_ROOT_CONTROLLER_LEAVING_VIEW so that the developer can either finish its containing Activity or
|
||||
* Defaults to POP_ROOT_CONTROLLER_BUT_NOT_VIEW so that the developer can either finish its containing Activity or
|
||||
* otherwise hide its parent view without any strange artifacting.
|
||||
*/
|
||||
@NonNull
|
||||
@@ -804,6 +804,37 @@ public abstract class Router {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
ChangeTransaction popTransaction(@NonNull Controller controller) {
|
||||
RouterTransaction from = null;
|
||||
RouterTransaction to = null;
|
||||
|
||||
Iterator<RouterTransaction> iterator = backstack.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
RouterTransaction transaction = iterator.next();
|
||||
if (transaction.controller() == controller) {
|
||||
from = transaction;
|
||||
if (iterator.hasNext()) {
|
||||
to = iterator.next();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (from == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ChangeTransaction(
|
||||
to != null ? to.controller() : null,
|
||||
from.controller(),
|
||||
false,
|
||||
container,
|
||||
from.popChangeHandler(),
|
||||
Collections.emptyList()
|
||||
);
|
||||
}
|
||||
|
||||
void watchContainerAttach() {
|
||||
container.post(new Runnable() {
|
||||
@Override
|
||||
@@ -1109,7 +1140,7 @@ public abstract class Router {
|
||||
public enum PopRootControllerMode {
|
||||
/**
|
||||
* The Router will not pop the final controller left on the backstack when the back button is pressed
|
||||
* or when pop events are called. This mode should generally be used for Activity-hosted routers.
|
||||
* or when pop events are called. This mode is the default for Activity-hosted routers.
|
||||
*/
|
||||
NEVER,
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.bluelinelabs.conductor.internal
|
||||
|
||||
import android.view.View
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
|
||||
class BackGestureViewState(
|
||||
val fromView: View,
|
||||
val toViews: List<BackGestureControllerView>,
|
||||
)
|
||||
|
||||
class BackGestureControllerView(
|
||||
val controller: Controller,
|
||||
val view: View,
|
||||
val inflatedForGesture: Boolean,
|
||||
)
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.bluelinelabs.conductor.internal
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LifecycleRegistry
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.Controller.LifecycleListener
|
||||
|
||||
class ControllerLifecycleOwner(lifecycleController: Controller) : LifecycleOwner {
|
||||
private val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this) // --> State.INITIALIZED
|
||||
|
||||
override val lifecycle: Lifecycle
|
||||
get() = lifecycleRegistry
|
||||
|
||||
init {
|
||||
lifecycleController.addLifecycleListener(
|
||||
object : LifecycleListener() {
|
||||
override fun postContextAvailable(controller: Controller, context: Context) {
|
||||
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) // --> State.CREATED;
|
||||
}
|
||||
|
||||
override fun postCreateView(controller: Controller, view: View) {
|
||||
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START) // --> State.STARTED;
|
||||
}
|
||||
|
||||
override fun postAttach(controller: Controller, view: View) {
|
||||
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME) // --> State.RESUMED;
|
||||
}
|
||||
|
||||
override fun preDetach(controller: Controller, view: View) {
|
||||
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE) // --> State.STARTED;
|
||||
}
|
||||
|
||||
override fun preDestroyView(controller: Controller, view: View) {
|
||||
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP) // --> State.CREATED;
|
||||
}
|
||||
|
||||
override fun preContextUnavailable(controller: Controller, context: Context) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun preDestroy(controller: Controller) {
|
||||
// Only act on Controllers that have had at least the onContextAvailable call made on them.
|
||||
if (lifecycleRegistry.currentState != Lifecycle.State.INITIALIZED) {
|
||||
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY) // --> State.DESTROYED;
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -14,7 +14,6 @@ import androidx.savedstate.setViewTreeSavedStateRegistryOwner
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.bluelinelabs.conductor.R
|
||||
|
||||
/**
|
||||
* This class sets the [ViewTreeLifecycleOwner] and [ViewTreeSavedStateRegistryOwner] which is
|
||||
@@ -56,8 +55,8 @@ internal class OwnViewTreeLifecycleAndRegistry private constructor(
|
||||
* it on purpose.
|
||||
*/
|
||||
if (
|
||||
view.getTag(R.id.view_tree_lifecycle_owner) == null &&
|
||||
view.getTag(R.id.view_tree_saved_state_registry_owner) == null
|
||||
view.getTag(androidx.lifecycle.runtime.R.id.view_tree_lifecycle_owner) == null &&
|
||||
view.getTag(androidx.savedstate.R.id.view_tree_saved_state_registry_owner) == null
|
||||
) {
|
||||
view.setViewTreeLifecycleOwner(this@OwnViewTreeLifecycleAndRegistry)
|
||||
view.setViewTreeSavedStateRegistryOwner(this@OwnViewTreeLifecycleAndRegistry)
|
||||
|
||||
@@ -343,6 +343,8 @@ class RouterTests {
|
||||
|
||||
@Test
|
||||
fun testRearrangeTransactionBackstack() {
|
||||
router.setPopRootControllerMode(Router.PopRootControllerMode.POP_ROOT_CONTROLLER_AND_VIEW)
|
||||
|
||||
val transaction1 = TestController().asTransaction()
|
||||
val transaction2 = TestController().asTransaction()
|
||||
var backstack = listOf(transaction1, transaction2)
|
||||
@@ -433,4 +435,4 @@ class RouterTests {
|
||||
Assert.assertFalse(controller1.isBeingDestroyed())
|
||||
Assert.assertTrue(controller3.isBeingDestroyed())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-8
@@ -27,20 +27,22 @@ android {
|
||||
compose = true
|
||||
}
|
||||
|
||||
compileSdkVersion 33
|
||||
compileSdk 34
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
jvmTarget = "11"
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion libs.versions.compose.compiler.get()
|
||||
}
|
||||
|
||||
namespace "com.bluelinelabs.conductor.demo"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -51,13 +53,9 @@ dependencies {
|
||||
|
||||
implementation libs.picasso
|
||||
|
||||
implementation libs.autodispose.ktx
|
||||
|
||||
implementation project(':conductor')
|
||||
implementation project(':conductor-modules:viewpager')
|
||||
implementation project(':conductor-modules:viewpager2')
|
||||
implementation project(':conductor-modules:autodispose')
|
||||
implementation project(':conductor-modules:arch-components-lifecycle')
|
||||
implementation project(':conductor-modules:androidx-transition')
|
||||
|
||||
implementation libs.compose.ui
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.bluelinelabs.conductor.demo">
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:fullBackupContent="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="GoogleAppIndexingWarning">
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:fullBackupContent="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="GoogleAppIndexingWarning">
|
||||
|
||||
<activity
|
||||
android:name="com.bluelinelabs.conductor.demo.MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.bluelinelabs.conductor.demo.MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
-110
@@ -1,110 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.OnLifecycleEvent
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
import com.bluelinelabs.conductor.archlifecycle.LifecycleController
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.ToolbarProvider
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.watchForLeaks
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerLifecycleBinding
|
||||
|
||||
class ArchLifecycleController : LifecycleController() {
|
||||
|
||||
|
||||
init {
|
||||
Log.i(TAG, "Conductor: Constructor called")
|
||||
watchForLeaks()
|
||||
|
||||
lifecycle.addObserver(object : LifecycleObserver {
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
|
||||
fun onLifecycleEvent(source: LifecycleOwner, event: Lifecycle.Event) {
|
||||
Log.d(
|
||||
TAG,
|
||||
"Lifecycle: " + source.javaClass.simpleName + " emitted event " + event + " and is now in state " + source.lifecycle.currentState
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
Log.d(TAG, "Lifecycle: " + javaClass.simpleName + " is now in state " + lifecycle.currentState)
|
||||
}
|
||||
|
||||
override fun onContextAvailable(context: Context) {
|
||||
Log.i(TAG, "Conductor: onContextAvailable() called")
|
||||
super.onContextAvailable(context)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup,
|
||||
savedViewState: Bundle?
|
||||
): View {
|
||||
Log.i(TAG, "Conductor: onCreateView() called")
|
||||
|
||||
val binding = ControllerLifecycleBinding.inflate(inflater, container, false)
|
||||
|
||||
binding.root.setBackgroundColor(ContextCompat.getColor(container.context, R.color.orange_300))
|
||||
binding.title.text = binding.root.resources.getString(R.string.rxlifecycle_title, TAG)
|
||||
|
||||
binding.nextReleaseView.setOnClickListener {
|
||||
retainViewMode = RetainViewMode.RELEASE_DETACH
|
||||
|
||||
router.pushController(
|
||||
RouterTransaction.with(TextController("Logcat should now report that the Controller's onDetach() and LifecycleObserver's onPause() methods were called, followed by the Controller's onDestroyView() and LifecycleObserver's onStop()."))
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
)
|
||||
}
|
||||
|
||||
binding.nextRetainView.setOnClickListener {
|
||||
retainViewMode = RetainViewMode.RETAIN_DETACH
|
||||
|
||||
router.pushController(
|
||||
RouterTransaction.with(TextController("Logcat should now report that the Controller's onDetach() and LifecycleObserver's onPause() methods were called."))
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
)
|
||||
}
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onAttach(view: View) {
|
||||
Log.i(TAG, "Conductor: onAttach() called")
|
||||
super.onAttach(view)
|
||||
(activity as ToolbarProvider).toolbar.title = "Arch Components Lifecycle Demo"
|
||||
}
|
||||
|
||||
override fun onDetach(view: View) {
|
||||
Log.i(TAG, "Conductor: onDetach() called")
|
||||
super.onDetach(view)
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
Log.i(TAG, "Conductor: onDestroyView() called")
|
||||
super.onDestroyView(view)
|
||||
}
|
||||
|
||||
override fun onContextUnavailable() {
|
||||
Log.i(TAG, "Conductor: onContextUnavailable() called")
|
||||
super.onContextUnavailable()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
Log.i(TAG, "Conductor: onDestroy() called")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ArchLifecycleController"
|
||||
}
|
||||
}
|
||||
-104
@@ -1,104 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.RouterTransaction.Companion.with
|
||||
import com.bluelinelabs.conductor.autodispose.ControllerScopeProvider
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.ToolbarProvider
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.watchForLeaks
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerLifecycleBinding
|
||||
import com.uber.autodispose.autoDisposable
|
||||
import io.reactivex.Observable
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
// Shamelessly borrowed from the official RxLifecycle demo by Trello and adapted for Conductor Controllers
|
||||
// instead of Activities or Fragments.
|
||||
class AutodisposeController : Controller() {
|
||||
|
||||
private val scopeProvider = ControllerScopeProvider.from(this)
|
||||
|
||||
init {
|
||||
watchForLeaks()
|
||||
Observable.interval(1, TimeUnit.SECONDS)
|
||||
.doOnDispose { Log.i(TAG, "Disposing from constructor") }
|
||||
.autoDisposable(scopeProvider)
|
||||
.subscribe { num: Long ->
|
||||
Log.i(TAG, "Started in constructor, running until onDestroy(): $num")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup,
|
||||
savedViewState: Bundle?
|
||||
): View {
|
||||
Log.i(TAG, "onCreateView() called")
|
||||
val binding = ControllerLifecycleBinding.inflate(inflater, container, false)
|
||||
binding.title.text = binding.root.resources.getString(R.string.rxlifecycle_title, TAG)
|
||||
|
||||
binding.nextReleaseView.setOnClickListener {
|
||||
retainViewMode = RetainViewMode.RELEASE_DETACH
|
||||
router.pushController(
|
||||
with(TextController("Logcat should now report that the observables from onAttach() and onViewBound() have been disposed of, while the constructor observable is still running."))
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
)
|
||||
}
|
||||
|
||||
binding.nextRetainView.setOnClickListener {
|
||||
retainViewMode = RetainViewMode.RETAIN_DETACH
|
||||
router.pushController(
|
||||
with(TextController("Logcat should now report that the observables from onAttach() has been disposed of, while the constructor and onViewBound() observables are still running."))
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
)
|
||||
}
|
||||
|
||||
Observable.interval(1, TimeUnit.SECONDS)
|
||||
.doOnDispose { Log.i(TAG, "Disposing from onCreateView()") }
|
||||
.autoDisposable(scopeProvider)
|
||||
.subscribe { num: Long ->
|
||||
Log.i(TAG, "Started in onCreateView(), running until onDestroyView(): $num")
|
||||
}
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onAttach(view: View) {
|
||||
super.onAttach(view)
|
||||
Log.i(TAG, "onAttach() called")
|
||||
|
||||
(activity as ToolbarProvider).toolbar.title = "Autodispose Demo"
|
||||
Observable.interval(1, TimeUnit.SECONDS)
|
||||
.doOnDispose { Log.i(TAG, "Disposing from onAttach()") }
|
||||
.autoDisposable(scopeProvider)
|
||||
.subscribe { num: Long ->
|
||||
Log.i(TAG, "Started in onAttach(), running until onDetach(): $num")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
super.onDestroyView(view)
|
||||
Log.i(TAG, "onDestroyView() called")
|
||||
}
|
||||
|
||||
override fun onDetach(view: View) {
|
||||
super.onDetach(view)
|
||||
Log.i(TAG, "onDetach() called")
|
||||
}
|
||||
|
||||
public override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
Log.i(TAG, "onDestroy() called")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "AutodisposeController"
|
||||
}
|
||||
}
|
||||
-121
@@ -1,121 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerCityDetailBinding
|
||||
import com.bluelinelabs.conductor.demo.databinding.RowCityDetailBinding
|
||||
import com.bluelinelabs.conductor.demo.databinding.RowCityHeaderBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
class CityDetailController(args: Bundle) : BaseController(R.layout.controller_city_detail, args) {
|
||||
private val binding: ControllerCityDetailBinding by viewBinding(ControllerCityDetailBinding::bind)
|
||||
|
||||
override val title = args.getString(KEY_TITLE)!!
|
||||
|
||||
constructor(@DrawableRes image: Int, title: String) : this(
|
||||
bundleOf(
|
||||
KEY_TITLE to title,
|
||||
KEY_IMAGE to image
|
||||
)
|
||||
)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
binding.recyclerView.setHasFixedSize(true)
|
||||
binding.recyclerView.layoutManager = LinearLayoutManager(view.context)
|
||||
binding.recyclerView.adapter = CityDetailAdapter(
|
||||
inflater = LayoutInflater.from(view.context),
|
||||
title = title,
|
||||
imageDrawableRes = args.getInt(KEY_IMAGE),
|
||||
details = LIST_ROWS,
|
||||
transitionNameBase = title
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_TITLE = "CityDetailController.title"
|
||||
private const val KEY_IMAGE = "CityDetailController.image"
|
||||
|
||||
private val LIST_ROWS = listOf(
|
||||
"• This is a city.",
|
||||
"• There's some cool stuff about it.",
|
||||
"• But really this is just a demo, not a city guide app.",
|
||||
"• This demo is meant to show some nice transitions.",
|
||||
"• You should have seen some sweet shared element transitions using the ImageView and the TextView in the \"header\" above.",
|
||||
"• This transition utilized some callbacks to ensure all the necessary rows in the RecyclerView were laid about before the transition occurred.",
|
||||
"• Just adding some more lines so it scrolls now...\n\n\n\n\n\n\nThe end."
|
||||
)
|
||||
}
|
||||
|
||||
class CityDetailAdapter(
|
||||
private val inflater: LayoutInflater,
|
||||
private val title: String,
|
||||
@DrawableRes private val imageDrawableRes: Int,
|
||||
private val details: List<String>,
|
||||
private val transitionNameBase: String
|
||||
) : RecyclerView.Adapter<ViewHolder<*>>() {
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (position == 0) VIEW_TYPE_HEADER else VIEW_TYPE_DETAIL
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<*> {
|
||||
return if (viewType == VIEW_TYPE_HEADER) {
|
||||
HeaderViewHolder(RowCityHeaderBinding.inflate(inflater, parent, false))
|
||||
} else {
|
||||
DetailViewHolder(RowCityDetailBinding.inflate(inflater, parent, false))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder<*>, position: Int) {
|
||||
when (holder) {
|
||||
is HeaderViewHolder -> {
|
||||
holder.bind(
|
||||
imageDrawableRes = imageDrawableRes,
|
||||
title = title,
|
||||
imageTransitionName = inflater.context.resources.getString(R.string.transition_tag_image_named, transitionNameBase),
|
||||
textViewTransitionName = inflater.context.resources.getString(R.string.transition_tag_title_named, transitionNameBase)
|
||||
)
|
||||
}
|
||||
is DetailViewHolder -> {
|
||||
holder.bind(details[position - 1])
|
||||
}
|
||||
else -> {
|
||||
throw IllegalStateException("Invalid view holder class ${holder.javaClass.canonicalName}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = details.size + 1
|
||||
|
||||
companion object {
|
||||
private const val VIEW_TYPE_HEADER = 0
|
||||
private const val VIEW_TYPE_DETAIL = 1
|
||||
}
|
||||
}
|
||||
|
||||
open class ViewHolder<Binding : ViewBinding>(binding: Binding) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
class HeaderViewHolder(private val binding: RowCityHeaderBinding) : ViewHolder<RowCityHeaderBinding>(binding) {
|
||||
fun bind(@DrawableRes imageDrawableRes: Int, title: String?, imageTransitionName: String?, textViewTransitionName: String?) {
|
||||
binding.imageView.setImageResource(imageDrawableRes)
|
||||
binding.textView.text = title
|
||||
binding.imageView.transitionName = imageTransitionName
|
||||
binding.textView.transitionName = textViewTransitionName
|
||||
}
|
||||
}
|
||||
|
||||
class DetailViewHolder(private val binding: RowCityDetailBinding) : ViewHolder<RowCityDetailBinding>(binding) {
|
||||
fun bind(detail: String) {
|
||||
binding.textView.text = detail
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.changehandler.CityGridSharedElementTransitionChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerCityGridBinding
|
||||
import com.bluelinelabs.conductor.demo.databinding.RowCityGridBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
class CityGridController(args: Bundle) : BaseController(R.layout.controller_city_grid, args) {
|
||||
private val binding: ControllerCityGridBinding by viewBinding(ControllerCityGridBinding::bind)
|
||||
|
||||
override val title = "Shared Element Demos"
|
||||
|
||||
constructor(title: String?, dotColor: Int, fromPosition: Int) : this(
|
||||
bundleOf(
|
||||
KEY_TITLE to title,
|
||||
KEY_DOT_COLOR to dotColor,
|
||||
KEY_FROM_POSITION to fromPosition
|
||||
)
|
||||
)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.title.text = args.getString(KEY_TITLE)!!
|
||||
binding.dot.drawable.setColorFilter(ContextCompat.getColor(view.context, args.getInt(KEY_DOT_COLOR)), PorterDuff.Mode.SRC_ATOP)
|
||||
|
||||
binding.title.transitionName = view.resources.getString(R.string.transition_tag_title_indexed, args.getInt(KEY_FROM_POSITION))
|
||||
binding.dot.transitionName = view.resources.getString(R.string.transition_tag_dot_indexed, args.getInt(KEY_FROM_POSITION))
|
||||
|
||||
binding.recyclerView.setHasFixedSize(true)
|
||||
binding.recyclerView.layoutManager = GridLayoutManager(view.context, 2)
|
||||
binding.recyclerView.adapter = CityGridAdapter(LayoutInflater.from(view.context), CITY_MODELS, ::onModelRowClick)
|
||||
}
|
||||
|
||||
private fun onModelRowClick(model: CityModel) {
|
||||
val names = listOf(
|
||||
resources!!.getString(R.string.transition_tag_title_named, model.title),
|
||||
resources!!.getString(R.string.transition_tag_image_named, model.title)
|
||||
)
|
||||
|
||||
router.pushController(
|
||||
RouterTransaction.with(CityDetailController(model.drawableRes, model.title))
|
||||
.pushChangeHandler(CityGridSharedElementTransitionChangeHandler(names))
|
||||
.popChangeHandler(CityGridSharedElementTransitionChangeHandler(names))
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_TITLE = "CityGridController.title"
|
||||
private const val KEY_DOT_COLOR = "CityGridController.dotColor"
|
||||
private const val KEY_FROM_POSITION = "CityGridController.position"
|
||||
|
||||
private val CITY_MODELS = arrayOf(
|
||||
CityModel(R.drawable.chicago, "Chicago"),
|
||||
CityModel(R.drawable.jakarta, "Jakarta"),
|
||||
CityModel(R.drawable.london, "London"),
|
||||
CityModel(R.drawable.sao_paulo, "Sao Paulo"),
|
||||
CityModel(R.drawable.tokyo, "Tokyo")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class CityModel(@DrawableRes val drawableRes: Int, val title: String)
|
||||
|
||||
private class CityGridAdapter(
|
||||
private val inflater: LayoutInflater,
|
||||
private val items: Array<CityModel>,
|
||||
private val modelClickListener: (CityModel) -> Unit
|
||||
) : RecyclerView.Adapter<CityGridAdapter.ViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(
|
||||
RowCityGridBinding.inflate(inflater, parent, false),
|
||||
modelClickListener
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(items[position])
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
class ViewHolder(
|
||||
private val binding: RowCityGridBinding,
|
||||
private val modelClickListener: (CityModel) -> Unit
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: CityModel) {
|
||||
binding.image.setImageResource(item.drawableRes)
|
||||
binding.title.text = item.title
|
||||
|
||||
binding.image.transitionName = itemView.resources.getString(R.string.transition_tag_image_named, item.title)
|
||||
binding.image.transitionName = itemView.resources.getString(R.string.transition_tag_title_named, item.title)
|
||||
|
||||
itemView.setOnClickListener { modelClickListener(item) }
|
||||
}
|
||||
}
|
||||
}
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.graphics.PorterDuff
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bluelinelabs.conductor.RouterTransaction.Companion.with
|
||||
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerAdditionalModulesBinding
|
||||
import com.bluelinelabs.conductor.demo.databinding.RowHomeBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
class ExternalModulesController : BaseController(R.layout.controller_additional_modules) {
|
||||
private val binding: ControllerAdditionalModulesBinding by viewBinding(
|
||||
ControllerAdditionalModulesBinding::bind
|
||||
)
|
||||
|
||||
override val title = "External Module Demos"
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.recyclerView.setHasFixedSize(true)
|
||||
binding.recyclerView.layoutManager = LinearLayoutManager(view.context)
|
||||
binding.recyclerView.adapter = AdditionalModulesAdapter(
|
||||
LayoutInflater.from(view.context),
|
||||
ModuleModel.values(),
|
||||
::onModelRowClick
|
||||
)
|
||||
}
|
||||
|
||||
private fun onModelRowClick(model: ModuleModel) {
|
||||
when (model) {
|
||||
ModuleModel.AUTODISPOSE -> router.pushController(
|
||||
with(AutodisposeController())
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
)
|
||||
ModuleModel.ARCH_LIFECYCLE -> router.pushController(
|
||||
with(ArchLifecycleController())
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum class ModuleModel(val title: String, @ColorRes val color: Int) {
|
||||
AUTODISPOSE("Autodispose", R.color.purple_300),
|
||||
ARCH_LIFECYCLE("Arch Components Lifecycle", R.color.orange_300);
|
||||
}
|
||||
|
||||
private class AdditionalModulesAdapter(
|
||||
private val inflater: LayoutInflater,
|
||||
private val items: Array<ModuleModel>,
|
||||
private val modelClickListener: (ModuleModel) -> Unit
|
||||
) : RecyclerView.Adapter<AdditionalModulesAdapter.ViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(RowHomeBinding.inflate(inflater, parent, false), modelClickListener)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(items[position])
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.size
|
||||
}
|
||||
|
||||
class ViewHolder(
|
||||
private val binding: RowHomeBinding,
|
||||
private val modelClickListener: (ModuleModel) -> Unit
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(item: ModuleModel) {
|
||||
binding.title.text = item.title
|
||||
binding.dot.drawable.setColorFilter(
|
||||
ContextCompat.getColor(itemView.context, item.color),
|
||||
PorterDuff.Mode.SRC_ATOP
|
||||
)
|
||||
itemView.setOnClickListener { modelClickListener(item) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import android.text.style.URLSpan
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.BackEventCompat
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.ContextCompat
|
||||
@@ -18,12 +19,11 @@ import androidx.core.graphics.BlendModeCompat
|
||||
import androidx.core.text.buildSpannedString
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
import com.bluelinelabs.conductor.asTransaction
|
||||
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.changehandler.ArcFadeMoveChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.changehandler.FabToDialogTransitionChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.controllers.NavigationDemoController.DisplayUpMode
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
@@ -78,12 +78,13 @@ class HomeController : BaseController(R.layout.controller_home) {
|
||||
}
|
||||
|
||||
private fun onModelRowClick(model: DemoModel, position: Int) {
|
||||
println("onModelRowClick")
|
||||
when (model) {
|
||||
DemoModel.NAVIGATION -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(NavigationDemoController(0, DisplayUpMode.SHOW_FOR_CHILDREN_ONLY))
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
.pushChangeHandler(WhateverChangeHandler())
|
||||
.popChangeHandler(WhateverChangeHandler())
|
||||
.tag(NavigationDemoController.TAG_UP_TRANSACTION)
|
||||
)
|
||||
}
|
||||
@@ -118,25 +119,11 @@ class HomeController : BaseController(R.layout.controller_home) {
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
)
|
||||
}
|
||||
DemoModel.SHARED_ELEMENT_TRANSITIONS -> {
|
||||
val titleSharedElementName =
|
||||
resources!!.getString(R.string.transition_tag_title_indexed, position)
|
||||
val dotSharedElementName =
|
||||
resources!!.getString(R.string.transition_tag_dot_indexed, position)
|
||||
DemoModel.ON_BACK_PRESSED_CALLBACK -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(CityGridController(model.title, model.color, position))
|
||||
.pushChangeHandler(
|
||||
ArcFadeMoveChangeHandler(
|
||||
titleSharedElementName,
|
||||
dotSharedElementName
|
||||
)
|
||||
)
|
||||
.popChangeHandler(
|
||||
ArcFadeMoveChangeHandler(
|
||||
titleSharedElementName,
|
||||
dotSharedElementName
|
||||
)
|
||||
)
|
||||
RouterTransaction.with(OnBackPressedCallbackController())
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
)
|
||||
}
|
||||
DemoModel.DRAG_DISMISS -> {
|
||||
@@ -146,13 +133,6 @@ class HomeController : BaseController(R.layout.controller_home) {
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
)
|
||||
}
|
||||
DemoModel.EXTERNAL_MODULES -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(ExternalModulesController())
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
)
|
||||
}
|
||||
DemoModel.MASTER_DETAIL -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(MasterDetailListController())
|
||||
@@ -208,14 +188,13 @@ private enum class DemoModel(val title: String, @ColorRes val color: Int) {
|
||||
COMPOSE("Jetpack Compose", R.color.amber_500),
|
||||
NAVIGATION("Navigation Demos", R.color.red_300),
|
||||
TRANSITIONS("Transition Demos", R.color.blue_grey_300),
|
||||
SHARED_ELEMENT_TRANSITIONS("Shared Element Demos", R.color.purple_300),
|
||||
ON_BACK_PRESSED_CALLBACK("Back Handling", R.color.purple_300),
|
||||
CHILD_CONTROLLERS("Child Controllers", R.color.orange_300),
|
||||
VIEW_PAGER("ViewPager", R.color.green_300),
|
||||
VIEW_PAGER_2("ViewPager2", R.color.pink_300),
|
||||
TARGET_CONTROLLER("Target Controller", R.color.deep_orange_300),
|
||||
MASTER_DETAIL("Master Detail", R.color.lime_300),
|
||||
DRAG_DISMISS("Drag Dismiss", R.color.teal_300),
|
||||
EXTERNAL_MODULES("Bonus Modules", R.color.deep_purple_300)
|
||||
}
|
||||
|
||||
private class HomeAdapter(
|
||||
@@ -257,3 +236,47 @@ private class HomeAdapter(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WhateverChangeHandler : ControllerChangeHandler() {
|
||||
override val enableOnBackGestureCallbacks = true
|
||||
|
||||
override fun handleOnBackStarted(container: ViewGroup, to: View?, from: View, event: BackEventCompat) {
|
||||
println("handleOnBackStarted")
|
||||
to?.let { container.addView(it) }
|
||||
}
|
||||
|
||||
override fun handleOnBackProgressed(container: ViewGroup, to: View?, from: View, event: BackEventCompat) {
|
||||
if (event.swipeEdge == BackEventCompat.EDGE_LEFT) {
|
||||
from.translationX = event.progress * container.width
|
||||
to?.translationX = -container.width + event.progress * container.width
|
||||
} else {
|
||||
from.translationX = -event.progress * container.width
|
||||
to?.translationX = container.width + -event.progress * container.width
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleOnBackCancelled(container: ViewGroup, to: View?, from: View) {
|
||||
to?.let { container.removeView(it) }
|
||||
}
|
||||
|
||||
override fun performChange(
|
||||
container: ViewGroup,
|
||||
from: View?,
|
||||
to: View?,
|
||||
isPush: Boolean,
|
||||
changeListener: ControllerChangeCompletedListener,
|
||||
) {
|
||||
from?.translationX = 0f
|
||||
to?.translationX = 0f
|
||||
println("perform change called")
|
||||
if (isPush) {
|
||||
to?.let { container.addView(it) }
|
||||
from?.let { container.removeView(it) }
|
||||
} else {
|
||||
to?.let { if (it.parent == null) container.addView(it) }
|
||||
from?.let { container.removeView(it) }
|
||||
}
|
||||
|
||||
changeListener.onChangeCompleted()
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -20,7 +20,6 @@ class MultipleChildRouterController : BaseController(R.layout.controller_multipl
|
||||
|
||||
childContainers.forEach { container ->
|
||||
val childRouter = getChildRouter(container).setPopRootControllerMode(PopRootControllerMode.POP_ROOT_CONTROLLER_BUT_NOT_VIEW)
|
||||
.setPopRootControllerMode(PopRootControllerMode.NEVER)
|
||||
if (!childRouter.hasRootController()) {
|
||||
childRouter.setRoot(RouterTransaction.with(NavigationDemoController(0, NavigationDemoController.DisplayUpMode.HIDE)))
|
||||
}
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.selection.selectable
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.RadioButton
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.demo.ToolbarProvider
|
||||
|
||||
class OnBackPressedCallbackController : Controller() {
|
||||
|
||||
private val onBackPressedCallback = object : OnBackPressedCallback(false) {
|
||||
override fun handleOnBackPressed() {
|
||||
Toast.makeText(activity!!, "Back handled at the Controller level", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onContextAvailable(context: Context) {
|
||||
super.onContextAvailable(context)
|
||||
|
||||
onBackPressedDispatcher?.addCallback(lifecycleOwner, onBackPressedCallback)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup,
|
||||
savedViewState: Bundle?
|
||||
): View {
|
||||
return ComposeView(container.context).apply {
|
||||
setContent {
|
||||
OnBackPressedDemo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttach(view: View) {
|
||||
super.onAttach(view)
|
||||
|
||||
(activity as? ToolbarProvider)?.toolbar?.apply {
|
||||
title = "OnBackPressed Demo"
|
||||
menu.clear()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun OnBackPressedDemo(modifier: Modifier = Modifier) {
|
||||
val radioOptions = BackOption.values()
|
||||
val (selectedOption, onOptionSelected) = remember { mutableStateOf(radioOptions[0]) }
|
||||
|
||||
BackHandler(enabled = selectedOption == BackOption.Composable) {
|
||||
Toast.makeText(activity!!, "Back handled at the Composable level", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
MaterialTheme {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.padding(top = 16.dp),
|
||||
) {
|
||||
LaunchedEffect(selectedOption) {
|
||||
onBackPressedCallback.isEnabled = selectedOption == BackOption.Controller
|
||||
}
|
||||
|
||||
radioOptions.forEach { option ->
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.selectable(
|
||||
selected = (option == selectedOption),
|
||||
onClick = {
|
||||
onOptionSelected(option)
|
||||
},
|
||||
)
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
RadioButton(
|
||||
selected = (option == selectedOption),
|
||||
onClick = { onOptionSelected(option) },
|
||||
)
|
||||
Text(
|
||||
text = option.title,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum class BackOption(val title: String) {
|
||||
Controller("Handle back in Controller"),
|
||||
Composable("Handle back in Composable"),
|
||||
None("Disable back handlers"),
|
||||
}
|
||||
+2
-3
@@ -9,13 +9,12 @@ import androidx.appcompat.widget.Toolbar
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.bluelinelabs.conductor.archlifecycle.LifecycleController
|
||||
import com.bluelinelabs.conductor.demo.ToolbarProvider
|
||||
|
||||
abstract class BaseController(
|
||||
@LayoutRes private val layoutRes: Int,
|
||||
args: Bundle? = null
|
||||
) : LifecycleController(args) {
|
||||
) : Controller(args) {
|
||||
|
||||
init {
|
||||
watchForLeaks()
|
||||
@@ -82,4 +81,4 @@ abstract class BaseController(
|
||||
toolbar.menu.clear()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 487 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 434 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 300 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 338 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 439 KiB |
@@ -1,28 +0,0 @@
|
||||
<?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:background="#455A64"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="8dp"
|
||||
android:text="@string/additional_modules_explanation"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp"
|
||||
/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/city_grid_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:paddingEnd="@dimen/activity_horizontal_margin">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dot"
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="96dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/circle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/Base.TextAppearance.AppCompat.Large"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="40dp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
/>
|
||||
@@ -1,26 +0,0 @@
|
||||
<?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="200dp"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_weight="1"
|
||||
android:importantForAccessibility="no" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/Base.TextAppearance.AppCompat.Large"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?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="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="16dp" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="fitCenter"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
style="@style/Base.TextAppearance.AppCompat.Large"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -5,9 +5,6 @@
|
||||
<!-- Home Controller -->
|
||||
<string name="about">About</string>
|
||||
|
||||
<!-- Additional Modules Controller -->
|
||||
<string name="additional_modules_explanation">The following modules are provided as additional dependencies, and are not a part of the core library. If you\'ve made a module you want to see included, let us know!</string>
|
||||
|
||||
<!-- Navigation Demo -->
|
||||
<string name="pop_to_root">Pop to Root</string>
|
||||
<string name="go_up">Go Up</string>
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
VERSION_CODE=4
|
||||
VERSION_NAME=4.0.0-SNAPSHOT
|
||||
VERSION_NAME=4.0.0-SNAPSHOT-PREDICTIVE
|
||||
android.useAndroidX=true
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
|
||||
|
||||
+21
-29
@@ -1,32 +1,30 @@
|
||||
[versions]
|
||||
minsdk = "16"
|
||||
compilesdk = "33"
|
||||
minsdk = "19"
|
||||
compilesdk = "34"
|
||||
targetsdk = "28"
|
||||
|
||||
agp = "7.4.2" # Note: update lint version whenever this is updated
|
||||
androidx-activity = "1.6.1"
|
||||
androidx-annotation = "1.1.0"
|
||||
androidx-appcompat = "1.4.2"
|
||||
androidx-collection = "1.1.0"
|
||||
androidx-core = "1.3.2"
|
||||
androidx-lifecycle = "2.6.0"
|
||||
androidx-savedstate = "1.2.0"
|
||||
androidx-transition = "1.3.1"
|
||||
agp = "8.1.4" # Note: update lint version whenever this is updated
|
||||
androidx-activity = "1.8.2"
|
||||
androidx-annotation = "1.7.1"
|
||||
androidx-appcompat = "1.6.1"
|
||||
androidx-collection = "1.3.0"
|
||||
androidx-core = "1.12.0"
|
||||
androidx-lifecycle = "2.7.0"
|
||||
androidx-savedstate = "1.2.1"
|
||||
androidx-transition = "1.4.1"
|
||||
androidx-viewpager2 = "1.0.0"
|
||||
autodispose = "1.0.0"
|
||||
compose = "1.3.1"
|
||||
compose-compiler = "1.4.3"
|
||||
dokka = "1.8.10"
|
||||
junit = "4.13"
|
||||
compose = "1.5.4"
|
||||
compose-compiler = "1.5.3"
|
||||
dokka = "1.9.0"
|
||||
junit = "4.13.2"
|
||||
kotest = "4.6.0"
|
||||
kotlin = "1.8.10"
|
||||
leakCanary = "2.7"
|
||||
lint = "30.4.2" # Should always be agp + 23
|
||||
material = "1.2.1"
|
||||
mvnpublish = "0.23.2"
|
||||
kotlin = "1.9.10"
|
||||
leakCanary = "2.12"
|
||||
lint = "31.1.4" # Should always be agp + 23
|
||||
material = "1.11.0"
|
||||
mvnpublish = "0.27.0"
|
||||
picasso = "2.5.2"
|
||||
robolectric = "4.5.1"
|
||||
rxjava2 = "2.1.14"
|
||||
robolectric = "4.11.1"
|
||||
|
||||
[libraries]
|
||||
activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" }
|
||||
@@ -37,17 +35,12 @@ androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "a
|
||||
androidx-collection = { module = "androidx.collection:collection", version.ref = "androidx-collection" }
|
||||
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
|
||||
androidx-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime", version.ref = "androidx-lifecycle" }
|
||||
androidx-lifecycle-livedata-core = { module = "androidx.lifecycle:lifecycle-livedata-core", version.ref = "androidx-lifecycle" }
|
||||
androidx-savedstate-ktx = { module = "androidx.savedstate:savedstate-ktx", version.ref = "androidx-savedstate" }
|
||||
androidx-transition = { module = "androidx.transition:transition", version.ref = "androidx-transition" }
|
||||
androidx-viewpager2 = { module = "androidx.viewpager2:viewpager2", version.ref = "androidx-viewpager2" }
|
||||
autodispose = { module = "com.uber.autodispose:autodispose", version.ref = "autodispose" }
|
||||
autodispose-lifecycle = { module = "com.uber.autodispose:autodispose-lifecycle", version.ref = "autodispose" }
|
||||
autodispose-ktx = { module = "com.uber.autodispose:autodispose-ktx", version.ref = "autodispose" }
|
||||
compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "compose" }
|
||||
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
|
||||
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" }
|
||||
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose" }
|
||||
compose-material = { module = "androidx.compose.material:material", version.ref = "compose" }
|
||||
dokka = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" }
|
||||
junit = { module = "junit:junit", version.ref = "junit" }
|
||||
@@ -62,7 +55,6 @@ lint-tests = { module = "com.android.tools.lint:lint-tests", version.ref = "lint
|
||||
material = { module = "com.google.android.material:material", version.ref = "material" }
|
||||
picasso = { module = "com.squareup.picasso:picasso", version.ref = "picasso" }
|
||||
robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" }
|
||||
rxjava2 = { module = "io.reactivex.rxjava2:rxjava", version.ref = "rxjava2" }
|
||||
|
||||
[plugins]
|
||||
mvnpublish = { id = "com.vanniktech.maven.publish", version.ref = "mvnpublish" }
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -17,7 +17,5 @@ include ':conductor'
|
||||
include ':conductor-lint'
|
||||
include ':conductor-modules:viewpager'
|
||||
include ':conductor-modules:viewpager2'
|
||||
include ':conductor-modules:autodispose'
|
||||
include ':conductor-modules:arch-components-lifecycle'
|
||||
include ':conductor-modules:androidx-transition'
|
||||
include ':demo'
|
||||
|
||||
Reference in New Issue
Block a user