Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a8622c261 | |||
| 6820aa7d6a | |||
| 9ce27e4dee | |||
| 3c8ad0a833 | |||
| a720ac57e8 | |||
| 7d6901389b | |||
| e54e88bf0d | |||
| 010117603c |
@@ -1,26 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Deploy a jar, source jar, and javadoc jar to Sonatype's snapshot repo.
|
||||
#
|
||||
# Adapted from https://coderwall.com/p/9b_lfq and
|
||||
# http://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/
|
||||
|
||||
SLUG="bluelinelabs/Conductor"
|
||||
JDK="oraclejdk8"
|
||||
BRANCH="develop"
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$TRAVIS_REPO_SLUG" != "$SLUG" ]; then
|
||||
echo "Skipping snapshot deployment: wrong repository. Expected '$SLUG' but was '$TRAVIS_REPO_SLUG'."
|
||||
elif [ "$TRAVIS_JDK_VERSION" != "$JDK" ]; then
|
||||
echo "Skipping snapshot deployment: wrong JDK. Expected '$JDK' but was '$TRAVIS_JDK_VERSION'."
|
||||
elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
echo "Skipping snapshot deployment: was pull request."
|
||||
elif [ "$TRAVIS_BRANCH" != "$BRANCH" ]; then
|
||||
echo "Skipping snapshot deployment: wrong branch. Expected '$BRANCH' but was '$TRAVIS_BRANCH'."
|
||||
else
|
||||
echo "Deploying snapshot..."
|
||||
./gradlew clean uploadArchives
|
||||
echo "Snapshot deployed!"
|
||||
fi
|
||||
@@ -0,0 +1,36 @@
|
||||
name: Test & Publish
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Test with Gradle
|
||||
run: ./gradlew test
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/develop'
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Test with Gradle
|
||||
run: ./gradlew clean uploadArchives
|
||||
env:
|
||||
ORG_GRADLE_PROJECT_SONATYPE_NEXUS_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }}
|
||||
ORG_GRADLE_PROJECT_SONATYPE_NEXUS_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
language: android
|
||||
|
||||
before_install:
|
||||
- mkdir "$ANDROID_HOME/licenses" || true
|
||||
- echo "\n24333f8a63b6825ea9c5514f83c2829b004d1fee" > "$ANDROID_HOME/licenses/android-sdk-license"
|
||||
- echo "\n84831b9409646a918e30573bab4c9c91346d8abd" > "$ANDROID_HOME/licenses/android-sdk-preview-license"
|
||||
- yes | sdkmanager --update
|
||||
|
||||
script:
|
||||
- ./gradlew test
|
||||
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- master
|
||||
|
||||
after_success:
|
||||
- .buildscript/deploy_snapshot.sh
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.gradle
|
||||
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: Px0uj7aMtKUVZVBnoEjHrEHh4cwO2qKJrHHPvwBiDqhwLBaWQIVXYOy0njaYc5o8p96Fv7bMu7NZx/72vMu1+nmTKxgzrMIxvMW6kczBvJUpv6xd1NuC34x+5Xq5gBNOFvb8JarWStcKgIvnFqvBsRUeI1Hsz7Olb8HF+fEo1kShuP18ezSsBkXruw8JuGiU9x0kq4YhZ7vRvFnc3sJX2FL6heuvQsnUWrolUOsKRadNkCibo+Euuls7ExvbbAXN4LEO3rs0G2eBUBbi2wXvTMG9symtItEHTMPO7K+aQfNQnHsY91TYveH/IJM1u5p6OldsUSOUigzpDmpVYW94aLuJaYqc6Ibq3eUws+tv2didOHXZW5zOCFjldDFBIQFPA3fih/wK/JP0taQ0uIu1+2eifvuERarMkGsYlOFe5tJd10ipi+kK5vNxoRwS9kGv5WwP5fVPX2m5XbD2y1LnugCCcAumfNX7NyNBIRqTy7BP34O3EMLZpMxjwSLnUBnYd4V/0LEvoVmbYmrLhWwpojBJmdwe2QknrPuvRErxNujRA1uEVupbU5A6RW1BmrtzSahJYoROI+ayG7UTOSbFN8+DorER1SUXsrOFlawak8yWsoi6OIynTKucrFM3YcBdJ3Su5AIhfBAOASZa6CUa6sn6Zo8mHmDVGKeckvXnLCU=
|
||||
- secure: 3Dj6roVTO2a9Z8lwlTGzJJ+QGeyIYSuQ/Z6YsYnW3wB9Mw36uWqw9rOmMNIGjjyAlER8bKgalHr90Pus87oaNaIlbEyvq+L+I0FVAwognViFjo/a2apCcq81THoKjT1l0sgGRzvLNDynQe1q2L0tOu21wtBhMLb7FKQYB9+oD3H+rcU63xD2tv3ToJz+j+dccZ9nrtgk0MQ1xAeMtEb4tdq3flKATKhIuDkp9chaDxx/ZGwyhdE0UP29UUyP5Np1QvpFAlAJIZloZPvde2e05fwxTh4rwUCetkfJknDK6WrGiq97WGRXJpfORNuwGn7jxDCtgxcAm9nGF8qmI/v78BhjJ857CfJBTLGv4QI0RszlhXyezJqqRYjCn9S4yx8UAOixVJfJfFNHLqD4MFn41b7j8J3HDJPxNt0t/qYhUMrgrZVosNOUqhwCyQTKDqtrpvmSUbhHpk2+fxZF1GEL5N540rA0OjLmFUUEDSvRQVaa/waeqXrRefOhsXIx20dHs93C6XDffjnxVMKlqtPab2MlHV/23QCuSa6eW+lKyOZ6ZkWLwwDsLbnuD0WJfJpiL1xaTdPJNIDb6kB/Bno4V1O4xrYncEOaA4Vr4amO8le9Q33/QeNrUZSXs/eye5t0f02wCzubuiEDVEeoR/qj5+5CNWv3AWr/f8AgXp80Pzw=
|
||||
+3
-1
@@ -2,13 +2,15 @@ buildscript {
|
||||
apply from: rootProject.file('dependencies.gradle')
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:$agpVersion"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
classpath "com.vanniktech:gradle-maven-publish-plugin:$mvnPublishVersion"
|
||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokkaVersion"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -32,9 +32,9 @@ public abstract class RouterPagerAdapter extends PagerAdapter {
|
||||
|
||||
private final Controller host;
|
||||
private int maxPagesToStateSave = Integer.MAX_VALUE;
|
||||
private Map<Integer, String> tags = new HashMap<>();
|
||||
private final Map<Integer, String> tags = new HashMap<>();
|
||||
private SparseArray<Bundle> savedPages = new SparseArray<>();
|
||||
private SparseArray<Router> visibleRouters = new SparseArray<>();
|
||||
private final SparseArray<Router> visibleRouters = new SparseArray<>();
|
||||
private ArrayList<Integer> savedPageHistory = new ArrayList<>();
|
||||
private Router currentPrimaryRouter;
|
||||
|
||||
@@ -103,7 +103,7 @@ public abstract class RouterPagerAdapter extends PagerAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(ViewGroup container, int position, Object object) {
|
||||
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
||||
Router router = (Router)object;
|
||||
|
||||
Bundle savedState = new Bundle();
|
||||
@@ -121,8 +121,8 @@ public abstract class RouterPagerAdapter extends PagerAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrimaryItem(ViewGroup container, int position, Object object) {
|
||||
Router router = (Router)object;
|
||||
public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
||||
Router router = (Router) object;
|
||||
if (router != currentPrimaryRouter) {
|
||||
if (currentPrimaryRouter != null) {
|
||||
for (RouterTransaction transaction : currentPrimaryRouter.getBackstack()) {
|
||||
@@ -139,7 +139,7 @@ public abstract class RouterPagerAdapter extends PagerAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(View view, Object object) {
|
||||
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
|
||||
Router router = (Router)object;
|
||||
final List<RouterTransaction> backstack = router.getBackstack();
|
||||
for (RouterTransaction transaction : backstack) {
|
||||
|
||||
+39
-13
@@ -48,8 +48,7 @@ abstract class RouterStateAdapter(private val host: Controller) :
|
||||
}
|
||||
|
||||
private fun inferViewPager(recyclerView: RecyclerView): ViewPager2 {
|
||||
return recyclerView.parent as? ViewPager2 ?:
|
||||
error("Expected ViewPager2 instance. Got: ${recyclerView.parent}")
|
||||
return recyclerView.parent as? ViewPager2 ?: error("Expected ViewPager2 instance. Got: ${recyclerView.parent}")
|
||||
}
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
@@ -89,6 +88,10 @@ abstract class RouterStateAdapter(private val host: Controller) :
|
||||
super.onViewDetachedFromWindow(holder)
|
||||
|
||||
detachRouter(holder)
|
||||
|
||||
// Controller has fully detached and destroyed its view reference by now. Remove the leftover
|
||||
// view from the container.
|
||||
holder.container.removeAllViews()
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: RouterViewHolder) {
|
||||
@@ -115,6 +118,18 @@ abstract class RouterStateAdapter(private val host: Controller) :
|
||||
}
|
||||
|
||||
override fun saveState(): Parcelable {
|
||||
// Ensure all visible pages are saved, starting at the outermost pages and working our way in
|
||||
val visiblePositions = (0 until visibleRouters.size()).map { visibleRouters.keyAt(it) }.toMutableList()
|
||||
while (visiblePositions.isNotEmpty()) {
|
||||
val lastPosition = visiblePositions.removeAt(visiblePositions.lastIndex)
|
||||
savePage(getItemId(lastPosition), visibleRouters[lastPosition])
|
||||
|
||||
if (visiblePositions.isNotEmpty()) {
|
||||
val firstPosition = visiblePositions.removeAt(0)
|
||||
savePage(getItemId(firstPosition), visibleRouters[firstPosition])
|
||||
}
|
||||
}
|
||||
|
||||
return SavedState(
|
||||
savedPagesKeys = (0 until savedPages.size()).map { savedPages.keyAt(it) },
|
||||
savedPagesValues = (0 until savedPages.size()).map { savedPages.valueAt(it) },
|
||||
@@ -138,11 +153,18 @@ abstract class RouterStateAdapter(private val host: Controller) :
|
||||
private fun attachRouter(holder: RouterViewHolder, position: Int) {
|
||||
val itemId = getItemId(position)
|
||||
val router = host.getChildRouter(holder.container, "$itemId")
|
||||
|
||||
// This should have already been handled by onViewRecycled, but it seems like this wasn't
|
||||
// always reliably called
|
||||
if (router != holder.currentRouter) {
|
||||
holder.currentRouter?.let { host.removeChildRouter(it) }
|
||||
}
|
||||
|
||||
holder.currentRouter = router
|
||||
holder.currentItemId = itemId
|
||||
|
||||
if (!router.hasRootController()) {
|
||||
val routerSavedState = savedPages[position.toLong()]
|
||||
val routerSavedState = savedPages[itemId]
|
||||
if (routerSavedState != null) {
|
||||
router.restoreInstanceState(routerSavedState)
|
||||
savedPages.remove(itemId)
|
||||
@@ -172,14 +194,7 @@ abstract class RouterStateAdapter(private val host: Controller) :
|
||||
holder.currentRouter?.let { router ->
|
||||
router.prepareForHostDetach()
|
||||
|
||||
val savedState = Bundle()
|
||||
router.saveInstanceState(savedState)
|
||||
savedPages.put(holder.currentItemId, savedState)
|
||||
|
||||
savedPageHistory.remove(holder.currentItemId)
|
||||
savedPageHistory.add(holder.currentItemId)
|
||||
|
||||
ensurePagesSaved()
|
||||
savePage(holder.currentItemId, router)
|
||||
|
||||
if (visibleRouters[holder.currentItemPosition] == router) {
|
||||
visibleRouters.remove(holder.currentItemPosition)
|
||||
@@ -189,10 +204,21 @@ abstract class RouterStateAdapter(private val host: Controller) :
|
||||
holder.attached = false
|
||||
}
|
||||
|
||||
private fun savePage(itemId: Long, router: Router) {
|
||||
val savedState = Bundle()
|
||||
router.saveInstanceState(savedState)
|
||||
savedPages.put(itemId, savedState)
|
||||
|
||||
savedPageHistory.remove(itemId)
|
||||
savedPageHistory.add(itemId)
|
||||
|
||||
ensurePagesSaved()
|
||||
}
|
||||
|
||||
private fun ensurePagesSaved() {
|
||||
while (savedPages.size() > maxPagesToStateSave) {
|
||||
val positionToRemove = savedPageHistory.removeAt(0)
|
||||
savedPages.remove(positionToRemove)
|
||||
val routerIdToRemove = savedPageHistory.removeAt(0)
|
||||
savedPages.remove(routerIdToRemove)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1099,7 +1099,7 @@ public abstract class Controller {
|
||||
});
|
||||
viewAttachHandler.listenForAttach(view);
|
||||
}
|
||||
} else if (retainViewMode == RetainViewMode.RETAIN_DETACH) {
|
||||
} else {
|
||||
restoreChildControllerHosts();
|
||||
}
|
||||
|
||||
@@ -1111,7 +1111,7 @@ public abstract class Controller {
|
||||
if (!childRouter.hasHost()) {
|
||||
View containerView = view.findViewById(childRouter.getHostId());
|
||||
|
||||
if (containerView != null && containerView instanceof ViewGroup) {
|
||||
if (containerView instanceof ViewGroup) {
|
||||
childRouter.setHostContainer(this, (ViewGroup) containerView);
|
||||
childRouter.rebindIfNeeded();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
-keepclassmembers public class * extends com.bluelinelabs.conductor.Controller {
|
||||
public <init>();
|
||||
public <init>(android.os.Bundle);
|
||||
}
|
||||
|
||||
-keepclassmembers public class * extends com.bluelinelabs.conductor.ControllerChangeHandler {
|
||||
public <init>();
|
||||
}
|
||||
|
||||
+19
-9
@@ -1,13 +1,7 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.bluelinelabs.conductor.demo"
|
||||
minSdkVersion 21
|
||||
@@ -27,19 +21,35 @@ android {
|
||||
packagingOptions {
|
||||
exclude 'META-INF/rxjava.properties'
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
}
|
||||
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation rootProject.ext.androidxAppCompat
|
||||
implementation rootProject.ext.androidxViewPager2
|
||||
implementation rootProject.ext.material
|
||||
implementation rootProject.ext.androidxCoreKtx
|
||||
|
||||
implementation rootProject.ext.archComponentsLiveDataCore // Fix duplicate classes
|
||||
|
||||
annotationProcessor rootProject.ext.butterknifeCompiler
|
||||
implementation rootProject.ext.butterknife
|
||||
implementation rootProject.ext.picasso
|
||||
|
||||
implementation rootProject.ext.autodisposeKtx
|
||||
|
||||
implementation project(':conductor')
|
||||
implementation project(':conductor-modules:viewpager')
|
||||
implementation project(':conductor-modules:viewpager2')
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
|
||||
public interface ActionBarProvider {
|
||||
ActionBar getSupportActionBar();
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
import com.squareup.leakcanary.RefWatcher;
|
||||
|
||||
public class DemoApplication extends Application {
|
||||
|
||||
public static RefWatcher refWatcher;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
refWatcher = LeakCanary.install(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.bluelinelabs.conductor.demo
|
||||
|
||||
import android.app.Application
|
||||
import com.squareup.leakcanary.LeakCanary
|
||||
import com.squareup.leakcanary.RefWatcher
|
||||
|
||||
class DemoApplication : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
refWatcher = LeakCanary.install(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
lateinit var refWatcher: RefWatcher
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
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.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public final class MainActivity extends AppCompatActivity implements ActionBarProvider {
|
||||
|
||||
@BindView(R.id.toolbar) Toolbar toolbar;
|
||||
@BindView(R.id.controller_container) ViewGroup container;
|
||||
|
||||
private Router router;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
router = Conductor.attachRouter(this, container, savedInstanceState);
|
||||
if (!router.hasRootController()) {
|
||||
router.setRoot(RouterTransaction.with(new HomeController()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (!router.handleBack()) {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.bluelinelabs.conductor.demo
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import com.bluelinelabs.conductor.Conductor.attachRouter
|
||||
import com.bluelinelabs.conductor.Router
|
||||
import com.bluelinelabs.conductor.RouterTransaction.Companion.with
|
||||
import com.bluelinelabs.conductor.demo.controllers.HomeController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ActivityMainBinding
|
||||
|
||||
class MainActivity : AppCompatActivity(), ToolbarProvider {
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
private lateinit var router: Router
|
||||
|
||||
override val toolbar: Toolbar
|
||||
get() = binding.toolbar
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
router = attachRouter(this, binding.controllerContainer, savedInstanceState)
|
||||
if (!router.hasRootController()) {
|
||||
router.setRoot(with(HomeController()))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (!router.handleBack()) {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.bluelinelabs.conductor.demo
|
||||
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
|
||||
interface ToolbarProvider {
|
||||
val toolbar: Toolbar
|
||||
}
|
||||
-140
@@ -1,140 +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 android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.lifecycle.Lifecycle.Event;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.OnLifecycleEvent;
|
||||
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
import com.bluelinelabs.conductor.ControllerChangeType;
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.archlifecycle.LifecycleController;
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||
import com.bluelinelabs.conductor.demo.ActionBarProvider;
|
||||
import com.bluelinelabs.conductor.demo.DemoApplication;
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public class ArchLifecycleController extends LifecycleController {
|
||||
|
||||
private static final String TAG = "ArchLifecycleController";
|
||||
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
|
||||
private Unbinder unbinder;
|
||||
private boolean hasExited;
|
||||
|
||||
public ArchLifecycleController() {
|
||||
Log.i(TAG, "Conductor: Constructor called");
|
||||
|
||||
getLifecycle().addObserver(new LifecycleObserver() {
|
||||
@OnLifecycleEvent(Event.ON_ANY)
|
||||
void onLifecycleEvent(@NonNull LifecycleOwner source, @NonNull Event event) {
|
||||
Log.d(TAG, "Lifecycle: " + source.getClass().getSimpleName() + " emitted event " + event + " and is now in state " + source.getLifecycle().getCurrentState());
|
||||
}
|
||||
});
|
||||
|
||||
Log.d(TAG, "Lifecycle: " + getClass().getSimpleName() + " is now in state " + getLifecycle().getCurrentState());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onContextAvailable(@NonNull Context context) {
|
||||
Log.i(TAG, "Conductor: onContextAvailable() called");
|
||||
super.onContextAvailable(context);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container, @Nullable Bundle savedViewState) {
|
||||
Log.i(TAG, "Conductor: onCreateView() called");
|
||||
|
||||
View view = inflater.inflate(R.layout.controller_lifecycle, container, false);
|
||||
view.setBackgroundColor(ContextCompat.getColor(container.getContext(), R.color.orange_300));
|
||||
unbinder = ButterKnife.bind(this, view);
|
||||
|
||||
tvTitle.setText(getResources().getString(R.string.rxlifecycle_title, TAG));
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttach(@NonNull View view) {
|
||||
Log.i(TAG, "Conductor: onAttach() called");
|
||||
super.onAttach(view);
|
||||
|
||||
(((ActionBarProvider) getActivity()).getSupportActionBar()).setTitle("Arch Components Lifecycle Demo");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetach(@NonNull View view) {
|
||||
Log.i(TAG, "Conductor: onDetach() called");
|
||||
super.onDetach(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroyView(@NonNull View view) {
|
||||
Log.i(TAG, "Conductor: onDestroyView() called");
|
||||
super.onDestroyView(view);
|
||||
|
||||
unbinder.unbind();
|
||||
unbinder = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onContextUnavailable() {
|
||||
Log.i(TAG, "Conductor: onContextUnavailable() called");
|
||||
super.onContextUnavailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
Log.i(TAG, "Conductor: onDestroy() called");
|
||||
super.onDestroy();
|
||||
|
||||
if (hasExited) {
|
||||
DemoApplication.refWatcher.watch(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChangeEnded(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
super.onChangeEnded(changeHandler, changeType);
|
||||
|
||||
hasExited = !changeType.isEnter;
|
||||
if (isDestroyed()) {
|
||||
DemoApplication.refWatcher.watch(this);
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_next_release_view) void onNextWithReleaseClicked() {
|
||||
setRetainViewMode(RetainViewMode.RELEASE_DETACH);
|
||||
|
||||
getRouter().pushController(RouterTransaction.with(new 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(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_next_retain_view) void onNextWithRetainClicked() {
|
||||
setRetainViewMode(RetainViewMode.RETAIN_DETACH);
|
||||
|
||||
getRouter().pushController(RouterTransaction.with(new TextController("Logcat should now report that the Controller's onDetach() and LifecycleObserver's onPause() methods were called."))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
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.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
import com.bluelinelabs.conductor.archlifecycle.LifecycleController
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.DemoApplication
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.ToolbarProvider
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerLifecycleBinding
|
||||
|
||||
class ArchLifecycleController : LifecycleController() {
|
||||
|
||||
private var hasExited = false
|
||||
|
||||
init {
|
||||
Log.i(TAG, "Conductor: Constructor called")
|
||||
|
||||
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")
|
||||
super.onDestroy()
|
||||
if (hasExited) {
|
||||
DemoApplication.refWatcher.watch(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChangeEnded(
|
||||
changeHandler: ControllerChangeHandler,
|
||||
changeType: ControllerChangeType
|
||||
) {
|
||||
super.onChangeEnded(changeHandler, changeType)
|
||||
hasExited = !changeType.isEnter
|
||||
if (isDestroyed) {
|
||||
DemoApplication.refWatcher.watch(this)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ArchLifecycleController"
|
||||
}
|
||||
}
|
||||
-143
@@ -1,143 +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 android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
import com.bluelinelabs.conductor.ControllerChangeType;
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.autodispose.ControllerScopeProvider;
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||
import com.bluelinelabs.conductor.demo.ActionBarProvider;
|
||||
import com.bluelinelabs.conductor.demo.DemoApplication;
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.uber.autodispose.AutoDispose;
|
||||
import com.uber.autodispose.lifecycle.LifecycleScopeProvider;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.Unbinder;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.functions.Action;
|
||||
import io.reactivex.functions.Consumer;
|
||||
|
||||
// Shamelessly borrowed from the official RxLifecycle demo by Trello and adapted for Conductor Controllers
|
||||
// instead of Activities or Fragments.
|
||||
public class AutodisposeController extends Controller {
|
||||
|
||||
private static final String TAG = "AutodisposeController";
|
||||
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
|
||||
private Unbinder unbinder;
|
||||
private boolean hasExited;
|
||||
private final LifecycleScopeProvider scopeProvider = ControllerScopeProvider.from(this);
|
||||
|
||||
public AutodisposeController() {
|
||||
Observable.interval(1, TimeUnit.SECONDS)
|
||||
.doOnDispose(() -> Log.i(TAG, "Disposing from constructor"))
|
||||
.as(AutoDispose.<Long>autoDisposable((scopeProvider)))
|
||||
.subscribe(num -> Log.i(TAG, "Started in constructor, running until onDestroy(): " + num));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container, @Nullable Bundle savedViewState) {
|
||||
Log.i(TAG, "onCreateView() called");
|
||||
|
||||
View view = inflater.inflate(R.layout.controller_lifecycle, container, false);
|
||||
view.setBackgroundColor(ContextCompat.getColor(container.getContext(), R.color.purple_300));
|
||||
unbinder = ButterKnife.bind(this, view);
|
||||
|
||||
tvTitle.setText(getResources().getString(R.string.rxlifecycle_title, TAG));
|
||||
|
||||
Observable.interval(1, TimeUnit.SECONDS)
|
||||
.doOnDispose(() -> Log.i(TAG, "Disposing from onCreateView()"))
|
||||
.as(AutoDispose.<Long>autoDisposable((scopeProvider)))
|
||||
.subscribe(num -> Log.i(TAG, "Started in onCreateView(), running until onDestroyView(): " + num));
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttach(@NonNull View view) {
|
||||
super.onAttach(view);
|
||||
|
||||
Log.i(TAG, "onAttach() called");
|
||||
|
||||
(((ActionBarProvider) getActivity()).getSupportActionBar()).setTitle("Autodispose Demo");
|
||||
|
||||
Observable.interval(1, TimeUnit.SECONDS)
|
||||
.doOnDispose(() -> Log.i(TAG, "Disposing from onAttach()"))
|
||||
.as(AutoDispose.<Long>autoDisposable((scopeProvider)))
|
||||
.subscribe(num -> Log.i(TAG, "Started in onAttach(), running until onDetach(): " + num));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroyView(@NonNull View view) {
|
||||
super.onDestroyView(view);
|
||||
|
||||
Log.i(TAG, "onDestroyView() called");
|
||||
|
||||
unbinder.unbind();
|
||||
unbinder = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetach(@NonNull View view) {
|
||||
super.onDetach(view);
|
||||
|
||||
Log.i(TAG, "onDetach() called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
Log.i(TAG, "onDestroy() called");
|
||||
|
||||
if (hasExited) {
|
||||
DemoApplication.refWatcher.watch(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChangeEnded(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
super.onChangeEnded(changeHandler, changeType);
|
||||
|
||||
hasExited = !changeType.isEnter;
|
||||
if (isDestroyed()) {
|
||||
DemoApplication.refWatcher.watch(this);
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_next_release_view)
|
||||
void onNextWithReleaseClicked() {
|
||||
setRetainViewMode(RetainViewMode.RELEASE_DETACH);
|
||||
|
||||
getRouter().pushController(RouterTransaction.with(new TextController("Logcat should now report that the observables from onAttach() and onViewBound() have been disposed of, while the constructor observable is still running."))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_next_retain_view)
|
||||
void onNextWithRetainClicked() {
|
||||
setRetainViewMode(RetainViewMode.RETAIN_DETACH);
|
||||
|
||||
getRouter().pushController(RouterTransaction.with(new TextController("Logcat should now report that the observables from onAttach() has been disposed of, while the constructor and onViewBound() observables are still running."))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
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.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.bluelinelabs.conductor.RouterTransaction.Companion.with
|
||||
import com.bluelinelabs.conductor.autodispose.ControllerScopeProvider
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.DemoApplication
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.ToolbarProvider
|
||||
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 var hasExited = false
|
||||
private val scopeProvider = ControllerScopeProvider.from(this)
|
||||
|
||||
init {
|
||||
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")
|
||||
if (hasExited) {
|
||||
DemoApplication.refWatcher.watch(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChangeEnded(
|
||||
changeHandler: ControllerChangeHandler,
|
||||
changeType: ControllerChangeType
|
||||
) {
|
||||
super.onChangeEnded(changeHandler, changeType)
|
||||
hasExited = !changeType.isEnter
|
||||
if (isDestroyed) {
|
||||
DemoApplication.refWatcher.watch(this)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "AutodisposeController"
|
||||
}
|
||||
}
|
||||
@@ -1,56 +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 android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class ChildController extends BaseController {
|
||||
|
||||
private static final String KEY_TITLE = "ChildController.title";
|
||||
private static final String KEY_BG_COLOR = "ChildController.bgColor";
|
||||
private static final String KEY_COLOR_IS_RES = "ChildController.colorIsResId";
|
||||
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
|
||||
public ChildController(String title, int backgroundColor, boolean colorIsResId) {
|
||||
this(new BundleBuilder(new Bundle())
|
||||
.putString(KEY_TITLE, title)
|
||||
.putInt(KEY_BG_COLOR, backgroundColor)
|
||||
.putBoolean(KEY_COLOR_IS_RES, colorIsResId)
|
||||
.build());
|
||||
}
|
||||
|
||||
public ChildController(Bundle args) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_child, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
|
||||
tvTitle.setText(getArgs().getString(KEY_TITLE));
|
||||
|
||||
int bgColor = getArgs().getInt(KEY_BG_COLOR);
|
||||
if (getArgs().getBoolean(KEY_COLOR_IS_RES)) {
|
||||
bgColor = ContextCompat.getColor(getActivity(), bgColor);
|
||||
}
|
||||
view.setBackgroundColor(bgColor);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerChildBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
class ChildController(args: Bundle) : BaseController(R.layout.controller_child, args) {
|
||||
private val binding: ControllerChildBinding by viewBinding(ControllerChildBinding::bind)
|
||||
|
||||
constructor(title: String, backgroundColor: Int, colorIsResId: Boolean) : this(
|
||||
bundleOf(
|
||||
KEY_TITLE to title,
|
||||
KEY_BG_COLOR to backgroundColor,
|
||||
KEY_COLOR_IS_RES to colorIsResId
|
||||
)
|
||||
)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
binding.title.text = args.getString(KEY_TITLE)
|
||||
|
||||
val bgColor = args.getInt(KEY_BG_COLOR)
|
||||
if (args.getBoolean(KEY_COLOR_IS_RES)) {
|
||||
view.setBackgroundColor(ContextCompat.getColor(view.context, bgColor))
|
||||
} else {
|
||||
view.setBackgroundColor(bgColor)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_TITLE = "ChildController.title"
|
||||
private const val KEY_BG_COLOR = "ChildController.bgColor"
|
||||
private const val KEY_COLOR_IS_RES = "ChildController.colorIsResId"
|
||||
}
|
||||
}
|
||||
-167
@@ -1,167 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class CityDetailController extends BaseController {
|
||||
|
||||
private static final String KEY_TITLE = "CityDetailController.title";
|
||||
private static final String KEY_IMAGE = "CityDetailController.image";
|
||||
|
||||
private static final String[] LIST_ROWS = new String[] {
|
||||
"• 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."
|
||||
};
|
||||
|
||||
@BindView(R.id.recycler_view) RecyclerView recyclerView;
|
||||
|
||||
@DrawableRes private int imageDrawableRes;
|
||||
private String title;
|
||||
|
||||
public CityDetailController(@DrawableRes int imageDrawableRes, String title) {
|
||||
this(new BundleBuilder(new Bundle())
|
||||
.putInt(KEY_IMAGE, imageDrawableRes)
|
||||
.putString(KEY_TITLE, title)
|
||||
.build());
|
||||
}
|
||||
|
||||
public CityDetailController(Bundle args) {
|
||||
super(args);
|
||||
imageDrawableRes = getArgs().getInt(KEY_IMAGE);
|
||||
title = getArgs().getString(KEY_TITLE);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_city_detail, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
|
||||
recyclerView.setHasFixedSize(true);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
|
||||
recyclerView.setAdapter(new CityDetailAdapter(LayoutInflater.from(view.getContext()), title, imageDrawableRes, LIST_ROWS, title));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
static class CityDetailAdapter extends RecyclerView.Adapter<CityDetailAdapter.ViewHolder> {
|
||||
|
||||
private static final int VIEW_TYPE_HEADER = 0;
|
||||
private static final int VIEW_TYPE_DETAIL = 1;
|
||||
|
||||
private final LayoutInflater inflater;
|
||||
private final String title;
|
||||
@DrawableRes private final int imageDrawableRes;
|
||||
private final String imageViewTransitionName;
|
||||
private final String textViewTransitionName;
|
||||
private final String[] details;
|
||||
|
||||
public CityDetailAdapter(LayoutInflater inflater, String title, @DrawableRes int imageDrawableRes, String[] details, String transitionNameBase) {
|
||||
this.inflater = inflater;
|
||||
this.title = title;
|
||||
this.imageDrawableRes = imageDrawableRes;
|
||||
this.details = details;
|
||||
imageViewTransitionName = inflater.getContext().getResources().getString(R.string.transition_tag_image_named, transitionNameBase);
|
||||
textViewTransitionName = inflater.getContext().getResources().getString(R.string.transition_tag_title_named, transitionNameBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position == 0) {
|
||||
return VIEW_TYPE_HEADER;
|
||||
} else {
|
||||
return VIEW_TYPE_DETAIL;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
if (viewType == VIEW_TYPE_HEADER) {
|
||||
return new HeaderViewHolder(inflater.inflate(R.layout.row_city_header, parent, false));
|
||||
} else {
|
||||
return new DetailViewHolder(inflater.inflate(R.layout.row_city_detail, parent, false));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
if (getItemViewType(position) == VIEW_TYPE_HEADER) {
|
||||
((HeaderViewHolder)holder).bind(imageDrawableRes, title, imageViewTransitionName, textViewTransitionName);
|
||||
} else {
|
||||
((DetailViewHolder)holder).bind(details[position - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return 1 + details.length;
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
}
|
||||
|
||||
static class HeaderViewHolder extends ViewHolder {
|
||||
|
||||
@BindView(R.id.image_view) ImageView imageView;
|
||||
@BindView(R.id.text_view) TextView textView;
|
||||
|
||||
public HeaderViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
void bind(@DrawableRes int imageDrawableRes, String title, String imageTransitionName, String textViewTransitionName) {
|
||||
imageView.setImageResource(imageDrawableRes);
|
||||
textView.setText(title);
|
||||
|
||||
ViewCompat.setTransitionName(imageView, imageTransitionName);
|
||||
ViewCompat.setTransitionName(textView, textViewTransitionName);
|
||||
}
|
||||
}
|
||||
|
||||
static class DetailViewHolder extends ViewHolder {
|
||||
|
||||
@BindView(R.id.text_view) TextView textView;
|
||||
|
||||
public DetailViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
void bind(String detail) {
|
||||
textView.setText(detail);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
-168
@@ -1,168 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
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.util.BundleBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class CityGridController extends BaseController {
|
||||
|
||||
private static final String KEY_TITLE = "CityGridController.title";
|
||||
private static final String KEY_DOT_COLOR = "CityGridController.dotColor";
|
||||
private static final String KEY_FROM_POSITION = "CityGridController.position";
|
||||
|
||||
private static final CityModel[] CITY_MODELS = new CityModel[] {
|
||||
new CityModel(R.drawable.chicago, "Chicago"),
|
||||
new CityModel(R.drawable.jakarta, "Jakarta"),
|
||||
new CityModel(R.drawable.london, "London"),
|
||||
new CityModel(R.drawable.sao_paulo, "Sao Paulo"),
|
||||
new CityModel(R.drawable.tokyo, "Tokyo")
|
||||
};
|
||||
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
@BindView(R.id.img_dot) ImageView imgDot;
|
||||
@BindView(R.id.recycler_view) RecyclerView recyclerView;
|
||||
|
||||
private String title;
|
||||
private int dotColor;
|
||||
private int fromPosition;
|
||||
|
||||
public CityGridController(String title, int dotColor, int fromPosition) {
|
||||
this(new BundleBuilder(new Bundle())
|
||||
.putString(KEY_TITLE, title)
|
||||
.putInt(KEY_DOT_COLOR, dotColor)
|
||||
.putInt(KEY_FROM_POSITION, fromPosition)
|
||||
.build());
|
||||
}
|
||||
|
||||
public CityGridController(Bundle args) {
|
||||
super(args);
|
||||
title = getArgs().getString(KEY_TITLE);
|
||||
dotColor = getArgs().getInt(KEY_DOT_COLOR);
|
||||
fromPosition = getArgs().getInt(KEY_FROM_POSITION);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_city_grid, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
|
||||
tvTitle.setText(title);
|
||||
imgDot.getDrawable().setColorFilter(ContextCompat.getColor(getActivity(), dotColor), Mode.SRC_ATOP);
|
||||
|
||||
ViewCompat.setTransitionName(tvTitle, getResources().getString(R.string.transition_tag_title_indexed, fromPosition));
|
||||
ViewCompat.setTransitionName(imgDot, getResources().getString(R.string.transition_tag_dot_indexed, fromPosition));
|
||||
|
||||
recyclerView.setHasFixedSize(true);
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(view.getContext(), 2));
|
||||
recyclerView.setAdapter(new CityGridAdapter(LayoutInflater.from(view.getContext()), CITY_MODELS));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "Shared Element Demos";
|
||||
}
|
||||
|
||||
void onModelRowClick(CityModel model) {
|
||||
String imageTransitionName = getResources().getString(R.string.transition_tag_image_named, model.title);
|
||||
String titleTransitionName = getResources().getString(R.string.transition_tag_title_named, model.title);
|
||||
|
||||
List<String> names = new ArrayList<>();
|
||||
names.add(imageTransitionName);
|
||||
names.add(titleTransitionName);
|
||||
|
||||
getRouter().pushController(RouterTransaction.with(new CityDetailController(model.drawableRes, model.title))
|
||||
.pushChangeHandler(new CityGridSharedElementTransitionChangeHandler(names))
|
||||
.popChangeHandler(new CityGridSharedElementTransitionChangeHandler(names)));
|
||||
}
|
||||
|
||||
class CityGridAdapter extends RecyclerView.Adapter<CityGridAdapter.ViewHolder> {
|
||||
|
||||
private final LayoutInflater inflater;
|
||||
private final CityModel[] items;
|
||||
|
||||
public CityGridAdapter(LayoutInflater inflater, CityModel[] items) {
|
||||
this.inflater = inflater;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(inflater.inflate(R.layout.row_city_grid, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
holder.bind(items[position]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.length;
|
||||
}
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
@BindView(R.id.tv_title) TextView textView;
|
||||
@BindView(R.id.img_city) ImageView imageView;
|
||||
private CityModel model;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
|
||||
void bind(CityModel item) {
|
||||
model = item;
|
||||
imageView.setImageResource(item.drawableRes);
|
||||
textView.setText(item.title);
|
||||
|
||||
ViewCompat.setTransitionName(textView, getResources().getString(R.string.transition_tag_title_named, model.title));
|
||||
ViewCompat.setTransitionName(imageView, getResources().getString(R.string.transition_tag_image_named, model.title));
|
||||
}
|
||||
|
||||
@OnClick(R.id.row_root)
|
||||
void onRowClick() {
|
||||
onModelRowClick(model);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static class CityModel {
|
||||
@DrawableRes int drawableRes;
|
||||
String title;
|
||||
|
||||
public CityModel(@DrawableRes int drawableRes, String title) {
|
||||
this.drawableRes = drawableRes;
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.support.annotation.DrawableRes
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class DialogController extends BaseController {
|
||||
|
||||
private static final String KEY_TITLE = "DialogController.title";
|
||||
private static final String KEY_DESCRIPTION = "DialogController.description";
|
||||
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
@BindView(R.id.tv_description) TextView tvDescription;
|
||||
|
||||
public DialogController(CharSequence title, CharSequence description) {
|
||||
this(new BundleBuilder(new Bundle())
|
||||
.putCharSequence(KEY_TITLE, title)
|
||||
.putCharSequence(KEY_DESCRIPTION, description)
|
||||
.build());
|
||||
}
|
||||
|
||||
public DialogController(Bundle args) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_dialog, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
tvTitle.setText(getArgs().getCharSequence(KEY_TITLE));
|
||||
tvDescription.setText(getArgs().getCharSequence(KEY_DESCRIPTION));
|
||||
tvDescription.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
@OnClick({R.id.dismiss, R.id.dialog_window})
|
||||
public void dismissDialog() {
|
||||
getRouter().popController(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleBack() {
|
||||
return super.handleBack();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.view.View
|
||||
import androidx.core.os.bundleOf
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerDialogBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
class DialogController(args: Bundle) : BaseController(R.layout.controller_dialog, args) {
|
||||
private val binding: ControllerDialogBinding by viewBinding(ControllerDialogBinding::bind)
|
||||
|
||||
constructor(title: CharSequence, description: CharSequence) : this(
|
||||
bundleOf(
|
||||
KEY_TITLE to title,
|
||||
KEY_DESCRIPTION to description
|
||||
)
|
||||
)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
binding.title.text = args.getCharSequence(KEY_TITLE)
|
||||
binding.description.text = args.getCharSequence(KEY_DESCRIPTION)
|
||||
binding.description.movementMethod = LinkMovementMethod.getInstance()
|
||||
|
||||
binding.dismiss.setOnClickListener { router.popController(this) }
|
||||
binding.dialogBackground.setOnClickListener { router.popController(this) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_TITLE = "DialogController.title"
|
||||
private const val KEY_DESCRIPTION = "DialogController.description"
|
||||
}
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.changehandler.ScaleFadeChangeHandler;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.demo.widget.ElasticDragDismissFrameLayout;
|
||||
import com.bluelinelabs.conductor.demo.widget.ElasticDragDismissFrameLayout.ElasticDragDismissCallback;
|
||||
|
||||
@TargetApi(VERSION_CODES.LOLLIPOP)
|
||||
public class DragDismissController extends BaseController {
|
||||
|
||||
private final ElasticDragDismissCallback dragDismissListener = new ElasticDragDismissCallback() {
|
||||
@Override
|
||||
public void onDragDismissed() {
|
||||
overridePopHandler(new ScaleFadeChangeHandler());
|
||||
getRouter().popController(DragDismissController.this);
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_drag_dismiss, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
((ElasticDragDismissFrameLayout)view).addListener(dragDismissListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroyView(@NonNull View view) {
|
||||
super.onDestroyView(view);
|
||||
|
||||
((ElasticDragDismissFrameLayout)view).removeListener(dragDismissListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "Drag to Dismiss";
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.view.View
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.changehandler.ScaleFadeChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.widget.ElasticDragDismissFrameLayout
|
||||
import com.bluelinelabs.conductor.demo.widget.ElasticDragDismissFrameLayout.ElasticDragDismissCallback
|
||||
|
||||
class DragDismissController : BaseController(R.layout.controller_drag_dismiss) {
|
||||
override val title = "Drag to Dismiss"
|
||||
|
||||
private val dragDismissListener: ElasticDragDismissCallback = object : ElasticDragDismissCallback() {
|
||||
override fun onDragDismissed() {
|
||||
overridePopHandler(ScaleFadeChangeHandler())
|
||||
router.popController(this@DragDismissController)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
(view as ElasticDragDismissFrameLayout).addListener(dragDismissListener)
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
super.onDestroyView(view)
|
||||
(view as ElasticDragDismissFrameLayout).removeListener(dragDismissListener)
|
||||
}
|
||||
}
|
||||
-147
@@ -1,147 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
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 androidx.annotation.ColorRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class ExternalModulesController extends BaseController {
|
||||
|
||||
private enum DemoModel {
|
||||
AUTODISPOSE("Autodispose", R.color.purple_300),
|
||||
RX_LIFECYCLE_2("Rx Lifecycle 2", R.color.blue_grey_300),
|
||||
ARCH_LIFECYCLE("Arch Components Lifecycle", R.color.orange_300);
|
||||
|
||||
String title;
|
||||
@ColorRes int color;
|
||||
|
||||
DemoModel(String title, @ColorRes int color) {
|
||||
this.title = title;
|
||||
this.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
@BindView(R.id.recycler_view) RecyclerView recyclerView;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_additional_modules, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
|
||||
recyclerView.setHasFixedSize(true);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
|
||||
recyclerView.setAdapter(new AdditionalModulesAdapter(LayoutInflater.from(view.getContext()), DemoModel.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChangeStarted(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
if (changeType.isEnter) {
|
||||
setTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "External Module Demos";
|
||||
}
|
||||
|
||||
void onModelRowClick(DemoModel model) {
|
||||
switch (model) {
|
||||
case AUTODISPOSE:
|
||||
getRouter().pushController(RouterTransaction.with(new AutodisposeController())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case RX_LIFECYCLE_2:
|
||||
getRouter().pushController(RouterTransaction.with(new RxLifecycle2Controller())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case ARCH_LIFECYCLE:
|
||||
getRouter().pushController(RouterTransaction.with(new ArchLifecycleController())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
class AdditionalModulesAdapter extends RecyclerView.Adapter<AdditionalModulesAdapter.ViewHolder> {
|
||||
|
||||
private final LayoutInflater inflater;
|
||||
private final DemoModel[] items;
|
||||
|
||||
public AdditionalModulesAdapter(LayoutInflater inflater, DemoModel[] items) {
|
||||
this.inflater = inflater;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(inflater.inflate(R.layout.row_home, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
holder.bind(items[position]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.length;
|
||||
}
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
@BindView(R.id.img_dot) ImageView imgDot;
|
||||
private DemoModel model;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
|
||||
void bind(DemoModel item) {
|
||||
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(model);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
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.RX_LIFECYCLE_2 -> router.pushController(
|
||||
with(RxLifecycle2Controller())
|
||||
.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),
|
||||
RX_LIFECYCLE_2("Rx Lifecycle 2", R.color.blue_grey_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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,286 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
import android.text.style.URLSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
import com.bluelinelabs.conductor.ControllerChangeType;
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
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;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class HomeController extends BaseController {
|
||||
|
||||
private enum DemoModel {
|
||||
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),
|
||||
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),
|
||||
MULTIPLE_CHILD_ROUTERS("Multiple Child Routers", R.color.grey_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);
|
||||
|
||||
String title;
|
||||
@ColorRes int color;
|
||||
|
||||
DemoModel(String title, @ColorRes int color) {
|
||||
this.title = title;
|
||||
this.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
private static final String KEY_FAB_VISIBILITY = "HomeController.fabVisibility";
|
||||
|
||||
@BindView(R.id.recycler_view) RecyclerView recyclerView;
|
||||
@BindView(R.id.fab) View fab;
|
||||
|
||||
public HomeController() {
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_home, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
|
||||
recyclerView.setHasFixedSize(true);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
|
||||
recyclerView.setAdapter(new HomeAdapter(LayoutInflater.from(view.getContext()), DemoModel.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveViewState(@NonNull View view, @NonNull Bundle outState) {
|
||||
super.onSaveViewState(view, outState);
|
||||
outState.putInt(KEY_FAB_VISIBILITY, fab.getVisibility());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreViewState(@NonNull View view, @NonNull Bundle savedViewState) {
|
||||
super.onRestoreViewState(view, savedViewState);
|
||||
|
||||
//noinspection WrongConstant
|
||||
fab.setVisibility(savedViewState.getInt(KEY_FAB_VISIBILITY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
inflater.inflate(R.menu.home, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChangeStarted(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
setOptionsMenuHidden(!changeType.isEnter);
|
||||
|
||||
if (changeType.isEnter) {
|
||||
setTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
if (item.getItemId() == R.id.about) {
|
||||
onFabClicked(false);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "Conductor Demos";
|
||||
}
|
||||
|
||||
@OnClick(R.id.fab)
|
||||
public void onFabClicked() {
|
||||
onFabClicked(true);
|
||||
}
|
||||
|
||||
private void onFabClicked(boolean fromFab) {
|
||||
SpannableString details = new SpannableString("A small, yet full-featured framework that allows building View-based Android applications");
|
||||
details.setSpan(new AbsoluteSizeSpan(16, true), 0, details.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
|
||||
final String url = "https://github.com/bluelinelabs/Conductor";
|
||||
SpannableString link = new SpannableString(url);
|
||||
link.setSpan(new URLSpan(url) {
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
|
||||
}
|
||||
}, 0, link.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
|
||||
SpannableStringBuilder description = new SpannableStringBuilder();
|
||||
description.append(details);
|
||||
description.append("\n\n");
|
||||
description.append(link);
|
||||
|
||||
ControllerChangeHandler pushHandler = fromFab ? new FabToDialogTransitionChangeHandler() : new FadeChangeHandler(false);
|
||||
ControllerChangeHandler popHandler = fromFab ? new FabToDialogTransitionChangeHandler() : new FadeChangeHandler();
|
||||
|
||||
getRouter()
|
||||
.pushController(RouterTransaction.with(new DialogController("Conductor", description))
|
||||
.pushChangeHandler(pushHandler)
|
||||
.popChangeHandler(popHandler));
|
||||
|
||||
}
|
||||
|
||||
void onModelRowClick(DemoModel model, int position) {
|
||||
switch (model) {
|
||||
case NAVIGATION:
|
||||
getRouter().pushController(RouterTransaction.with(new NavigationDemoController(0, DisplayUpMode.SHOW_FOR_CHILDREN_ONLY))
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler())
|
||||
.tag(NavigationDemoController.TAG_UP_TRANSACTION)
|
||||
);
|
||||
break;
|
||||
case TRANSITIONS:
|
||||
getRouter().pushController(TransitionDemoController.getRouterTransaction(0, this));
|
||||
break;
|
||||
case TARGET_CONTROLLER:
|
||||
getRouter().pushController(
|
||||
RouterTransaction.with(new TargetDisplayController())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case VIEW_PAGER:
|
||||
getRouter().pushController(RouterTransaction.with(new ViewPagerController())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case VIEW_PAGER_2:
|
||||
getRouter().pushController(RouterTransaction.with(new ViewPager2Controller())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case CHILD_CONTROLLERS:
|
||||
getRouter().pushController(RouterTransaction.with(new ParentController())
|
||||
.pushChangeHandler(new FadeChangeHandler())
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case SHARED_ELEMENT_TRANSITIONS:
|
||||
String titleSharedElementName = getResources().getString(R.string.transition_tag_title_indexed, position);
|
||||
String dotSharedElementName = getResources().getString(R.string.transition_tag_dot_indexed, position);
|
||||
|
||||
getRouter().pushController(RouterTransaction.with(new CityGridController(model.title, model.color, position))
|
||||
.pushChangeHandler(new ArcFadeMoveChangeHandler(titleSharedElementName, dotSharedElementName))
|
||||
.popChangeHandler(new ArcFadeMoveChangeHandler(titleSharedElementName, dotSharedElementName)));
|
||||
break;
|
||||
case DRAG_DISMISS:
|
||||
getRouter().pushController(RouterTransaction.with(new DragDismissController())
|
||||
.pushChangeHandler(new FadeChangeHandler(false))
|
||||
.popChangeHandler(new FadeChangeHandler()));
|
||||
break;
|
||||
case EXTERNAL_MODULES:
|
||||
getRouter().pushController(RouterTransaction.with(new ExternalModulesController())
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
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 inflater;
|
||||
private final DemoModel[] items;
|
||||
|
||||
public HomeAdapter(LayoutInflater inflater, DemoModel[] items) {
|
||||
this.inflater = inflater;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(inflater.inflate(R.layout.row_home, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
holder.bind(position, items[position]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.length;
|
||||
}
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
@BindView(R.id.img_dot) ImageView imgDot;
|
||||
private DemoModel model;
|
||||
private int position;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
|
||||
void bind(int position, DemoModel item) {
|
||||
model = item;
|
||||
tvTitle.setText(item.title);
|
||||
imgDot.getDrawable().setColorFilter(ContextCompat.getColor(getActivity(), item.color), Mode.SRC_ATOP);
|
||||
this.position = position;
|
||||
|
||||
ViewCompat.setTransitionName(tvTitle, getResources().getString(R.string.transition_tag_title_indexed, position));
|
||||
ViewCompat.setTransitionName(imgDot, getResources().getString(R.string.transition_tag_dot_indexed, position));
|
||||
}
|
||||
|
||||
@OnClick(R.id.row_root)
|
||||
void onRowClick() {
|
||||
onModelRowClick(model, position);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.PorterDuff
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableString
|
||||
import android.text.Spanned
|
||||
import android.text.style.AbsoluteSizeSpan
|
||||
import android.text.style.URLSpan
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.text.buildSpannedString
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
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
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerHomeBinding
|
||||
import com.bluelinelabs.conductor.demo.databinding.RowHomeBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
class HomeController : BaseController(R.layout.controller_home) {
|
||||
private val binding: ControllerHomeBinding by viewBinding(ControllerHomeBinding::bind)
|
||||
|
||||
override val title = "Conductor Demos"
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
binding.recyclerView.setHasFixedSize(true)
|
||||
binding.recyclerView.layoutManager = LinearLayoutManager(view.context)
|
||||
binding.recyclerView.adapter = HomeAdapter(
|
||||
LayoutInflater.from(view.context),
|
||||
DemoModel.values(),
|
||||
::onModelRowClick
|
||||
)
|
||||
|
||||
binding.fab.setOnClickListener { showAboutDialog(fromFab = true) }
|
||||
}
|
||||
|
||||
override fun configureToolbar(toolbar: Toolbar) {
|
||||
super.configureToolbar(toolbar)
|
||||
|
||||
toolbar.setOnMenuItemClickListener {
|
||||
if (it.itemId == R.id.about) {
|
||||
showAboutDialog(fromFab = false)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun configureMenu(toolbar: Toolbar) {
|
||||
super.configureMenu(toolbar)
|
||||
|
||||
toolbar.inflateMenu(R.menu.home)
|
||||
}
|
||||
|
||||
override fun onSaveViewState(view: View, outState: Bundle) {
|
||||
super.onSaveViewState(view, outState)
|
||||
outState.putInt(KEY_FAB_VISIBILITY, binding.fab.visibility)
|
||||
}
|
||||
|
||||
override fun onRestoreViewState(view: View, savedViewState: Bundle) {
|
||||
super.onRestoreViewState(view, savedViewState)
|
||||
binding.fab.visibility = savedViewState.getInt(KEY_FAB_VISIBILITY)
|
||||
}
|
||||
|
||||
private fun onModelRowClick(model: DemoModel, position: Int) {
|
||||
when (model) {
|
||||
DemoModel.NAVIGATION -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(NavigationDemoController(0, DisplayUpMode.SHOW_FOR_CHILDREN_ONLY))
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
.tag(NavigationDemoController.TAG_UP_TRANSACTION)
|
||||
)
|
||||
}
|
||||
DemoModel.TRANSITIONS -> {
|
||||
router.pushController(TransitionDemoController.getRouterTransaction(0, this))
|
||||
}
|
||||
DemoModel.TARGET_CONTROLLER -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(TargetDisplayController())
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
)
|
||||
}
|
||||
DemoModel.VIEW_PAGER -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(ViewPagerController())
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
)
|
||||
}
|
||||
DemoModel.VIEW_PAGER_2 -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(ViewPager2Controller())
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
)
|
||||
}
|
||||
DemoModel.CHILD_CONTROLLERS -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(ParentController())
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.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)
|
||||
router.pushController(
|
||||
RouterTransaction.with(CityGridController(model.title, model.color, position))
|
||||
.pushChangeHandler(ArcFadeMoveChangeHandler(titleSharedElementName, dotSharedElementName))
|
||||
.popChangeHandler(ArcFadeMoveChangeHandler(titleSharedElementName, dotSharedElementName))
|
||||
)
|
||||
}
|
||||
DemoModel.DRAG_DISMISS -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(DragDismissController())
|
||||
.pushChangeHandler(FadeChangeHandler(false))
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
)
|
||||
}
|
||||
DemoModel.EXTERNAL_MODULES -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(ExternalModulesController())
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
)
|
||||
}
|
||||
DemoModel.MULTIPLE_CHILD_ROUTERS -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(MultipleChildRouterController())
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
)
|
||||
}
|
||||
DemoModel.MASTER_DETAIL -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(MasterDetailListController())
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showAboutDialog(fromFab: Boolean) {
|
||||
val details = SpannableString("A small, yet full-featured framework that allows building View-based Android applications").apply {
|
||||
setSpan(AbsoluteSizeSpan(16, true), 0, length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
|
||||
}
|
||||
|
||||
val link = SpannableString(CONDUCTOR_URL).apply {
|
||||
setSpan(object : URLSpan(CONDUCTOR_URL) {
|
||||
override fun onClick(widget: View) {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
||||
}
|
||||
}, 0, length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
|
||||
}
|
||||
|
||||
val description = buildSpannedString {
|
||||
append(details)
|
||||
append("\n\n")
|
||||
append(link)
|
||||
}
|
||||
|
||||
val pushHandler = if (fromFab) FabToDialogTransitionChangeHandler() else FadeChangeHandler(false)
|
||||
val popHandler = if (fromFab) FabToDialogTransitionChangeHandler() else FadeChangeHandler()
|
||||
router.pushController(
|
||||
RouterTransaction.with(DialogController("Conductor", description))
|
||||
.pushChangeHandler(pushHandler)
|
||||
.popChangeHandler(popHandler)
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_FAB_VISIBILITY = "HomeController.fabVisibility"
|
||||
private const val CONDUCTOR_URL = "https://github.com/bluelinelabs/Conductor"
|
||||
}
|
||||
}
|
||||
|
||||
private enum class DemoModel(val title: String, @ColorRes val color: Int) {
|
||||
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),
|
||||
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),
|
||||
MULTIPLE_CHILD_ROUTERS("Multiple Child Routers", R.color.grey_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(
|
||||
private val inflater: LayoutInflater,
|
||||
private val items: Array<DemoModel>,
|
||||
private val modelClickListener: (DemoModel, Int) -> Unit
|
||||
) : RecyclerView.Adapter<HomeAdapter.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(position, items[position])
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
class ViewHolder(
|
||||
private val binding: RowHomeBinding,
|
||||
private val modelClickListener: (DemoModel, Int) -> Unit
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(position: Int, item: DemoModel) {
|
||||
binding.title.text = item.title
|
||||
binding.dot.drawable.setColorFilter(
|
||||
ContextCompat.getColor(binding.root.context, item.color),
|
||||
PorterDuff.Mode.SRC_ATOP
|
||||
)
|
||||
binding.root.setOnClickListener { modelClickListener(item, position) }
|
||||
|
||||
binding.title.transitionName =
|
||||
binding.root.resources.getString(R.string.transition_tag_title_indexed, position)
|
||||
binding.dot.transitionName =
|
||||
binding.root.resources.getString(R.string.transition_tag_dot_indexed, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
-158
@@ -1,158 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.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).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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
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.HorizontalChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerMasterDetailListBinding
|
||||
import com.bluelinelabs.conductor.demo.databinding.RowDetailItemBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
class MasterDetailListController : BaseController(R.layout.controller_master_detail_list) {
|
||||
private val binding: ControllerMasterDetailListBinding by viewBinding(ControllerMasterDetailListBinding::bind)
|
||||
|
||||
override val title = "Master/Detail Flow"
|
||||
|
||||
private lateinit var adapter: DetailItemAdapter
|
||||
private var selectedIndex = 0
|
||||
private var twoPaneView = false
|
||||
|
||||
private val dataModels = mutableListOf(
|
||||
DetailItemModel(
|
||||
"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
|
||||
),
|
||||
DetailItemModel(
|
||||
"Item 2",
|
||||
"This is another item.",
|
||||
R.color.cyan_300
|
||||
),
|
||||
DetailItemModel(
|
||||
"Item 3",
|
||||
"Wow, a 3rd item!",
|
||||
R.color.deep_purple_300
|
||||
)
|
||||
)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
adapter = DetailItemAdapter(LayoutInflater.from(view.context), dataModels, ::onRowSelected)
|
||||
|
||||
binding.recyclerView.setHasFixedSize(true)
|
||||
binding.recyclerView.layoutManager = LinearLayoutManager(view.context)
|
||||
binding.recyclerView.adapter = adapter
|
||||
twoPaneView = binding.detailContainer != null
|
||||
if (twoPaneView) {
|
||||
onRowSelected(selectedIndex)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putInt(KEY_SELECTED_INDEX, selectedIndex)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
selectedIndex = savedInstanceState.getInt(KEY_SELECTED_INDEX)
|
||||
}
|
||||
|
||||
private fun onRowSelected(index: Int) {
|
||||
dataModels[selectedIndex] = dataModels[selectedIndex].copy(selected = false)
|
||||
selectedIndex = index
|
||||
dataModels[selectedIndex] = dataModels[selectedIndex].copy(selected = true)
|
||||
|
||||
val model = dataModels[selectedIndex]
|
||||
val controller = ChildController(model.detail, model.backgroundColor, true)
|
||||
if (twoPaneView) {
|
||||
getChildRouter(binding.detailContainer!!).setRoot(with(controller))
|
||||
} else {
|
||||
router.pushController(
|
||||
with(controller)
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_SELECTED_INDEX = "MasterDetailListController.selectedIndex"
|
||||
}
|
||||
}
|
||||
|
||||
data class DetailItemModel(val title: String, val detail: String, val backgroundColor: Int, val selected: Boolean = false)
|
||||
|
||||
class DetailItemAdapter(
|
||||
private val inflater: LayoutInflater,
|
||||
private val items: List<DetailItemModel>,
|
||||
private val rowClickListener: (Int) -> Unit
|
||||
) : RecyclerView.Adapter<DetailItemAdapter.ViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(RowDetailItemBinding.inflate(inflater, parent, false)) { position ->
|
||||
rowClickListener(position)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(items[position], position)
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
class ViewHolder(
|
||||
private val binding: RowDetailItemBinding,
|
||||
private val rowClickListener: (Int) -> Unit
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: DetailItemModel, position: Int) {
|
||||
binding.title.text = item.title
|
||||
|
||||
if (item.selected) {
|
||||
itemView.setBackgroundColor(ContextCompat.getColor(itemView.context, R.color.grey_400))
|
||||
} else {
|
||||
itemView.setBackgroundColor(ContextCompat.getColor(itemView.context, android.R.color.transparent))
|
||||
}
|
||||
|
||||
itemView.setOnClickListener { rowClickListener(position) }
|
||||
}
|
||||
}
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import androidx.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.NavigationDemoController.DisplayUpMode;
|
||||
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).setPopsLastView(false);
|
||||
if (!childRouter.hasRootController()) {
|
||||
childRouter.setRoot(RouterTransaction.with(new NavigationDemoController(0, DisplayUpMode.HIDE)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "Child Router Demo";
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.view.View
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerMultipleChildRoutersBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
class MultipleChildRouterController : BaseController(R.layout.controller_multiple_child_routers) {
|
||||
private val binding: ControllerMultipleChildRoutersBinding by viewBinding(ControllerMultipleChildRoutersBinding::bind)
|
||||
|
||||
override val title = "Child Router Demo"
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
val childContainers = listOf(binding.container0, binding.container1, binding.container2)
|
||||
|
||||
childContainers.forEach { container ->
|
||||
val childRouter = getChildRouter(container).setPopsLastView(false)
|
||||
if (!childRouter.hasRootController()) {
|
||||
childRouter.setRoot(RouterTransaction.with(NavigationDemoController(0, NavigationDemoController.DisplayUpMode.HIDE)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-121
@@ -1,121 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
import com.bluelinelabs.conductor.ControllerChangeType;
|
||||
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 com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
import com.bluelinelabs.conductor.demo.util.ColorUtil;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class NavigationDemoController extends BaseController {
|
||||
|
||||
public enum DisplayUpMode {
|
||||
SHOW,
|
||||
SHOW_FOR_CHILDREN_ONLY,
|
||||
HIDE;
|
||||
|
||||
private DisplayUpMode getDisplayUpModeForChild() {
|
||||
switch (this) {
|
||||
case HIDE:
|
||||
return HIDE;
|
||||
default:
|
||||
return SHOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final String TAG_UP_TRANSACTION = "NavigationDemoController.up";
|
||||
|
||||
private static final String KEY_INDEX = "NavigationDemoController.index";
|
||||
private static final String KEY_DISPLAY_UP_MODE = "NavigationDemoController.displayUpMode";
|
||||
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
|
||||
private int index;
|
||||
private DisplayUpMode displayUpMode;
|
||||
|
||||
public NavigationDemoController(int index, DisplayUpMode displayUpMode) {
|
||||
this(new BundleBuilder(new Bundle())
|
||||
.putInt(KEY_INDEX, index)
|
||||
.putInt(KEY_DISPLAY_UP_MODE, displayUpMode.ordinal())
|
||||
.build());
|
||||
}
|
||||
|
||||
public NavigationDemoController(Bundle args) {
|
||||
super(args);
|
||||
index = args.getInt(KEY_INDEX);
|
||||
displayUpMode = DisplayUpMode.values()[args.getInt(KEY_DISPLAY_UP_MODE)];
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_navigation_demo, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
|
||||
if (displayUpMode != DisplayUpMode.SHOW) {
|
||||
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
|
||||
protected void onChangeEnded(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
super.onChangeEnded(changeHandler, changeType);
|
||||
|
||||
setButtonsEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChangeStarted(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
super.onChangeStarted(changeHandler, changeType);
|
||||
|
||||
setButtonsEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "Navigation Demos";
|
||||
}
|
||||
|
||||
private void setButtonsEnabled(boolean enabled) {
|
||||
final View view = getView();
|
||||
if (view != null) {
|
||||
view.findViewById(R.id.btn_next).setEnabled(enabled);
|
||||
view.findViewById(R.id.btn_up).setEnabled(enabled);
|
||||
view.findViewById(R.id.btn_pop_to_root).setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_next) void onNextClicked() {
|
||||
getRouter().pushController(RouterTransaction.with(new NavigationDemoController(index + 1, displayUpMode.getDisplayUpModeForChild()))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_up) void onUpClicked() {
|
||||
getRouter().popToTag(TAG_UP_TRANSACTION);
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_pop_to_root) void onPopToRootClicked() {
|
||||
getRouter().popToRoot();
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isVisible
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
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 com.bluelinelabs.conductor.demo.databinding.ControllerNavigationDemoBinding
|
||||
import com.bluelinelabs.conductor.demo.util.getMaterialColor
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
class NavigationDemoController(args: Bundle) : BaseController(R.layout.controller_navigation_demo, args) {
|
||||
private val binding: ControllerNavigationDemoBinding by viewBinding(ControllerNavigationDemoBinding::bind)
|
||||
|
||||
private val index = args.getInt(KEY_INDEX)
|
||||
private val displayUpMode = DisplayUpMode.values()[args.getInt(KEY_DISPLAY_UP_MODE)]
|
||||
|
||||
override val title = "Navigation Demos"
|
||||
|
||||
constructor(index: Int, displayUpMode: DisplayUpMode) : this(
|
||||
bundleOf(
|
||||
KEY_INDEX to index,
|
||||
KEY_DISPLAY_UP_MODE to displayUpMode.ordinal
|
||||
)
|
||||
)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
binding.root.setBackgroundColor(view.resources.getMaterialColor(index))
|
||||
binding.goUp.isVisible = displayUpMode == DisplayUpMode.SHOW
|
||||
binding.title.text = view.resources.getString(R.string.navigation_title, index)
|
||||
|
||||
binding.popToRoot.setOnClickListener { router.popToRoot() }
|
||||
binding.goUp.setOnClickListener { router.popToTag(TAG_UP_TRANSACTION) }
|
||||
binding.goToNext.setOnClickListener {
|
||||
router.pushController(
|
||||
RouterTransaction.with(NavigationDemoController(index + 1, displayUpMode.displayUpModeForChild))
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChangeEnded(
|
||||
changeHandler: ControllerChangeHandler,
|
||||
changeType: ControllerChangeType
|
||||
) {
|
||||
super.onChangeEnded(changeHandler, changeType)
|
||||
if (changeType.isEnter) {
|
||||
setButtonsEnabled(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChangeStarted(
|
||||
changeHandler: ControllerChangeHandler,
|
||||
changeType: ControllerChangeType
|
||||
) {
|
||||
super.onChangeStarted(changeHandler, changeType)
|
||||
setButtonsEnabled(false)
|
||||
}
|
||||
|
||||
private fun setButtonsEnabled(enabled: Boolean) {
|
||||
binding.goToNext.isEnabled = enabled
|
||||
binding.goUp.isEnabled = enabled
|
||||
binding.popToRoot.isEnabled = enabled
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG_UP_TRANSACTION = "NavigationDemoController.up"
|
||||
|
||||
private const val KEY_INDEX = "NavigationDemoController.index"
|
||||
private const val KEY_DISPLAY_UP_MODE = "NavigationDemoController.displayUpMode"
|
||||
}
|
||||
|
||||
enum class DisplayUpMode {
|
||||
SHOW, SHOW_FOR_CHILDREN_ONLY, HIDE;
|
||||
|
||||
val displayUpModeForChild: DisplayUpMode
|
||||
get() = when (this) {
|
||||
HIDE -> HIDE
|
||||
else -> SHOW
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
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;
|
||||
import com.bluelinelabs.conductor.demo.util.ColorUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ParentController extends BaseController {
|
||||
|
||||
private static final int NUMBER_OF_CHILDREN = 5;
|
||||
private boolean finishing;
|
||||
private boolean hasShownAll;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_parent, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChangeEnded(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
super.onChangeEnded(changeHandler, changeType);
|
||||
|
||||
if (changeType == ControllerChangeType.PUSH_ENTER) {
|
||||
addChild(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void addChild(final int index) {
|
||||
@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).setPopsLastView(true);
|
||||
|
||||
if (!childRouter.hasRootController()) {
|
||||
ChildController childController = new ChildController("Child Controller #" + index, ColorUtil.getMaterialColor(getResources(), index), false);
|
||||
|
||||
childController.addLifecycleListener(new LifecycleListener() {
|
||||
@Override
|
||||
public void onChangeEnd(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
if (!isBeingDestroyed()) {
|
||||
if (changeType == ControllerChangeType.PUSH_ENTER && !hasShownAll) {
|
||||
if (index < NUMBER_OF_CHILDREN - 1) {
|
||||
addChild(index + 1);
|
||||
} else {
|
||||
hasShownAll = true;
|
||||
}
|
||||
} 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()));
|
||||
}
|
||||
}
|
||||
|
||||
private void removeChild(int index) {
|
||||
List<Router> childRouters = getChildRouters();
|
||||
if (index < childRouters.size()) {
|
||||
removeChildRouter(childRouters.get(index));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleBack() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "Parent/Child Demo";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
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 com.bluelinelabs.conductor.demo.databinding.ControllerParentBinding
|
||||
import com.bluelinelabs.conductor.demo.util.getMaterialColor
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
|
||||
class ParentController : BaseController(R.layout.controller_parent) {
|
||||
private val binding: ControllerParentBinding by viewBinding(ControllerParentBinding::bind)
|
||||
|
||||
override val title = "Parent/Child Demo"
|
||||
|
||||
private var hasShownAll = false
|
||||
private var animatingOut = false
|
||||
|
||||
override fun onChangeEnded(
|
||||
changeHandler: ControllerChangeHandler,
|
||||
changeType: ControllerChangeType
|
||||
) {
|
||||
if (changeType == ControllerChangeType.PUSH_ENTER) {
|
||||
addChild(0)
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleBack(): Boolean {
|
||||
val childControllers = childRouters.filter { it.hasRootController() }.size
|
||||
|
||||
return if (childControllers != NUMBER_OF_CHILDREN || animatingOut) {
|
||||
true
|
||||
} else {
|
||||
animatingOut = true
|
||||
super.handleBack()
|
||||
}
|
||||
}
|
||||
|
||||
private fun addChild(index: Int) {
|
||||
val container = when (index) {
|
||||
0 -> binding.childContent1
|
||||
1 -> binding.childContent2
|
||||
2 -> binding.childContent3
|
||||
3 -> binding.childContent4
|
||||
4 -> binding.childContent5
|
||||
else -> throw IllegalStateException("Invalid child index $index")
|
||||
}
|
||||
|
||||
val childRouter = getChildRouter(container).setPopsLastView(true)
|
||||
if (!childRouter.hasRootController()) {
|
||||
val child = ChildController(
|
||||
title = "Child Controller #$index",
|
||||
backgroundColor = resources!!.getMaterialColor(index),
|
||||
colorIsResId = false
|
||||
)
|
||||
child.addLifecycleListener(object : LifecycleListener() {
|
||||
override fun onChangeEnd(
|
||||
controller: Controller,
|
||||
changeHandler: ControllerChangeHandler,
|
||||
changeType: ControllerChangeType
|
||||
) {
|
||||
if (!isBeingDestroyed) {
|
||||
if (changeType == ControllerChangeType.PUSH_ENTER && !hasShownAll) {
|
||||
if (index < NUMBER_OF_CHILDREN - 1) {
|
||||
addChild(index + 1)
|
||||
} else {
|
||||
hasShownAll = true
|
||||
}
|
||||
} else if (changeType == ControllerChangeType.POP_EXIT) {
|
||||
if (index > 0) {
|
||||
removeChild(index - 1)
|
||||
} else {
|
||||
router.popController(this@ParentController)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
childRouter.setRoot(
|
||||
RouterTransaction.with(child)
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeChild(index: Int) {
|
||||
val childRouters = childRouters
|
||||
if (index < childRouters.size) {
|
||||
removeChildRouter(childRouters[index])
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val NUMBER_OF_CHILDREN = 5
|
||||
}
|
||||
}
|
||||
-138
@@ -1,138 +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 android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
import com.bluelinelabs.conductor.ControllerChangeType;
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||
import com.bluelinelabs.conductor.demo.ActionBarProvider;
|
||||
import com.bluelinelabs.conductor.demo.DemoApplication;
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.rxlifecycle2.ControllerEvent;
|
||||
import com.bluelinelabs.conductor.rxlifecycle2.RxController;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.Unbinder;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.functions.Action;
|
||||
import io.reactivex.functions.Consumer;
|
||||
|
||||
// Shamelessly borrowed from the official RxLifecycle demo by Trello and adapted for Conductor Controllers
|
||||
// instead of Activities or Fragments.
|
||||
public class RxLifecycle2Controller extends RxController {
|
||||
|
||||
private static final String TAG = "RxLifecycleController";
|
||||
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
|
||||
private Unbinder unbinder;
|
||||
private boolean hasExited;
|
||||
|
||||
public RxLifecycle2Controller() {
|
||||
Observable.interval(1, TimeUnit.SECONDS)
|
||||
.doOnDispose(() -> Log.i(TAG, "Disposing from constructor"))
|
||||
.compose(this.<Long>bindUntilEvent(ControllerEvent.DESTROY))
|
||||
.subscribe(num -> Log.i(TAG, "Started in constructor, running until onDestroy(): " + num));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container, @Nullable Bundle savedViewState) {
|
||||
Log.i(TAG, "onCreateView() called");
|
||||
|
||||
View view = inflater.inflate(R.layout.controller_lifecycle, container, false);
|
||||
view.setBackgroundColor(ContextCompat.getColor(container.getContext(), R.color.blue_grey_300));
|
||||
unbinder = ButterKnife.bind(this, view);
|
||||
|
||||
tvTitle.setText(getResources().getString(R.string.rxlifecycle_title, TAG));
|
||||
|
||||
Observable.interval(1, TimeUnit.SECONDS)
|
||||
.doOnDispose(() -> Log.i(TAG, "Disposing from onCreateView()"))
|
||||
.compose(this.<Long>bindUntilEvent(ControllerEvent.DESTROY_VIEW))
|
||||
.subscribe(num -> Log.i(TAG, "Started in onCreateView(), running until onDestroyView(): " + num));
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttach(@NonNull View view) {
|
||||
super.onAttach(view);
|
||||
|
||||
Log.i(TAG, "onAttach() called");
|
||||
|
||||
(((ActionBarProvider)getActivity()).getSupportActionBar()).setTitle("RxLifecycle2 Demo");
|
||||
|
||||
Observable.interval(1, TimeUnit.SECONDS)
|
||||
.doOnDispose(() -> Log.i(TAG, "Disposing from onAttach()"))
|
||||
.compose(this.<Long>bindUntilEvent(ControllerEvent.DETACH))
|
||||
.subscribe(num -> Log.i(TAG, "Started in onAttach(), running until onDetach(): " + num));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroyView(@NonNull View view) {
|
||||
super.onDestroyView(view);
|
||||
|
||||
Log.i(TAG, "onDestroyView() called");
|
||||
|
||||
unbinder.unbind();
|
||||
unbinder = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetach(@NonNull View view) {
|
||||
super.onDetach(view);
|
||||
|
||||
Log.i(TAG, "onDetach() called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
Log.i(TAG, "onDestroy() called");
|
||||
|
||||
if (hasExited) {
|
||||
DemoApplication.refWatcher.watch(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChangeEnded(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
super.onChangeEnded(changeHandler, changeType);
|
||||
|
||||
hasExited = !changeType.isEnter;
|
||||
if (isDestroyed()) {
|
||||
DemoApplication.refWatcher.watch(this);
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_next_release_view) void onNextWithReleaseClicked() {
|
||||
setRetainViewMode(RetainViewMode.RELEASE_DETACH);
|
||||
|
||||
getRouter().pushController(RouterTransaction.with(new TextController("Logcat should now report that the observables from onAttach() and onViewBound() have been disposed of, while the constructor observable is still running."))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_next_retain_view) void onNextWithRetainClicked() {
|
||||
setRetainViewMode(RetainViewMode.RETAIN_DETACH);
|
||||
|
||||
getRouter().pushController(RouterTransaction.with(new TextController("Logcat should now report that the observables from onAttach() has been disposed of, while the constructor and onViewBound() observables are still running."))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
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.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.bluelinelabs.conductor.RouterTransaction.Companion.with
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.DemoApplication
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.ToolbarProvider
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerLifecycleBinding
|
||||
import com.bluelinelabs.conductor.rxlifecycle2.ControllerEvent
|
||||
import com.bluelinelabs.conductor.rxlifecycle2.RxController
|
||||
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 RxLifecycle2Controller : RxController() {
|
||||
|
||||
private var hasExited = false
|
||||
|
||||
init {
|
||||
Observable.interval(1, TimeUnit.SECONDS)
|
||||
.doOnDispose { Log.i(TAG, "Disposing from constructor") }
|
||||
.compose(bindUntilEvent(ControllerEvent.DESTROY))
|
||||
.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()") }
|
||||
.compose(bindUntilEvent(ControllerEvent.DESTROY_VIEW))
|
||||
.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 = "RxLifecycle2 Demo"
|
||||
Observable.interval(1, TimeUnit.SECONDS)
|
||||
.doOnDispose { Log.i(TAG, "Disposing from onAttach()") }
|
||||
.compose(bindUntilEvent(ControllerEvent.DETACH))
|
||||
.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")
|
||||
if (hasExited) {
|
||||
DemoApplication.refWatcher.watch(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChangeEnded(
|
||||
changeHandler: ControllerChangeHandler,
|
||||
changeType: ControllerChangeType
|
||||
) {
|
||||
super.onChangeEnded(changeHandler, changeType)
|
||||
hasExited = !changeType.isEnter
|
||||
if (isDestroyed) {
|
||||
DemoApplication.refWatcher.watch(this)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "RxLifecycleController"
|
||||
}
|
||||
|
||||
}
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.MediaStore;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
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.TargetTitleEntryController.TargetTitleEntryControllerListener;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class TargetDisplayController extends BaseController implements TargetTitleEntryControllerListener {
|
||||
|
||||
private static final int REQUEST_SELECT_IMAGE = 126;
|
||||
|
||||
private static final String KEY_SELECTED_TEXT = "TargetDisplayController.selectedText";
|
||||
private static final String KEY_SELECTED_IMAGE = "TargetDisplayController.selectedImage";
|
||||
|
||||
@BindView(R.id.tv_selection) TextView tvSelection;
|
||||
@BindView(R.id.image_view) ImageView imageView;
|
||||
|
||||
private String selectedText;
|
||||
private Uri imageUri;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_target_display, container, false);
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_pick_title) void launchTitlePicker() {
|
||||
getRouter().pushController(RouterTransaction.with(new TargetTitleEntryController(this))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_pick_image) void launchImagePicker() {
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||
intent.setType("image/*");
|
||||
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
|
||||
startActivityForResult(Intent.createChooser(intent, "Select Image"), REQUEST_SELECT_IMAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTitlePicked(String option) {
|
||||
selectedText = option;
|
||||
setTextView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == REQUEST_SELECT_IMAGE && resultCode == Activity.RESULT_OK) {
|
||||
imageUri = data.getData();
|
||||
setImageView();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
setTextView();
|
||||
setImageView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
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);
|
||||
selectedText = savedInstanceState.getString(KEY_SELECTED_TEXT);
|
||||
|
||||
String uriString = savedInstanceState.getString(KEY_SELECTED_IMAGE);
|
||||
if (!TextUtils.isEmpty(uriString)) {
|
||||
imageUri = Uri.parse(uriString);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "Target Controller Demo";
|
||||
}
|
||||
|
||||
private void setImageView() {
|
||||
Picasso.with(getActivity())
|
||||
.load(imageUri)
|
||||
.fit()
|
||||
.centerCrop()
|
||||
.into(imageView);
|
||||
}
|
||||
|
||||
private void setTextView() {
|
||||
if (tvSelection != null) {
|
||||
if (!TextUtils.isEmpty(selectedText)) {
|
||||
tvSelection.setText(selectedText);
|
||||
} else {
|
||||
tvSelection.setText("Press pick title to set this title, or pick image to fill in the image view.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import android.view.View
|
||||
import com.bluelinelabs.conductor.RouterTransaction.Companion.with
|
||||
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.bluelinelabs.conductor.demo.databinding.ControllerTargetDisplayBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
import com.squareup.picasso.Picasso
|
||||
|
||||
class TargetDisplayController : BaseController(R.layout.controller_target_display), TargetTitleEntryControllerListener {
|
||||
private val binding: ControllerTargetDisplayBinding by viewBinding(ControllerTargetDisplayBinding::bind)
|
||||
|
||||
override val title = "Target Controller Demo"
|
||||
|
||||
private var selectedText: String? = null
|
||||
private var imageUri: Uri? = null
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
setTextView()
|
||||
setImageView()
|
||||
|
||||
binding.pickTitleButton.setOnClickListener {
|
||||
router.pushController(
|
||||
with(TargetTitleEntryController(this))
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
)
|
||||
}
|
||||
|
||||
binding.pickImageButton.setOnClickListener {
|
||||
val intent = Intent(Intent.ACTION_GET_CONTENT, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
|
||||
intent.type = "image/*"
|
||||
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true)
|
||||
startActivityForResult(Intent.createChooser(intent, "Select Image"), REQUEST_SELECT_IMAGE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTitlePicked(option: String?) {
|
||||
selectedText = option
|
||||
setTextView()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == REQUEST_SELECT_IMAGE && resultCode == Activity.RESULT_OK) {
|
||||
imageUri = data?.data
|
||||
setImageView()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putString(KEY_SELECTED_TEXT, selectedText)
|
||||
outState.putString(KEY_SELECTED_IMAGE, if (imageUri != null) imageUri.toString() else null)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
selectedText = savedInstanceState.getString(KEY_SELECTED_TEXT)
|
||||
val uriString = savedInstanceState.getString(KEY_SELECTED_IMAGE)
|
||||
if (!uriString.isNullOrEmpty()) {
|
||||
imageUri = Uri.parse(uriString)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setImageView() {
|
||||
view ?: return
|
||||
|
||||
Picasso.with(activity)
|
||||
.load(imageUri)
|
||||
.fit()
|
||||
.centerCrop()
|
||||
.into(binding.imageView)
|
||||
}
|
||||
|
||||
private fun setTextView() {
|
||||
view ?: return
|
||||
|
||||
if (!selectedText.isNullOrEmpty()) {
|
||||
binding.selection.text = selectedText
|
||||
} else {
|
||||
binding.selection.text = "Press pick title to set this title, or pick image to fill in the image view."
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val REQUEST_SELECT_IMAGE = 126
|
||||
private const val KEY_SELECTED_TEXT = "TargetDisplayController.selectedText"
|
||||
private const val KEY_SELECTED_IMAGE = "TargetDisplayController.selectedImage"
|
||||
}
|
||||
}
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.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.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class TargetTitleEntryController extends BaseController {
|
||||
|
||||
public interface TargetTitleEntryControllerListener {
|
||||
void onTitlePicked(String option);
|
||||
}
|
||||
|
||||
@BindView(R.id.edit_text) EditText editText;
|
||||
|
||||
public <T extends Controller & TargetTitleEntryControllerListener> TargetTitleEntryController(T targetController) {
|
||||
setTargetController(targetController);
|
||||
}
|
||||
|
||||
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) {
|
||||
return inflater.inflate(R.layout.controller_target_title_entry, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "Target Controller Demo";
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_use_title) void optionPicked() {
|
||||
Controller targetController = getTargetController();
|
||||
if (targetController != null) {
|
||||
((TargetTitleEntryControllerListener)targetController).onTitlePicked(editText.getText().toString());
|
||||
getRouter().popController(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerTargetTitleEntryBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
class TargetTitleEntryController() : BaseController(R.layout.controller_target_title_entry) {
|
||||
private val binding: ControllerTargetTitleEntryBinding by viewBinding(ControllerTargetTitleEntryBinding::bind)
|
||||
|
||||
override val title = "Target Controller Demo"
|
||||
|
||||
constructor(targetController: TargetTitleEntryControllerListener) : this() {
|
||||
check(targetController is Controller)
|
||||
setTargetController(targetController)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.useTitleButton.setOnClickListener {
|
||||
targetController?.let { listener ->
|
||||
(listener as TargetTitleEntryControllerListener).onTitlePicked(binding.editText.text.toString())
|
||||
router.popController(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetach(view: View) {
|
||||
val imm = binding.editText.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.hideSoftInputFromWindow(binding.editText.windowToken, 0)
|
||||
}
|
||||
|
||||
interface TargetTitleEntryControllerListener {
|
||||
fun onTitlePicked(option: String?)
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class TextController extends BaseController {
|
||||
|
||||
private static final String KEY_TEXT = "TextController.text";
|
||||
|
||||
@BindView(R.id.text_view) TextView textView;
|
||||
|
||||
public TextController(String text) {
|
||||
this(new BundleBuilder(new Bundle())
|
||||
.putString(KEY_TEXT, text)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
public TextController(Bundle args) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_text, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
textView.setText(getArgs().getString(KEY_TEXT));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.os.bundleOf
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerTextBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
class TextController(args: Bundle) : BaseController(R.layout.controller_text, args) {
|
||||
private val binding: ControllerTextBinding by viewBinding(ControllerTextBinding::bind)
|
||||
|
||||
constructor(text: String) : this(bundleOf(KEY_TEXT to text))
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
binding.textView.text = args.getString(KEY_TEXT)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_TEXT = "TextController.text"
|
||||
}
|
||||
}
|
||||
-146
@@ -1,146 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler;
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
import com.bluelinelabs.conductor.demo.changehandler.ArcFadeMoveChangeHandler;
|
||||
import com.bluelinelabs.conductor.demo.changehandler.CircularRevealChangeHandlerCompat;
|
||||
import com.bluelinelabs.conductor.demo.changehandler.FlipChangeHandler;
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
|
||||
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
public class TransitionDemoController extends BaseController {
|
||||
|
||||
private static final String KEY_INDEX = "TransitionDemoController.index";
|
||||
|
||||
public enum TransitionDemo {
|
||||
VERTICAL("Vertical Slide Animation", R.layout.controller_transition_demo, R.color.blue_grey_300),
|
||||
CIRCULAR("Circular Reveal Animation", R.layout.controller_transition_demo, R.color.red_300),
|
||||
FADE("Fade Animation", R.layout.controller_transition_demo, R.color.blue_300),
|
||||
FLIP("Flip Animation", R.layout.controller_transition_demo, R.color.deep_orange_300),
|
||||
HORIZONTAL("Horizontal Slide Animation", R.layout.controller_transition_demo, R.color.green_300),
|
||||
ARC_FADE("Arc/Fade Shared Element Transition", R.layout.controller_transition_demo_shared, 0),
|
||||
ARC_FADE_RESET("Arc/Fade Shared Element Transition", R.layout.controller_transition_demo, R.color.pink_300);
|
||||
|
||||
String title;
|
||||
int layoutId;
|
||||
int colorId;
|
||||
|
||||
TransitionDemo(String title, @LayoutRes int layoutId, @ColorRes int colorId) {
|
||||
this.title = title;
|
||||
this.layoutId = layoutId;
|
||||
this.colorId = colorId;
|
||||
}
|
||||
|
||||
public static TransitionDemo fromIndex(int index) {
|
||||
return TransitionDemo.values()[index];
|
||||
}
|
||||
}
|
||||
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
@BindView(R.id.btn_next) FloatingActionButton btnNext;
|
||||
@BindView(R.id.transition_root) View containerView;
|
||||
|
||||
private TransitionDemo transitionDemo;
|
||||
|
||||
public TransitionDemoController(int index) {
|
||||
this(new BundleBuilder(new Bundle())
|
||||
.putInt(KEY_INDEX, index)
|
||||
.build());
|
||||
}
|
||||
|
||||
public TransitionDemoController(Bundle args) {
|
||||
super(args);
|
||||
transitionDemo = TransitionDemo.fromIndex(args.getInt(KEY_INDEX));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(transitionDemo.layoutId, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
View bgView = view.findViewById(R.id.bg_view);
|
||||
if (transitionDemo.colorId != 0 && bgView != null) {
|
||||
bgView.setBackgroundColor(ContextCompat.getColor(getActivity(), transitionDemo.colorId));
|
||||
}
|
||||
|
||||
final int nextIndex = transitionDemo.ordinal() + 1;
|
||||
int buttonColor = 0;
|
||||
if (nextIndex < TransitionDemo.values().length) {
|
||||
buttonColor = TransitionDemo.fromIndex(nextIndex).colorId;
|
||||
}
|
||||
if (buttonColor == 0) {
|
||||
buttonColor = TransitionDemo.fromIndex(0).colorId;
|
||||
}
|
||||
|
||||
btnNext.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(getActivity(), buttonColor)));
|
||||
tvTitle.setText(transitionDemo.title);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "Transition Demos";
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_next) void onNextClicked() {
|
||||
final int nextIndex = transitionDemo.ordinal() + 1;
|
||||
|
||||
if (nextIndex < TransitionDemo.values().length) {
|
||||
getRouter().pushController(getRouterTransaction(nextIndex, this));
|
||||
} else {
|
||||
getRouter().popToRoot();
|
||||
}
|
||||
}
|
||||
|
||||
public ControllerChangeHandler getChangeHandler(Controller from) {
|
||||
switch (transitionDemo) {
|
||||
case VERTICAL:
|
||||
return new VerticalChangeHandler();
|
||||
case CIRCULAR:
|
||||
TransitionDemoController demoController = (TransitionDemoController) from;
|
||||
return new CircularRevealChangeHandlerCompat(demoController.btnNext, demoController.containerView);
|
||||
case FADE:
|
||||
return new FadeChangeHandler();
|
||||
case FLIP:
|
||||
return new FlipChangeHandler();
|
||||
case ARC_FADE:
|
||||
return new ArcFadeMoveChangeHandler(from.getResources().getString(R.string.transition_tag_dot), from.getResources().getString(R.string.transition_tag_title));
|
||||
case ARC_FADE_RESET:
|
||||
return new ArcFadeMoveChangeHandler(from.getResources().getString(R.string.transition_tag_dot), from.getResources().getString(R.string.transition_tag_title));
|
||||
case HORIZONTAL:
|
||||
return new HorizontalChangeHandler();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static RouterTransaction getRouterTransaction(int index, Controller fromController) {
|
||||
TransitionDemoController toController = new TransitionDemoController(index);
|
||||
|
||||
return RouterTransaction.with(toController)
|
||||
.pushChangeHandler(toController.getChangeHandler(fromController))
|
||||
.popChangeHandler(toController.getChangeHandler(fromController));
|
||||
}
|
||||
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DimenRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.changehandler.ArcFadeMoveChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.changehandler.CircularRevealChangeHandlerCompat
|
||||
import com.bluelinelabs.conductor.demo.changehandler.FlipChangeHandler
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerTransitionDemoBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
|
||||
class TransitionDemoController(args: Bundle) : BaseController(R.layout.controller_transition_demo, args) {
|
||||
private val binding: ControllerTransitionDemoBinding by viewBinding(ControllerTransitionDemoBinding::bind)
|
||||
|
||||
override val title = "Transition Demos"
|
||||
|
||||
private val demo = TransitionDemo.values()[args.getInt(KEY_INDEX)]
|
||||
|
||||
constructor(index: Int) : this(bundleOf(KEY_INDEX to index))
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
if (demo.layout == TransactionDemoLayout.SHARED) {
|
||||
binding.bgView.isGone = true
|
||||
}
|
||||
|
||||
binding.title.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin = view.resources.getDimension(demo.layout.topMargin).toInt() }
|
||||
binding.next.updateLayoutParams<FrameLayout.LayoutParams> { gravity = demo.layout.fabGravity }
|
||||
|
||||
if (demo.colorId != 0) {
|
||||
binding.bgView.setBackgroundColor(ContextCompat.getColor(activity!!, demo.colorId))
|
||||
}
|
||||
|
||||
val nextIndex = demo.ordinal + 1
|
||||
val buttonColor = if (nextIndex < TransitionDemo.values().size) {
|
||||
TransitionDemo.values()[nextIndex].colorId
|
||||
} else {
|
||||
R.color.blue_grey_300
|
||||
}
|
||||
|
||||
binding.next.backgroundTintList = ContextCompat.getColorStateList(view.context, buttonColor)
|
||||
binding.title.text = demo.title
|
||||
|
||||
binding.next.setOnClickListener {
|
||||
if (nextIndex < TransitionDemo.values().size) {
|
||||
router.pushController(getRouterTransaction(nextIndex, this))
|
||||
} else {
|
||||
router.popToRoot()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getChangeHandler(from: Controller): ControllerChangeHandler {
|
||||
return when (demo) {
|
||||
TransitionDemo.VERTICAL -> VerticalChangeHandler()
|
||||
TransitionDemo.CIRCULAR -> {
|
||||
val demoController = from as TransitionDemoController
|
||||
CircularRevealChangeHandlerCompat(demoController.binding.next, demoController.binding.transitionRoot)
|
||||
}
|
||||
TransitionDemo.FADE -> FadeChangeHandler()
|
||||
TransitionDemo.FLIP -> FlipChangeHandler()
|
||||
TransitionDemo.ARC_FADE -> ArcFadeMoveChangeHandler(
|
||||
from.resources!!.getString(R.string.transition_tag_dot), from.resources!!.getString(R.string.transition_tag_title)
|
||||
)
|
||||
TransitionDemo.ARC_FADE_RESET -> ArcFadeMoveChangeHandler(
|
||||
from.resources!!.getString(R.string.transition_tag_dot), from.resources!!.getString(R.string.transition_tag_title)
|
||||
)
|
||||
TransitionDemo.HORIZONTAL -> HorizontalChangeHandler()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_INDEX = "TransitionDemoController.index"
|
||||
|
||||
fun getRouterTransaction(index: Int, fromController: Controller): RouterTransaction {
|
||||
val toController = TransitionDemoController(index)
|
||||
return RouterTransaction.with(toController)
|
||||
.pushChangeHandler(toController.getChangeHandler(fromController))
|
||||
.popChangeHandler(toController.getChangeHandler(fromController))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class TransactionDemoLayout(@DimenRes val topMargin: Int, val fabGravity: Int) {
|
||||
STANDARD(R.dimen.transition_margin_top_standard, Gravity.BOTTOM or Gravity.END),
|
||||
SHARED(R.dimen.transition_margin_top_shared, Gravity.CENTER)
|
||||
}
|
||||
|
||||
enum class TransitionDemo(val title: String, val layout: TransactionDemoLayout, @ColorRes val colorId: Int) {
|
||||
VERTICAL(
|
||||
"Vertical Slide Animation",
|
||||
TransactionDemoLayout.STANDARD,
|
||||
R.color.blue_grey_300
|
||||
),
|
||||
CIRCULAR(
|
||||
"Circular Reveal Animation",
|
||||
TransactionDemoLayout.STANDARD,
|
||||
R.color.red_300
|
||||
),
|
||||
FADE("Fade Animation",
|
||||
TransactionDemoLayout.STANDARD,
|
||||
R.color.blue_300
|
||||
),
|
||||
FLIP(
|
||||
"Flip Animation",
|
||||
TransactionDemoLayout.STANDARD,
|
||||
R.color.deep_orange_300
|
||||
),
|
||||
HORIZONTAL(
|
||||
"Horizontal Slide Animation",
|
||||
TransactionDemoLayout.STANDARD,
|
||||
R.color.green_300
|
||||
),
|
||||
ARC_FADE(
|
||||
"Arc/Fade Shared Element Transition",
|
||||
TransactionDemoLayout.SHARED,
|
||||
R.color.blue_grey_300
|
||||
),
|
||||
ARC_FADE_RESET(
|
||||
"Arc/Fade Shared Element Transition",
|
||||
TransactionDemoLayout.STANDARD,
|
||||
R.color.pink_300
|
||||
)
|
||||
}
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
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 com.bluelinelabs.conductor.viewpager2.RouterStateAdapter;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class ViewPager2Controller 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};
|
||||
|
||||
@BindView(R.id.tab_layout) TabLayout tabLayout;
|
||||
@BindView(R.id.view_pager) ViewPager2 viewPager;
|
||||
|
||||
private final RouterStateAdapter pagerAdapter;
|
||||
|
||||
public ViewPager2Controller() {
|
||||
pagerAdapter = new RouterStateAdapter(this) {
|
||||
@Override
|
||||
public void configureRouter(@NonNull Router router, int position) {
|
||||
if (!router.hasRootController()) {
|
||||
Controller page = new ChildController(String.format(Locale.getDefault(), "Child #%d (Swipe to see more)", position), PAGE_COLORS[position], true);
|
||||
router.setRoot(RouterTransaction.with(page));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return PAGE_COLORS.length;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_view_pager2, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
viewPager.setAdapter(pagerAdapter);
|
||||
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> tab.setText("Page " + position)).attach();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroyView(@NonNull View view) {
|
||||
if (!getActivity().isChangingConfigurations()) {
|
||||
viewPager.setAdapter(null);
|
||||
}
|
||||
tabLayout.setupWithViewPager(null);
|
||||
super.onDestroyView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "ViewPager2 Demo";
|
||||
}
|
||||
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.view.View
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.Router
|
||||
import com.bluelinelabs.conductor.RouterTransaction.Companion.with
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerViewPager2Binding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
import com.bluelinelabs.conductor.viewpager2.RouterStateAdapter
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import java.util.*
|
||||
|
||||
class ViewPager2Controller : BaseController(R.layout.controller_view_pager2) {
|
||||
private val binding: ControllerViewPager2Binding by viewBinding(ControllerViewPager2Binding::bind)
|
||||
|
||||
override val title = "ViewPager2 Demo"
|
||||
|
||||
private val pageColors = intArrayOf(R.color.green_300, R.color.cyan_300, R.color.deep_purple_300, R.color.lime_300, R.color.red_300)
|
||||
|
||||
private lateinit var tabLayoutMediator: TabLayoutMediator
|
||||
|
||||
private val pagerAdapter = object : RouterStateAdapter(this) {
|
||||
override fun configureRouter(router: Router, position: Int) {
|
||||
if (!router.hasRootController()) {
|
||||
val page: Controller = ChildController(
|
||||
title = String.format(Locale.getDefault(), "Child #%d (Swipe to see more)", position),
|
||||
backgroundColor = pageColors[position],
|
||||
colorIsResId = true
|
||||
)
|
||||
router.setRoot(with(page))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = pageColors.size
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
binding.viewPager.adapter = pagerAdapter
|
||||
tabLayoutMediator = TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
|
||||
tab.text = "Page $position"
|
||||
}
|
||||
tabLayoutMediator.attach()
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
if (!activity!!.isChangingConfigurations) {
|
||||
binding.viewPager.adapter = null
|
||||
}
|
||||
tabLayoutMediator.detach()
|
||||
super.onDestroyView(view)
|
||||
}
|
||||
}
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
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 com.bluelinelabs.conductor.viewpager.RouterPagerAdapter;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class ViewPagerController 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};
|
||||
|
||||
@BindView(R.id.tab_layout) TabLayout tabLayout;
|
||||
@BindView(R.id.view_pager) ViewPager viewPager;
|
||||
|
||||
private final RouterPagerAdapter pagerAdapter;
|
||||
|
||||
public ViewPagerController() {
|
||||
pagerAdapter = new RouterPagerAdapter(this) {
|
||||
@Override
|
||||
public void configureRouter(@NonNull Router router, int position) {
|
||||
if (!router.hasRootController()) {
|
||||
Controller page = new ChildController(String.format(Locale.getDefault(), "Child #%d (Swipe to see more)", position), PAGE_COLORS[position], true);
|
||||
router.setRoot(RouterTransaction.with(page));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return PAGE_COLORS.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return "Page " + position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_view_pager, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
viewPager.setAdapter(pagerAdapter);
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroyView(@NonNull View view) {
|
||||
if (!getActivity().isChangingConfigurations()) {
|
||||
viewPager.setAdapter(null);
|
||||
}
|
||||
tabLayout.setupWithViewPager(null);
|
||||
super.onDestroyView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "ViewPager Demo";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers
|
||||
|
||||
import android.view.View
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.Router
|
||||
import com.bluelinelabs.conductor.RouterTransaction.Companion.with
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
import com.bluelinelabs.conductor.demo.controllers.base.BaseController
|
||||
import com.bluelinelabs.conductor.demo.databinding.ControllerViewPagerBinding
|
||||
import com.bluelinelabs.conductor.demo.util.viewBinding
|
||||
import com.bluelinelabs.conductor.viewpager.RouterPagerAdapter
|
||||
import java.util.*
|
||||
|
||||
class ViewPagerController : BaseController(R.layout.controller_view_pager) {
|
||||
private val binding: ControllerViewPagerBinding by viewBinding(ControllerViewPagerBinding::bind)
|
||||
|
||||
override val title = "ViewPager Demo"
|
||||
|
||||
private val pageColors = intArrayOf(R.color.green_300, R.color.cyan_300, R.color.deep_purple_300, R.color.lime_300, R.color.red_300)
|
||||
|
||||
private val pagerAdapter = object : RouterPagerAdapter(this) {
|
||||
override fun configureRouter(router: Router, position: Int) {
|
||||
if (!router.hasRootController()) {
|
||||
val page: Controller = ChildController(
|
||||
title = String.format(Locale.getDefault(), "Child #%d (Swipe to see more)", position),
|
||||
backgroundColor = pageColors[position],
|
||||
colorIsResId = true
|
||||
)
|
||||
router.setRoot(with(page))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCount() = pageColors.size
|
||||
|
||||
override fun getPageTitle(position: Int) = "Page $position"
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
binding.viewPager.adapter = pagerAdapter
|
||||
binding.tabLayout.setupWithViewPager(binding.viewPager)
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
if (!activity!!.isChangingConfigurations) {
|
||||
binding.viewPager.adapter = null
|
||||
}
|
||||
binding.tabLayout.setupWithViewPager(null)
|
||||
super.onDestroyView(view)
|
||||
}
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers.base;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import android.view.View;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
import com.bluelinelabs.conductor.demo.ActionBarProvider;
|
||||
|
||||
public abstract class BaseController extends RefWatchingController {
|
||||
|
||||
protected BaseController() { }
|
||||
|
||||
protected BaseController(Bundle args) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
// Note: This is just a quick demo of how an ActionBar *can* be accessed, not necessarily how it *should*
|
||||
// be accessed. In a production app, this would use Dagger instead.
|
||||
protected ActionBar getActionBar() {
|
||||
ActionBarProvider actionBarProvider = ((ActionBarProvider)getActivity());
|
||||
return actionBarProvider != null ? actionBarProvider.getSupportActionBar() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttach(@NonNull View view) {
|
||||
setTitle();
|
||||
super.onAttach(view);
|
||||
}
|
||||
|
||||
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) {
|
||||
actionBar.setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getTitle() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers.base
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.bluelinelabs.conductor.demo.ToolbarProvider
|
||||
|
||||
abstract class BaseController(
|
||||
@LayoutRes private val layoutRes: Int,
|
||||
args: Bundle? = null
|
||||
) : RefWatchingController(args) {
|
||||
|
||||
// Note: This is just a quick demo of how an ActionBar *can* be accessed, not necessarily how it *should*
|
||||
// be accessed. In a production app, this would use Dagger instead.
|
||||
protected val toolbar: Toolbar?
|
||||
get() = (activity as? ToolbarProvider)?.toolbar
|
||||
|
||||
protected open val title: String? = null
|
||||
|
||||
init {
|
||||
addLifecycleListener(object : LifecycleListener() {
|
||||
override fun postCreateView(controller: Controller, view: View) {
|
||||
onViewCreated(view)
|
||||
|
||||
toolbar?.let { configureToolbar(it) }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup,
|
||||
savedViewState: Bundle?
|
||||
): View {
|
||||
return inflater.inflate(layoutRes, container, false)
|
||||
}
|
||||
|
||||
open fun onViewCreated(view: View) = Unit
|
||||
|
||||
override fun onAttach(view: View) {
|
||||
toolbar?.let { configureToolbar(it) }
|
||||
super.onAttach(view)
|
||||
}
|
||||
|
||||
override fun onChangeStarted(
|
||||
changeHandler: ControllerChangeHandler,
|
||||
changeType: ControllerChangeType
|
||||
) {
|
||||
super.onChangeStarted(changeHandler, changeType)
|
||||
|
||||
if (changeType.isEnter) {
|
||||
toolbar?.let { configureMenu(it) }
|
||||
}
|
||||
}
|
||||
|
||||
open fun configureToolbar(toolbar: Toolbar) {
|
||||
val title = title ?: return
|
||||
|
||||
var parentController = parentController
|
||||
while (parentController != null) {
|
||||
if (parentController is BaseController && parentController.title != null) {
|
||||
return
|
||||
}
|
||||
parentController = parentController.parentController
|
||||
}
|
||||
|
||||
toolbar.title = title
|
||||
}
|
||||
|
||||
open fun configureMenu(toolbar: Toolbar) {
|
||||
toolbar.menu.clear()
|
||||
}
|
||||
|
||||
}
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers.base;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public abstract class ButterKnifeController extends Controller {
|
||||
|
||||
private Unbinder unbinder;
|
||||
|
||||
protected ButterKnifeController() { }
|
||||
protected ButterKnifeController(Bundle args) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
protected abstract View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container);
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container, @Nullable Bundle savedViewState) {
|
||||
View view = inflateView(inflater, container);
|
||||
unbinder = ButterKnife.bind(this, view);
|
||||
onViewBound(view);
|
||||
return view;
|
||||
}
|
||||
|
||||
protected void onViewBound(@NonNull View view) { }
|
||||
|
||||
@Override
|
||||
protected void onDestroyView(@NonNull View view) {
|
||||
super.onDestroyView(view);
|
||||
unbinder.unbind();
|
||||
unbinder = null;
|
||||
}
|
||||
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers.base;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler;
|
||||
import com.bluelinelabs.conductor.ControllerChangeType;
|
||||
import com.bluelinelabs.conductor.demo.DemoApplication;
|
||||
|
||||
public abstract class RefWatchingController extends ButterKnifeController {
|
||||
|
||||
protected RefWatchingController() { }
|
||||
protected RefWatchingController(Bundle args) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
private boolean hasExited;
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
if (hasExited) {
|
||||
DemoApplication.refWatcher.watch(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChangeEnded(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
super.onChangeEnded(changeHandler, changeType);
|
||||
|
||||
hasExited = !changeType.isEnter;
|
||||
if (isDestroyed()) {
|
||||
DemoApplication.refWatcher.watch(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.bluelinelabs.conductor.demo.controllers.base
|
||||
|
||||
import android.os.Bundle
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.bluelinelabs.conductor.demo.DemoApplication
|
||||
|
||||
abstract class RefWatchingController(args: Bundle?) : Controller(args) {
|
||||
|
||||
private var hasExited = false
|
||||
|
||||
public override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
if (hasExited) {
|
||||
DemoApplication.refWatcher.watch(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChangeEnded(
|
||||
changeHandler: ControllerChangeHandler,
|
||||
changeType: ControllerChangeType
|
||||
) {
|
||||
super.onChangeEnded(changeHandler, changeType)
|
||||
|
||||
hasExited = !changeType.isEnter
|
||||
if (isDestroyed) {
|
||||
DemoApplication.refWatcher.watch(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,20 +21,17 @@ import android.animation.TimeInterpolator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.FloatProperty;
|
||||
import android.util.IntProperty;
|
||||
import android.util.Property;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.interpolator.view.animation.FastOutLinearInInterpolator;
|
||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
|
||||
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator;
|
||||
import androidx.transition.Transition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Utility methods for working with animations.
|
||||
*/
|
||||
@@ -79,109 +76,6 @@ public class AnimUtils {
|
||||
return linear;
|
||||
}
|
||||
|
||||
/**
|
||||
* Linear interpolate between a and b with parameter t.
|
||||
*/
|
||||
public static float lerp(float a, float b, float t) {
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
|
||||
/**
|
||||
* A delegate for creating a {@link Property} of <code>int</code> type.
|
||||
*/
|
||||
public static abstract class IntProp<T> {
|
||||
|
||||
public final String name;
|
||||
|
||||
public IntProp(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public abstract void set(T object, int value);
|
||||
public abstract int get(T object);
|
||||
}
|
||||
|
||||
/**
|
||||
* The animation framework has an optimization for <code>Properties</code> of type
|
||||
* <code>int</code> but it was only made public in API24, so wrap the impl in our own type
|
||||
* and conditionally create the appropriate type, delegating the implementation.
|
||||
*/
|
||||
public static <T> Property<T, Integer> createIntProperty(final IntProp<T> impl) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
return new IntProperty<T>(impl.name) {
|
||||
@Override
|
||||
public Integer get(T object) {
|
||||
return impl.get(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(T object, int value) {
|
||||
impl.set(object, value);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return new Property<T, Integer>(Integer.class, impl.name) {
|
||||
@Override
|
||||
public Integer get(T object) {
|
||||
return impl.get(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T object, Integer value) {
|
||||
impl.set(object, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A delegate for creating a {@link Property} of <code>float</code> type.
|
||||
*/
|
||||
public static abstract class FloatProp<T> {
|
||||
|
||||
public final String name;
|
||||
|
||||
protected FloatProp(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public abstract void set(T object, float value);
|
||||
public abstract float get(T object);
|
||||
}
|
||||
|
||||
/**
|
||||
* The animation framework has an optimization for <code>Properties</code> of type
|
||||
* <code>float</code> but it was only made public in API24, so wrap the impl in our own type
|
||||
* and conditionally create the appropriate type, delegating the implementation.
|
||||
*/
|
||||
public static <T> Property<T, Float> createFloatProperty(final FloatProp<T> impl) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
return new FloatProperty<T>(impl.name) {
|
||||
@Override
|
||||
public Float get(T object) {
|
||||
return impl.get(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(T object, float value) {
|
||||
impl.set(object, value);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return new Property<T, Float>(Float.class, impl.name) {
|
||||
@Override
|
||||
public Float get(T object) {
|
||||
return impl.get(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T object, Float value) {
|
||||
impl.set(object, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* https://halfthought.wordpress.com/2014/11/07/reveal-transition/
|
||||
* <p/>
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.util;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class BundleBuilder {
|
||||
|
||||
private final Bundle bundle;
|
||||
|
||||
public BundleBuilder(Bundle bundle) {
|
||||
this.bundle = bundle;
|
||||
}
|
||||
|
||||
public BundleBuilder putAll(Bundle bundle) {
|
||||
this.bundle.putAll(bundle);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putBoolean(String key, boolean value) {
|
||||
bundle.putBoolean(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putBooleanArray(String key, boolean[] value) {
|
||||
bundle.putBooleanArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putDouble(String key, double value) {
|
||||
bundle.putDouble(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putDoubleArray(String key, double[] value) {
|
||||
bundle.putDoubleArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putLong(String key, long value) {
|
||||
bundle.putLong(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putLongArray(String key, long[] value) {
|
||||
bundle.putLongArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putString(String key, String value) {
|
||||
bundle.putString(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putStringArray(String key, String[] value) {
|
||||
bundle.putStringArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putBundle(String key, Bundle value) {
|
||||
bundle.putBundle(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putByte(String key, byte value) {
|
||||
bundle.putByte(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putByteArray(String key, byte[] value) {
|
||||
bundle.putByteArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putChar(String key, char value) {
|
||||
bundle.putChar(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putCharArray(String key, char[] value) {
|
||||
bundle.putCharArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putCharSequence(String key, CharSequence value) {
|
||||
bundle.putCharSequence(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putCharSequenceArray(String key, CharSequence[] value) {
|
||||
bundle.putCharSequenceArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putCharSequenceArrayList(String key, ArrayList<CharSequence> value) {
|
||||
bundle.putCharSequenceArrayList(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putInt(String key, int value) {
|
||||
bundle.putInt(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putIntArray(String key, int[] value) {
|
||||
bundle.putIntArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putFloat(String key, float value) {
|
||||
bundle.putFloat(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putFloatArray(String key, float[] value) {
|
||||
bundle.putFloatArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putIntegerArrayList(String key, ArrayList<Integer> value) {
|
||||
bundle.putIntegerArrayList(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putParcelable(String key, Parcelable value) {
|
||||
bundle.putParcelable(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putParcelableArray(String key, Parcelable[] value) {
|
||||
bundle.putParcelableArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putParcelableArrayList(String key, ArrayList<? extends Parcelable> value) {
|
||||
bundle.putParcelableArrayList(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putSerializable(String key, Serializable value) {
|
||||
bundle.putSerializable(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putShort(String key, short value) {
|
||||
bundle.putShort(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putShortArray(String key, short[] value) {
|
||||
bundle.putShortArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putSparseParcelableArray(String key, SparseArray<? extends Parcelable> value) {
|
||||
bundle.putSparseParcelableArray(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BundleBuilder putStringArrayList(String key, ArrayList<String> value) {
|
||||
bundle.putStringArrayList(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Bundle build() {
|
||||
return bundle;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.bluelinelabs.conductor.demo.util;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
|
||||
import com.bluelinelabs.conductor.demo.R;
|
||||
|
||||
public class ColorUtil {
|
||||
|
||||
public static int getMaterialColor(Resources resources, int index) {
|
||||
TypedArray colors = resources.obtainTypedArray(R.array.mdcolor_300);
|
||||
|
||||
final int returnColor = colors.getColor(index % colors.length(), Color.BLACK);
|
||||
|
||||
colors.recycle();
|
||||
return returnColor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.bluelinelabs.conductor.demo.util
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.core.content.res.use
|
||||
import com.bluelinelabs.conductor.demo.R
|
||||
|
||||
@ColorInt
|
||||
fun Resources.getMaterialColor(index: Int): Int {
|
||||
return obtainTypedArray(R.array.mdcolor_300).use {
|
||||
it.getColor(index % it.length(), Color.BLACK)
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.bluelinelabs.conductor.demo.util
|
||||
|
||||
import android.view.View
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
fun <T : ViewBinding> Controller.viewBinding(bindingFactory: (View) -> T) =
|
||||
ControllerViewBindingDelegate(this, bindingFactory)
|
||||
|
||||
class ControllerViewBindingDelegate<T : ViewBinding>(
|
||||
controller: Controller,
|
||||
private val viewBinder: (View) -> T
|
||||
) : ReadOnlyProperty<Controller, T>, LifecycleObserver {
|
||||
|
||||
private var binding: T? = null
|
||||
|
||||
init {
|
||||
controller.addLifecycleListener(object : Controller.LifecycleListener() {
|
||||
override fun postDestroyView(controller: Controller) {
|
||||
binding = null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun getValue(thisRef: Controller, property: KProperty<*>): T {
|
||||
return binding ?: viewBinder(thisRef.view!!).also { binding = it }
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
|
||||
@@ -1,35 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/city_grid_root"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingStart="@dimen/activity_horizontal_margin"
|
||||
android:paddingEnd="@dimen/activity_horizontal_margin"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:orientation="vertical" >
|
||||
android:paddingEnd="@dimen/activity_horizontal_margin">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/img_dot"
|
||||
android:id="@+id/dot"
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="96dp"
|
||||
android:src="@drawable/circle"
|
||||
/>
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/circle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:id="@+id/title"
|
||||
style="@style/Base.TextAppearance.AppCompat.Large"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="40dp"
|
||||
/>
|
||||
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"
|
||||
/>
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
android:layout_gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:id="@+id/title"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:layout_marginTop="24dp"
|
||||
@@ -39,7 +39,7 @@
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_description"
|
||||
android:id="@+id/description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="24dp"
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginBottom="@dimen/padding_normal"
|
||||
android:layout_marginEnd="@dimen/padding_normal"
|
||||
android:layout_marginRight="@dimen/padding_normal"
|
||||
android:elevation="@dimen/z_fab"
|
||||
android:scaleType="matrix"
|
||||
android:stateListAnimator="@animator/raise"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
@@ -21,7 +21,7 @@
|
||||
android:background="@color/white">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_next_retain_view"
|
||||
android:id="@+id/next_retain_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
@@ -30,7 +30,7 @@
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_next_release_view"
|
||||
android:id="@+id/next_release_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
@@ -21,7 +21,7 @@
|
||||
android:background="@color/white">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_pop_to_root"
|
||||
android:id="@+id/popToRoot"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
@@ -30,7 +30,7 @@
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_up"
|
||||
android:id="@+id/goUp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
@@ -39,7 +39,7 @@
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_next"
|
||||
android:id="@+id/goToNext"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
android:background="@color/pink_300" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_selection"
|
||||
android:id="@+id/selection"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
@@ -20,6 +20,7 @@
|
||||
android:layout_height="@dimen/display_target_image_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_margin="@dimen/display_target_image_margin"
|
||||
android:importantForAccessibility="no"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
@@ -29,7 +30,7 @@
|
||||
android:background="@color/white">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_pick_title"
|
||||
android:id="@+id/pick_title_button"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
@@ -38,7 +39,7 @@
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_pick_image"
|
||||
android:id="@+id/pick_image_button"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_use_title"
|
||||
android:id="@+id/use_title_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/use_title"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/transition_root"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
@@ -14,26 +13,22 @@
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:layout_marginTop="96dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:transitionName="@string/transition_tag_title"
|
||||
tools:targetApi="lollipop"
|
||||
/>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/btn_next"
|
||||
android:id="@+id/next"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_margin="24dp"
|
||||
app:srcCompat="@drawable/ic_arrow_forward_white_36dp"
|
||||
app:elevation="0dp"
|
||||
app:pressedTranslationZ="0dp"
|
||||
android:transitionName="@string/transition_tag_dot"
|
||||
tools:targetApi="lollipop"
|
||||
/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/transition_root"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:transitionName="@string/transition_tag_title"
|
||||
tools:targetApi="lollipop"
|
||||
/>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/btn_next"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:srcCompat="@drawable/ic_arrow_forward_white_36dp"
|
||||
app:elevation="0dp"
|
||||
app:pressedTranslationZ="0dp"
|
||||
android:transitionName="@string/transition_tag_dot"
|
||||
tools:targetApi="lollipop"
|
||||
/>
|
||||
|
||||
</FrameLayout>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/text_view"
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/row_root"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:clipChildren="false"
|
||||
@@ -11,19 +9,18 @@
|
||||
android:padding="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/img_city"
|
||||
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/tv_title"
|
||||
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"
|
||||
/>
|
||||
android:layout_gravity="center_horizontal" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
android:paddingBottom="16dp" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_view"
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
@@ -15,7 +15,7 @@
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_view"
|
||||
android:id="@+id/textView"
|
||||
style="@style/Base.TextAppearance.AppCompat.Large"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?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"
|
||||
@@ -9,7 +8,7 @@
|
||||
android:padding="24dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:id="@+id/title"
|
||||
style="@style/Base.TextAppearance.AppCompat.Large"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?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"
|
||||
@@ -11,15 +10,15 @@
|
||||
android:padding="24dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/img_dot"
|
||||
android:id="@+id/dot"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:src="@drawable/circle"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:id="@+id/title"
|
||||
style="@style/Base.TextAppearance.AppCompat.Large"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
<dimen name="display_target_image_size">200dp</dimen>
|
||||
<dimen name="display_target_image_margin">24dp</dimen>
|
||||
|
||||
<!-- Transition demo controllers -->
|
||||
<dimen name="transition_margin_top_standard">96dp</dimen>
|
||||
<dimen name="transition_margin_top_shared">24dp</dimen>
|
||||
|
||||
<!-- Custom transition dimensions -->
|
||||
<dimen name="padding_normal">16dp</dimen>
|
||||
<dimen name="z_fab">6dp</dimen>
|
||||
|
||||
+4
-5
@@ -3,7 +3,6 @@ ext {
|
||||
compileSdkVersion = 28
|
||||
targetSdkVersion = 28
|
||||
|
||||
butterknifeVersion = '10.1.0'
|
||||
picassoVersion = '2.5.2'
|
||||
leakCanaryVersion = '1.5.4'
|
||||
rxJavaVersion = '1.3.8'
|
||||
@@ -13,7 +12,8 @@ ext {
|
||||
autodisposeVersion = '1.0.0'
|
||||
archComponentsVersion = '2.0.0'
|
||||
junitVersion = '4.12'
|
||||
mvnPublishVersion = '0.11.1'
|
||||
mvnPublishVersion = '0.13.0'
|
||||
dokkaVersion = '1.4.10.2'
|
||||
|
||||
agpVersion = "4.1.0"
|
||||
lintVersion = agpVersion.replaceFirst(~/\d*/) { version ->
|
||||
@@ -30,9 +30,7 @@ ext {
|
||||
androidxTransition = "androidx.transition:transition:1.3.1"
|
||||
androidxCollection = "androidx.collection:collection:1.1.0"
|
||||
androidxViewPager2 = "androidx.viewpager2:viewpager2:1.0.0"
|
||||
|
||||
butterknife = "com.jakewharton:butterknife:$butterknifeVersion"
|
||||
butterknifeCompiler = "com.jakewharton:butterknife-compiler:$butterknifeVersion"
|
||||
androidxCoreKtx = "androidx.core:core-ktx:1.3.2"
|
||||
|
||||
picasso = "com.squareup.picasso:picasso:$picassoVersion"
|
||||
|
||||
@@ -47,6 +45,7 @@ ext {
|
||||
|
||||
autodispose = "com.uber.autodispose:autodispose:$autodisposeVersion"
|
||||
autodisposeLifecycle = "com.uber.autodispose:autodispose-lifecycle:$autodisposeVersion"
|
||||
autodisposeKtx = "com.uber.autodispose:autodispose-ktx:$autodisposeVersion"
|
||||
|
||||
archComponentsLifecycle = "androidx.lifecycle:lifecycle-runtime:$archComponentsVersion"
|
||||
archComponentsLiveDataCore = "androidx.lifecycle:lifecycle-livedata-core:$archComponentsVersion"
|
||||
|
||||
Reference in New Issue
Block a user