Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 301f3f3db8 | |||
| de961bcd24 | |||
| bccb7ffdce | |||
| b82196ce8c | |||
| 1d733906c8 | |||
| 39305091b9 | |||
| 8cbd987c7c | |||
| 6b9b8ba992 | |||
| ef05b43b0d | |||
| 7e316fa7ef | |||
| f7f45ad493 | |||
| 62520744cb | |||
| 4a09e0083c | |||
| 74e9681a48 | |||
| 3ef18015ee | |||
| 163fc90fcd | |||
| a920505915 | |||
| 88427b0271 | |||
| 3b8954b993 | |||
| d9fd28fb2c | |||
| f2977d599d | |||
| ccc8dd626c | |||
| c9f0b413cb | |||
| 47f5197f90 | |||
| d0b4e5c119 | |||
| f036217eb0 | |||
| 29fcd3c834 | |||
| 92600e69b2 | |||
| 9f41ec0d8f | |||
| 56fb9e82e9 | |||
| 96c1ec0a25 | |||
| d90f4ab3a1 | |||
| 07a956be3a | |||
| ad68431834 | |||
| 98b1ff265f | |||
| 9464fae539 | |||
| db0061a416 | |||
| 8b2b1e0137 | |||
| 2ac7848bbb | |||
| 29bc51db6f | |||
| e2f78e8185 | |||
| 3eb0302046 | |||
| 933fdd2715 | |||
| 143b144cbf | |||
| eeb5d20b8c | |||
| fe79f30c25 | |||
| 0ee0df0bcc | |||
| f665c263ee | |||
| 835d6425be | |||
| 851535ab28 | |||
| e4bb13b025 | |||
| 4e0f36d57a | |||
| 752c22c0b9 |
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Konstantin Tskhovrebov (@terrakok)
|
||||
and Vasili Chyrvon (@Jeevuz)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -21,9 +21,12 @@ It was designed to be used with the MVP pattern (try [Moxy](https://github.com/A
|
||||
+ functionality is simple to extend
|
||||
+ suitable for Unit Testing
|
||||
|
||||
## Version 2.+
|
||||
+ easy screen result subscription
|
||||
+ predefined navigator ready for setup transition animation
|
||||
## Additional features
|
||||
+ opening several screens inside single call (for example: deeplink)
|
||||
+ implementation of parallel navigation (Instagram like)
|
||||
+ predefined navigator ready for Single-Activity apps
|
||||
+ predefined navigator ready for setup transition animation
|
||||
|
||||
**See the sample application**
|
||||
|
||||
## How to add
|
||||
@@ -64,7 +67,7 @@ public class SampleApplication extends MvpApplication {
|
||||
```
|
||||
|
||||
## How it works?
|
||||

|
||||
<img src="https://github.com/terrakok/Cicerone/raw/develop/media/CiceroneDiagram.png" alt="drawing" width="800"/>
|
||||
|
||||
Presenter calls navigation method of Router.
|
||||
|
||||
@@ -81,29 +84,29 @@ public class SamplePresenter extends Presenter<SampleView> {
|
||||
}
|
||||
|
||||
public void onForwardCommandClick() {
|
||||
router.navigateTo("Some screen");
|
||||
router.navigateTo(new SomeScreen());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Router converts the navigation call to the set of Commands and sends them to CommandBuffer.
|
||||
Router converts the navigation call to the set of Commands and sends them to CommandBuffer.
|
||||
|
||||
CommandBuffer checks whether there are _"active"_ Navigator:
|
||||
If yes, it passes the commands to the Navigator. Navigator will process them to achive the desired transition.
|
||||
If no, then CommandBuffer saves the commands in a queue, and will apply them as soon as new _"active"_ Navigator will appear.
|
||||
CommandBuffer checks whether there are _"active"_ Navigator:
|
||||
- If yes, it passes the commands to the Navigator. Navigator will process them to achive the desired transition.
|
||||
- If no, then CommandBuffer saves the commands in a queue, and will apply them as soon as new _"active"_ Navigator will appear.
|
||||
|
||||
```java
|
||||
protected void executeCommand(Command command) {
|
||||
if (navigator != null) {
|
||||
navigator.applyCommand(command);
|
||||
} else {
|
||||
pendingCommands.add(command);
|
||||
void executeCommands(Command[] commands) {
|
||||
if (navigator != null) {
|
||||
navigator.applyCommands(commands);
|
||||
} else {
|
||||
pendingCommands.add(commands);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Navigator processes the navigation commands. Usually it is an anonymous class inside the Activity.
|
||||
Activity provides Navigator to the CommandBuffer in _onResume_ and removes it in _onPause_.
|
||||
Navigator processes the navigation commands. Usually it is an anonymous class inside the Activity.
|
||||
Activity provides Navigator to the CommandBuffer in _onResume_ and removes it in _onPause_.
|
||||
|
||||
**Attention**: Use _onResumeFragments()_ with FragmentActivity ([more info](https://developer.android.com/reference/android/support/v4/app/FragmentActivity.html#onResume()))
|
||||
|
||||
@@ -122,62 +125,36 @@ protected void onPause() {
|
||||
|
||||
private Navigator navigator = new Navigator() {
|
||||
@Override
|
||||
public void applyCommand(Command command) {
|
||||
//implement commands logic
|
||||
public void applyCommands(Command[] commands) {
|
||||
//implement commands logic (apply command batch to navigation container)
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Navigation commands
|
||||
This commands set will fulfill the needs of the most applications. But if you need something special - just add it!
|
||||
+ Forward - Opens new screen
|
||||

|
||||
+ Back - Rolls back the last transition
|
||||

|
||||
+ BackTo - Rolls back to the needed screen in the screens chain
|
||||

|
||||
+ Replace - Replaces the current screen
|
||||

|
||||
+ SystemMessage - Shows system message (Alert, Toast, Snack, etc.)
|
||||

|
||||
+ Forward - Opens new screen
|
||||

|
||||
+ Back - Rolls back the last transition
|
||||

|
||||
+ BackTo - Rolls back to the needed screen in the screens chain
|
||||

|
||||
+ Replace - Replaces the current screen
|
||||

|
||||
|
||||
## Predefined navigators
|
||||
The library provides predefined navigators for _Fragments_ to use inside _Activity_.
|
||||
To use, just provide it with the container and _FragmentManager_ and override few simple methods.
|
||||
The library provides predefined navigators for _Fragments_ and _Activity_.
|
||||
To use, just provide it with the container and _FragmentManager_.
|
||||
```java
|
||||
private Navigator navigator = new SupportAppNavigator(this, R.id.container) {
|
||||
@Override
|
||||
protected Intent createActivityIntent(String screenKey, Object data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Fragment createFragment(String screenKey, Object data) {
|
||||
switch (screenKey) {
|
||||
case Screens.PROFILE_SCREEN:
|
||||
return new ProfileFragment();
|
||||
case Screens.SELECT_PHOTO_SCREEN:
|
||||
return SelectPhotoFragment.getNewInstance((int) data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupFragmentTransactionAnimation(
|
||||
Command command,
|
||||
Fragment currentFragment,
|
||||
Fragment nextFragment,
|
||||
FragmentTransaction fragmentTransaction) {
|
||||
//setup animation
|
||||
}
|
||||
};
|
||||
private Navigator navigator = new SupportAppNavigator(this, R.id.container);
|
||||
```
|
||||
## Sample
|
||||
To see how to add, initialize and use the library and predefined navigators check out the sample.
|
||||
Or look at [GitFox (Android GitLab client)](https://gitlab.com/terrakok/gitlab-client)
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
## Participants
|
||||
+ idea and code - Konstantin Tskhovrebov (@terrakok)
|
||||
@@ -185,7 +162,10 @@ To see how to add, initialize and use the library and predefined navigators chec
|
||||
|
||||
## License
|
||||
```
|
||||
The MIT License (MIT)
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Konstantin Tskhovrebov (@terrakok)
|
||||
and Vasili Chyrvon (@Jeevuz)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
# Cicerone
|
||||
|
||||
[](https://t.me/Cicerone_RUS)
|
||||
|
||||

|
||||
|
||||
Cicerone (_"чи-че-ро́-не"_ - устар. гид) - легкая библиотека для простой реализации навигации в андроид приложении.
|
||||
Разработана для использования в MVP архитектуре (попробуйте [Moxy](https://github.com/Arello-Mobile/Moxy)), но легко встраивается в любые решения.
|
||||
|
||||
## Основные преимущества
|
||||
+ не завязана на Fragment'ы
|
||||
+ не фреймворк
|
||||
+ короткие вызовы навигации (никаких билдеров)
|
||||
+ lifecycle-безопасна!
|
||||
+ простое расширение функционала
|
||||
+ приспособлена для Unit тестов
|
||||
|
||||
## Как подключить?
|
||||
Добавьте в build.gradle зависимость:
|
||||
```groovy
|
||||
dependencies {
|
||||
//Cicerone
|
||||
compile 'ru.terrakok.cicerone:cicerone:X.X.X'
|
||||
}
|
||||
```
|
||||
И инициализируйте библиотеку, например, так:
|
||||
```java
|
||||
public class SampleApplication extends MvpApplication {
|
||||
public static SampleApplication INSTANCE;
|
||||
private Cicerone<Router> cicerone;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
INSTANCE = this;
|
||||
|
||||
initCicerone();
|
||||
}
|
||||
|
||||
private void initCicerone() {
|
||||
cicerone = Cicerone.create();
|
||||
}
|
||||
|
||||
public NavigatorHolder getNavigatorHolder() {
|
||||
return cicerone.getNavigatorHolder();
|
||||
}
|
||||
|
||||
public Router getRouter() {
|
||||
return cicerone.getRouter();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Как это работает?
|
||||

|
||||
|
||||
Presenter вызывает у Router метод навигации.
|
||||
|
||||
```java
|
||||
public class SamplePresenter extends Presenter<SampleView> {
|
||||
private Router router;
|
||||
|
||||
public SamplePresenter() {
|
||||
router = SampleApplication.INSTANCE.getRouter();
|
||||
}
|
||||
|
||||
public void onBackCommandClick() {
|
||||
router.exit();
|
||||
}
|
||||
|
||||
public void onForwardCommandClick() {
|
||||
router.navigateTo("Some screen");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Router - класс, который реализует вызванный метод навигации набором Command и отправляет их в CommandBuffer.
|
||||
CommandBuffer проверяет есть ли _"активный"_ Navigator.
|
||||
Если да, то на нем вызываются необходимые команды для осуществления запрошенного перехода.
|
||||
Если нет, то команды добавляются в очередь, которая будет применена, как только появится _"активный"_ Navigator.
|
||||
|
||||
```java
|
||||
protected void executeCommand(Command command) {
|
||||
if (navigator != null) {
|
||||
navigator.applyCommand(command);
|
||||
} else {
|
||||
pendingCommands.add(command);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Navigator - (например) анонимный класс внутри Activity, который реализует команды навигации.
|
||||
Activity предоставляет свой Navigator для CommandBuffer в методе _onResume_ и очищает в _onPause_
|
||||
|
||||
**Внимание**: В FragmentActivity следует использовать _onResumeFragments()_. ([подробнее](https://developer.android.com/reference/android/support/v4/app/FragmentActivity.html#onResume()))
|
||||
|
||||
```java
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
SampleApplication.INSTANCE.getNavigatorHolder().setNavigator(navigator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
SampleApplication.INSTANCE.getNavigatorHolder().removeNavigator();
|
||||
}
|
||||
|
||||
private Navigator navigator = new Navigator() {
|
||||
@Override
|
||||
public void applyCommand(Command command) {
|
||||
//implements commands logic
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Навигатор не обязан быть в Activity. Он может быть и внутри Fragment'а, который переключает внутри себя View.
|
||||
|
||||
## Команды навигатора
|
||||
Для большинства задач предоставленных в библиотеке команд должно хватить, но их всегда можно дополнить собственными!
|
||||
+ Forward - переход на новый экран
|
||||

|
||||
+ Back - возврат на предыдущий экран
|
||||

|
||||
+ BackTo - возврат к конкретному экрану в цепочке, либо на корневой, если указанный экран не найден
|
||||

|
||||
+ Replace - замена текущего экрана на новый
|
||||

|
||||
+ SystemMessage - показ системного сообщения (Alert, Toast, Snack и тд)
|
||||

|
||||
|
||||
## Готовые навигаторы
|
||||
Библиотека предоставляет готовые навигаторы для _Activity_.
|
||||
Чтобы их использовать, достаточно указать контейнер и передать _FragmentManager_.
|
||||
```java
|
||||
private Navigator navigator = new SupportFragmentNavigator(
|
||||
getSupportFragmentManager(), R.id.main_container) {
|
||||
@Override
|
||||
protected Fragment createFragment(String screenKey, Object data) {
|
||||
return SampleFragment.getNewInstance((int) data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showSystemMessage(String message) {
|
||||
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exit() {
|
||||
finish();
|
||||
}
|
||||
};
|
||||
```
|
||||
## Sample
|
||||
Работу библиотеки, готовых навигаторов и другое можно посмотреть в _sample_ приложении.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Участники
|
||||
+ идея и реализация - Константин Цховребов (@terrakok)
|
||||
+ архитектурные советы, документация и публикация - Василий Чирвон (@Jeevuz)
|
||||
|
||||
## Лицензия
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -3,9 +3,10 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.3.0'
|
||||
classpath 'com.android.tools.build:gradle:3.3.0-alpha12'
|
||||
|
||||
// For the library uploading to the Bintray
|
||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.1'
|
||||
@@ -16,6 +17,7 @@ buildscript {
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Fri Mar 10 17:09:31 MSK 2017
|
||||
#Thu Sep 27 15:42:22 MSK 2018
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
|
||||
@@ -7,6 +7,7 @@ targetCompatibility = JavaVersion.VERSION_1_7
|
||||
|
||||
dependencies {
|
||||
compileOnly project(':stub-android')
|
||||
compileOnly 'com.google.android:android:4.1.1.4'
|
||||
}
|
||||
|
||||
ext {
|
||||
@@ -15,7 +16,7 @@ ext {
|
||||
bintrayName = 'cicerone'
|
||||
publishedGroupId = 'ru.terrakok.cicerone'
|
||||
artifact = 'cicerone'
|
||||
libraryVersion = '2.1.0'
|
||||
libraryVersion = '4.0.0'
|
||||
gitUrl = 'https://github.com/terrakok/Cicerone'
|
||||
allLicenses = ['MIT']
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
/*
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok)
|
||||
*/
|
||||
|
||||
package ru.terrakok.cicerone;
|
||||
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 12.10.16
|
||||
*/
|
||||
|
||||
/**
|
||||
* BaseRouter is an abstract class to implement high-level navigation.
|
||||
* Extend it to add needed transition methods.
|
||||
@@ -23,11 +22,11 @@ public abstract class BaseRouter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends navigation command to {@link CommandBuffer}.
|
||||
* Sends navigation command array to {@link CommandBuffer}.
|
||||
*
|
||||
* @param command navigation command to execute
|
||||
* @param commands navigation command array to execute
|
||||
*/
|
||||
protected void executeCommand(Command command) {
|
||||
commandBuffer.executeCommand(command);
|
||||
protected void executeCommands(Command... commands) {
|
||||
commandBuffer.executeCommands(commands);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package ru.terrakok.cicerone;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
/*
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok)
|
||||
*/
|
||||
|
||||
package ru.terrakok.cicerone;
|
||||
|
||||
/**
|
||||
* Cicerone is the holder for other library components.
|
||||
* To use it, instantiate it using one of the {@link #create()} methods.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok)
|
||||
*/
|
||||
|
||||
package ru.terrakok.cicerone;
|
||||
|
||||
import java.util.LinkedList;
|
||||
@@ -5,25 +9,20 @@ import java.util.Queue;
|
||||
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 12.10.16
|
||||
*/
|
||||
|
||||
/**
|
||||
* Passes navigation command to an active {@link Navigator}
|
||||
* or stores it in the pending commands queue to pass it later.
|
||||
*/
|
||||
class CommandBuffer implements NavigatorHolder {
|
||||
private Navigator navigator;
|
||||
private Queue<Command> pendingCommands = new LinkedList<>();
|
||||
private Queue<Command[]> pendingCommands = new LinkedList<>();
|
||||
|
||||
@Override
|
||||
public void setNavigator(Navigator navigator) {
|
||||
this.navigator = navigator;
|
||||
while (!pendingCommands.isEmpty()) {
|
||||
if (navigator != null) {
|
||||
executeCommand(pendingCommands.poll());
|
||||
executeCommands(pendingCommands.poll());
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
@@ -34,15 +33,15 @@ class CommandBuffer implements NavigatorHolder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes {@code command} to the {@link Navigator} if it available.
|
||||
* Passes {@code commands} to the {@link Navigator} if it available.
|
||||
* Else puts it to the pending commands queue to pass it later.
|
||||
* @param command navigation command
|
||||
* @param commands navigation command array
|
||||
*/
|
||||
public void executeCommand(Command command) {
|
||||
void executeCommands(Command[] commands) {
|
||||
if (navigator != null) {
|
||||
navigator.applyCommand(command);
|
||||
navigator.applyCommands(commands);
|
||||
} else {
|
||||
pendingCommands.add(command);
|
||||
pendingCommands.add(commands);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
/*
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok)
|
||||
*/
|
||||
|
||||
package ru.terrakok.cicerone;
|
||||
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
*/
|
||||
|
||||
/**
|
||||
* The low-level navigation interface.
|
||||
* Navigator is the one who actually performs any transition.
|
||||
@@ -16,7 +15,7 @@ public interface Navigator {
|
||||
/**
|
||||
* Performs transition described by the navigation command
|
||||
*
|
||||
* @param command the navigation command to apply
|
||||
* @param commands the navigation command array to apply per single transaction
|
||||
*/
|
||||
void applyCommand(Command command);
|
||||
void applyCommands(Command[] commands);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package ru.terrakok.cicerone;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
/*
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok)
|
||||
*/
|
||||
|
||||
package ru.terrakok.cicerone;
|
||||
|
||||
/**
|
||||
* Navigator holder interface.
|
||||
* Use it to connect a {@link Navigator} to the {@link Cicerone}.
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
package ru.terrakok.cicerone;
|
||||
/*
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok)
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
package ru.terrakok.cicerone;
|
||||
|
||||
import ru.terrakok.cicerone.commands.Back;
|
||||
import ru.terrakok.cicerone.commands.BackTo;
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
import ru.terrakok.cicerone.commands.Forward;
|
||||
import ru.terrakok.cicerone.commands.Replace;
|
||||
import ru.terrakok.cicerone.commands.SystemMessage;
|
||||
import ru.terrakok.cicerone.result.ResultListener;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 12.10.16
|
||||
*/
|
||||
|
||||
/**
|
||||
* Router is the class for high-level navigation.
|
||||
@@ -22,144 +18,77 @@ import ru.terrakok.cicerone.result.ResultListener;
|
||||
*/
|
||||
public class Router extends BaseRouter {
|
||||
|
||||
private HashMap<Integer, ResultListener> resultListeners = new HashMap<>();
|
||||
|
||||
public Router() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to the screen result.<br>
|
||||
* <b>Note:</b> only one listener can subscribe to a unique resultCode!<br>
|
||||
* You must call a <b>removeResultListener()</b> to avoid a memory leak.
|
||||
*
|
||||
* @param resultCode key for filter results
|
||||
* @param listener result listener
|
||||
*/
|
||||
public void setResultListener(Integer resultCode, ResultListener listener) {
|
||||
resultListeners.put(resultCode, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from the screen result.
|
||||
*
|
||||
* @param resultCode key for filter results
|
||||
*/
|
||||
public void removeResultListener(Integer resultCode) {
|
||||
resultListeners.remove(resultCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send result data to subscriber.
|
||||
*
|
||||
* @param resultCode result data key
|
||||
* @param result result data
|
||||
* @return TRUE if listener was notified and FALSE otherwise
|
||||
*/
|
||||
protected boolean sendResult(Integer resultCode, Object result) {
|
||||
ResultListener resultListener = resultListeners.get(resultCode);
|
||||
if (resultListener != null) {
|
||||
resultListener.onResult(result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open new screen and add it to the screens chain.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param screen screen
|
||||
*/
|
||||
public void navigateTo(String screenKey) {
|
||||
navigateTo(screenKey, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open new screen and add it to screens chain.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param data initialisation parameters for the new screen
|
||||
*/
|
||||
public void navigateTo(String screenKey, Object data) {
|
||||
executeCommand(new Forward(screenKey, data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the current screens chain and start new one
|
||||
* by opening a new screen right after the root.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
*/
|
||||
public void newScreenChain(String screenKey) {
|
||||
newScreenChain(screenKey, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the current screens chain and start new one
|
||||
* by opening a new screen right after the root.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param data initialisation parameters for the new screen
|
||||
*/
|
||||
public void newScreenChain(String screenKey, Object data) {
|
||||
executeCommand(new BackTo(null));
|
||||
executeCommand(new Forward(screenKey, data));
|
||||
public void navigateTo(Screen screen) {
|
||||
executeCommands(new Forward(screen));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all screens and open new one as root.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param screen screen
|
||||
*/
|
||||
public void newRootScreen(String screenKey) {
|
||||
newRootScreen(screenKey, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all screens and open new one as root.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param data initialisation parameters for the root
|
||||
*/
|
||||
public void newRootScreen(String screenKey, Object data) {
|
||||
executeCommand(new BackTo(null));
|
||||
executeCommand(new Replace(screenKey, data));
|
||||
public void newRootScreen(Screen screen) {
|
||||
executeCommands(
|
||||
new BackTo(null),
|
||||
new Replace(screen)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace current screen.
|
||||
* By replacing the screen, you alters the backstack,
|
||||
* so by going back you will return to the previous screen
|
||||
* so by going fragmentBack you will return to the previous screen
|
||||
* and not to the replaced one.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param screen screen
|
||||
*/
|
||||
public void replaceScreen(String screenKey) {
|
||||
replaceScreen(screenKey, null);
|
||||
public void replaceScreen(Screen screen) {
|
||||
executeCommands(new Replace(screen));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace current screen.
|
||||
* By replacing the screen, you alters the backstack,
|
||||
* so by going back you will return to the previous screen
|
||||
* and not to the replaced one.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param data initialisation parameters for the new screen
|
||||
*/
|
||||
public void replaceScreen(String screenKey, Object data) {
|
||||
executeCommand(new Replace(screenKey, data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return back to the needed screen from the chain.
|
||||
* Return fragmentBack to the needed screen from the chain.
|
||||
* Behavior in the case when no needed screens found depends on
|
||||
* the processing of the {@link BackTo} command in a {@link Navigator} implementation.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param screen screen
|
||||
*/
|
||||
public void backTo(String screenKey) {
|
||||
executeCommand(new BackTo(screenKey));
|
||||
public void backTo(Screen screen) {
|
||||
executeCommands(new BackTo(screen));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens several screens inside single transaction.
|
||||
* @param screens
|
||||
*/
|
||||
public void newChain(Screen... screens) {
|
||||
Command[] commands = new Command[screens.length];
|
||||
for (int i = 0; i < commands.length; i++) {
|
||||
commands[i] = new Forward(screens[i]);
|
||||
}
|
||||
executeCommands(commands);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear current stack and open several screens inside single transaction.
|
||||
* @param screens
|
||||
*/
|
||||
public void newRootChain(Screen... screens) {
|
||||
Command[] commands = new Command[screens.length + 1];
|
||||
commands[0] = new BackTo(null);
|
||||
for (int i = 0; i < commands.length; i++) {
|
||||
commands[i + 1] = new Forward(screens[i]);
|
||||
}
|
||||
executeCommands(commands);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,8 +96,10 @@ public class Router extends BaseRouter {
|
||||
* It's mostly used to finish the application or close a supplementary navigation chain.
|
||||
*/
|
||||
public void finishChain() {
|
||||
executeCommand(new BackTo(null));
|
||||
executeCommand(new Back());
|
||||
executeCommands(
|
||||
new BackTo(null),
|
||||
new Back()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,36 +108,7 @@ public class Router extends BaseRouter {
|
||||
* the processing of the {@link Back} command in a {@link Navigator} implementation.
|
||||
*/
|
||||
public void exit() {
|
||||
executeCommand(new Back());
|
||||
executeCommands(new Back());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return to the previous screen in the chain and send result data.
|
||||
*
|
||||
* @param resultCode result data key
|
||||
* @param result result data
|
||||
*/
|
||||
public void exitWithResult(Integer resultCode, Object result) {
|
||||
exit();
|
||||
sendResult(resultCode, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return to the previous screen in the chain and show system message.
|
||||
*
|
||||
* @param message message to show
|
||||
*/
|
||||
public void exitWithMessage(String message) {
|
||||
executeCommand(new Back());
|
||||
executeCommand(new SystemMessage(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show system message.
|
||||
*
|
||||
* @param message message to show
|
||||
*/
|
||||
public void showSystemMessage(String message) {
|
||||
executeCommand(new SystemMessage(message));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package ru.terrakok.cicerone;
|
||||
|
||||
/**
|
||||
* Screen is class for description application screen.
|
||||
*/
|
||||
public abstract class Screen {
|
||||
protected String screenKey = getClass().getCanonicalName();
|
||||
|
||||
public String getScreenKey() {
|
||||
return screenKey;
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package ru.terrakok.cicerone.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.FragmentManager;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import ru.terrakok.cicerone.commands.BackTo;
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
import ru.terrakok.cicerone.commands.Forward;
|
||||
import ru.terrakok.cicerone.commands.Replace;
|
||||
|
||||
/**
|
||||
* Extends {@link FragmentNavigator} to allow
|
||||
* open new or replace current activity.
|
||||
* <p>
|
||||
* This navigator DOESN'T provide full featured Activity navigation,
|
||||
* but can ease Activity start or replace from current navigator.
|
||||
* </p>
|
||||
*
|
||||
* @author Vasili Chyrvon (vasili.chyrvon@gmail.com)
|
||||
*/
|
||||
public abstract class AppNavigator extends FragmentNavigator {
|
||||
|
||||
private Activity activity;
|
||||
|
||||
public AppNavigator(Activity activity, int containerId) {
|
||||
super(activity.getFragmentManager(), containerId);
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
public AppNavigator(Activity activity, FragmentManager fragmentManager, int containerId) {
|
||||
super(fragmentManager, containerId);
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to create option for start activity
|
||||
*
|
||||
* @param command current navigation command. Will be only {@link Forward} or {@link Replace}
|
||||
* @param activityIntent activity intent
|
||||
* @return transition options
|
||||
*/
|
||||
protected Bundle createStartActivityOptions(Command command, Intent activityIntent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyCommand(Command command) {
|
||||
if (command instanceof Forward) {
|
||||
Forward forward = (Forward) command;
|
||||
Intent activityIntent = createActivityIntent(forward.getScreenKey(), forward.getTransitionData());
|
||||
|
||||
// Start activity
|
||||
if (activityIntent != null) {
|
||||
Bundle options = createStartActivityOptions(command, activityIntent);
|
||||
activity.startActivity(activityIntent, options);
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (command instanceof Replace) {
|
||||
Replace replace = (Replace) command;
|
||||
Intent activityIntent = createActivityIntent(replace.getScreenKey(), replace.getTransitionData());
|
||||
|
||||
// Replace activity
|
||||
if (activityIntent != null) {
|
||||
Bundle options = createStartActivityOptions(command, activityIntent);
|
||||
activity.startActivity(activityIntent, options);
|
||||
activity.finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Use default fragments navigation
|
||||
super.applyCommand(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Intent to start Activity for {@code screenKey}.
|
||||
* <p>
|
||||
* <b>Warning:</b> This method does not work with {@link BackTo} command.
|
||||
* </p>
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param data initialization data, can be null
|
||||
* @return intent to start Activity for the passed screen key
|
||||
*/
|
||||
protected abstract Intent createActivityIntent(String screenKey, Object data);
|
||||
|
||||
@Override
|
||||
protected void showSystemMessage(String message) {
|
||||
// Toast by default
|
||||
Toast.makeText(activity, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exit() {
|
||||
// Finish by default
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
package ru.terrakok.cicerone.android;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.app.FragmentTransaction;
|
||||
|
||||
import ru.terrakok.cicerone.Navigator;
|
||||
import ru.terrakok.cicerone.commands.Back;
|
||||
import ru.terrakok.cicerone.commands.BackTo;
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
import ru.terrakok.cicerone.commands.Forward;
|
||||
import ru.terrakok.cicerone.commands.Replace;
|
||||
import ru.terrakok.cicerone.commands.SystemMessage;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@link Navigator} implementation based on the fragments.
|
||||
* <p>
|
||||
* {@link BackTo} navigation command will return to the root if
|
||||
* needed screen isn't found in the screens chain.
|
||||
* To change this behavior override {@link #backToUnexisting()} method.
|
||||
* </p>
|
||||
* <p>
|
||||
* {@link Back} command will call {@link #exit()} method if current screen is the root.
|
||||
* </p>
|
||||
*/
|
||||
public abstract class FragmentNavigator implements Navigator {
|
||||
private FragmentManager fragmentManager;
|
||||
private int containerId;
|
||||
|
||||
/**
|
||||
* Creates FragmentNavigator.
|
||||
*
|
||||
* @param fragmentManager fragment manager
|
||||
* @param containerId id of the fragments container layout
|
||||
*/
|
||||
public FragmentNavigator(FragmentManager fragmentManager, int containerId) {
|
||||
this.fragmentManager = fragmentManager;
|
||||
this.containerId = containerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to setup custom fragment transaction animation.
|
||||
*
|
||||
* @param command current navigation command. Will be only {@link Forward} or {@link Replace}
|
||||
* @param currentFragment current fragment in container
|
||||
* (for {@link Replace} command it will be screen previous in new chain, NOT replaced screen)
|
||||
* @param nextFragment next screen fragment
|
||||
* @param fragmentTransaction fragment transaction
|
||||
*/
|
||||
protected void setupFragmentTransactionAnimation(Command command,
|
||||
Fragment currentFragment,
|
||||
Fragment nextFragment,
|
||||
FragmentTransaction fragmentTransaction) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyCommand(Command command) {
|
||||
if (command instanceof Forward) {
|
||||
Forward forward = (Forward) command;
|
||||
Fragment fragment = createFragment(forward.getScreenKey(), forward.getTransitionData());
|
||||
if (fragment == null) {
|
||||
unknownScreen(command);
|
||||
return;
|
||||
}
|
||||
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
setupFragmentTransactionAnimation(
|
||||
command,
|
||||
fragmentManager.findFragmentById(containerId),
|
||||
fragment,
|
||||
fragmentTransaction
|
||||
);
|
||||
|
||||
fragmentTransaction
|
||||
.replace(containerId, fragment)
|
||||
.addToBackStack(forward.getScreenKey())
|
||||
.commit();
|
||||
} else if (command instanceof Back) {
|
||||
if (fragmentManager.getBackStackEntryCount() > 0) {
|
||||
fragmentManager.popBackStackImmediate();
|
||||
} else {
|
||||
exit();
|
||||
}
|
||||
} else if (command instanceof Replace) {
|
||||
Replace replace = (Replace) command;
|
||||
Fragment fragment = createFragment(replace.getScreenKey(), replace.getTransitionData());
|
||||
if (fragment == null) {
|
||||
unknownScreen(command);
|
||||
return;
|
||||
}
|
||||
if (fragmentManager.getBackStackEntryCount() > 0) {
|
||||
fragmentManager.popBackStackImmediate();
|
||||
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
setupFragmentTransactionAnimation(
|
||||
command,
|
||||
fragmentManager.findFragmentById(containerId),
|
||||
fragment,
|
||||
fragmentTransaction
|
||||
);
|
||||
|
||||
fragmentTransaction
|
||||
.replace(containerId, fragment)
|
||||
.addToBackStack(replace.getScreenKey())
|
||||
.commit();
|
||||
} else {
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
setupFragmentTransactionAnimation(
|
||||
command,
|
||||
fragmentManager.findFragmentById(containerId),
|
||||
fragment,
|
||||
fragmentTransaction
|
||||
);
|
||||
|
||||
fragmentTransaction
|
||||
.replace(containerId, fragment)
|
||||
.commit();
|
||||
}
|
||||
} else if (command instanceof BackTo) {
|
||||
String key = ((BackTo) command).getScreenKey();
|
||||
|
||||
if (key == null) {
|
||||
backToRoot();
|
||||
} else {
|
||||
boolean hasScreen = false;
|
||||
for (int i = 0; i < fragmentManager.getBackStackEntryCount(); i++) {
|
||||
if (key.equals(fragmentManager.getBackStackEntryAt(i).getName())) {
|
||||
fragmentManager.popBackStackImmediate(key, 0);
|
||||
hasScreen = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasScreen) {
|
||||
backToUnexisting();
|
||||
}
|
||||
}
|
||||
} else if (command instanceof SystemMessage) {
|
||||
showSystemMessage(((SystemMessage) command).getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void backToRoot() {
|
||||
fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Fragment matching {@code screenKey}.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param data initialization data
|
||||
* @return instantiated fragment for the passed screen key
|
||||
*/
|
||||
protected abstract Fragment createFragment(String screenKey, Object data);
|
||||
|
||||
/**
|
||||
* Shows system message.
|
||||
*
|
||||
* @param message message to show
|
||||
*/
|
||||
protected abstract void showSystemMessage(String message);
|
||||
|
||||
/**
|
||||
* Called when we try to back from the root.
|
||||
*/
|
||||
protected abstract void exit();
|
||||
|
||||
/**
|
||||
* Called when we tried to back to some specific screen, but didn't found it.
|
||||
*/
|
||||
protected void backToUnexisting() {
|
||||
backToRoot();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called if we can't create a screen.
|
||||
*/
|
||||
protected void unknownScreen(Command command) {
|
||||
throw new RuntimeException("Can't create a screen for passed screenKey.");
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
package ru.terrakok.cicerone.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import ru.terrakok.cicerone.commands.BackTo;
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
import ru.terrakok.cicerone.commands.Forward;
|
||||
import ru.terrakok.cicerone.commands.Replace;
|
||||
|
||||
/**
|
||||
* Extends {@link SupportFragmentNavigator} to allow
|
||||
* open new or replace current activity.
|
||||
* <p>
|
||||
* This navigator DOESN'T provide full featured Activity navigation,
|
||||
* but can ease Activity start or replace from current navigator.
|
||||
* </p>
|
||||
*
|
||||
* @author Vasili Chyrvon (vasili.chyrvon@gmail.com)
|
||||
*/
|
||||
public abstract class SupportAppNavigator extends SupportFragmentNavigator {
|
||||
|
||||
private Activity activity;
|
||||
|
||||
public SupportAppNavigator(FragmentActivity activity, int containerId) {
|
||||
super(activity.getSupportFragmentManager(), containerId);
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
public SupportAppNavigator(FragmentActivity activity, FragmentManager fragmentManager, int containerId) {
|
||||
super(fragmentManager, containerId);
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to create option for start activity
|
||||
*
|
||||
* @param command current navigation command. Will be only {@link Forward} or {@link Replace}
|
||||
* @param activityIntent activity intent
|
||||
* @return transition options
|
||||
*/
|
||||
protected Bundle createStartActivityOptions(Command command, Intent activityIntent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyCommand(Command command) {
|
||||
if (command instanceof Forward) {
|
||||
Forward forward = (Forward) command;
|
||||
Intent activityIntent = createActivityIntent(forward.getScreenKey(), forward.getTransitionData());
|
||||
|
||||
// Start activity
|
||||
if (activityIntent != null) {
|
||||
Bundle options = createStartActivityOptions(command, activityIntent);
|
||||
activity.startActivity(activityIntent, options);
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (command instanceof Replace) {
|
||||
Replace replace = (Replace) command;
|
||||
Intent activityIntent = createActivityIntent(replace.getScreenKey(), replace.getTransitionData());
|
||||
|
||||
// Replace activity
|
||||
if (activityIntent != null) {
|
||||
Bundle options = createStartActivityOptions(command, activityIntent);
|
||||
activity.startActivity(activityIntent, options);
|
||||
activity.finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Use default fragments navigation
|
||||
super.applyCommand(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Intent to start Activity for {@code screenKey}.
|
||||
* <p>
|
||||
* <b>Warning:</b> This method does not work with {@link BackTo} command.
|
||||
* </p>
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param data initialization data, can be null
|
||||
* @return intent to start Activity for the passed screen key
|
||||
*/
|
||||
protected abstract Intent createActivityIntent(String screenKey, Object data);
|
||||
|
||||
@Override
|
||||
protected void showSystemMessage(String message) {
|
||||
// Toast by default
|
||||
Toast.makeText(activity, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exit() {
|
||||
// Finish by default
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
package ru.terrakok.cicerone.android;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
|
||||
import ru.terrakok.cicerone.Navigator;
|
||||
import ru.terrakok.cicerone.commands.Back;
|
||||
import ru.terrakok.cicerone.commands.BackTo;
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
import ru.terrakok.cicerone.commands.Forward;
|
||||
import ru.terrakok.cicerone.commands.Replace;
|
||||
import ru.terrakok.cicerone.commands.SystemMessage;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@link Navigator} implementation based on the support fragments.
|
||||
* <p>
|
||||
* {@link BackTo} navigation command will return to the root if
|
||||
* needed screen isn't found in the screens chain.
|
||||
* To change this behavior override {@link #backToUnexisting()} method.
|
||||
* </p>
|
||||
* <p>
|
||||
* {@link Back} command will call {@link #exit()} method if current screen is the root.
|
||||
* </p>
|
||||
*/
|
||||
public abstract class SupportFragmentNavigator implements Navigator {
|
||||
private FragmentManager fragmentManager;
|
||||
private int containerId;
|
||||
|
||||
/**
|
||||
* Creates SupportFragmentNavigator.
|
||||
*
|
||||
* @param fragmentManager support fragment manager
|
||||
* @param containerId id of the fragments container layout
|
||||
*/
|
||||
public SupportFragmentNavigator(FragmentManager fragmentManager, int containerId) {
|
||||
this.fragmentManager = fragmentManager;
|
||||
this.containerId = containerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to setup custom fragment transaction animation.
|
||||
*
|
||||
* @param command current navigation command. Will be only {@link Forward} or {@link Replace}
|
||||
* @param currentFragment current fragment in container
|
||||
* (for {@link Replace} command it will be screen previous in new chain, NOT replaced screen)
|
||||
* @param nextFragment next screen fragment
|
||||
* @param fragmentTransaction fragment transaction
|
||||
*/
|
||||
protected void setupFragmentTransactionAnimation(Command command,
|
||||
Fragment currentFragment,
|
||||
Fragment nextFragment,
|
||||
FragmentTransaction fragmentTransaction) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyCommand(Command command) {
|
||||
if (command instanceof Forward) {
|
||||
Forward forward = (Forward) command;
|
||||
Fragment fragment = createFragment(forward.getScreenKey(), forward.getTransitionData());
|
||||
if (fragment == null) {
|
||||
unknownScreen(command);
|
||||
return;
|
||||
}
|
||||
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
setupFragmentTransactionAnimation(
|
||||
command,
|
||||
fragmentManager.findFragmentById(containerId),
|
||||
fragment,
|
||||
fragmentTransaction
|
||||
);
|
||||
|
||||
fragmentTransaction
|
||||
.replace(containerId, fragment)
|
||||
.addToBackStack(forward.getScreenKey())
|
||||
.commit();
|
||||
} else if (command instanceof Back) {
|
||||
if (fragmentManager.getBackStackEntryCount() > 0) {
|
||||
fragmentManager.popBackStackImmediate();
|
||||
} else {
|
||||
exit();
|
||||
}
|
||||
} else if (command instanceof Replace) {
|
||||
Replace replace = (Replace) command;
|
||||
Fragment fragment = createFragment(replace.getScreenKey(), replace.getTransitionData());
|
||||
if (fragment == null) {
|
||||
unknownScreen(command);
|
||||
return;
|
||||
}
|
||||
if (fragmentManager.getBackStackEntryCount() > 0) {
|
||||
fragmentManager.popBackStackImmediate();
|
||||
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
setupFragmentTransactionAnimation(
|
||||
command,
|
||||
fragmentManager.findFragmentById(containerId),
|
||||
fragment,
|
||||
fragmentTransaction
|
||||
);
|
||||
|
||||
fragmentTransaction
|
||||
.replace(containerId, fragment)
|
||||
.addToBackStack(replace.getScreenKey())
|
||||
.commit();
|
||||
} else {
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
setupFragmentTransactionAnimation(
|
||||
command,
|
||||
fragmentManager.findFragmentById(containerId),
|
||||
fragment,
|
||||
fragmentTransaction
|
||||
);
|
||||
|
||||
fragmentTransaction
|
||||
.replace(containerId, fragment)
|
||||
.commit();
|
||||
}
|
||||
} else if (command instanceof BackTo) {
|
||||
String key = ((BackTo) command).getScreenKey();
|
||||
|
||||
if (key == null) {
|
||||
backToRoot();
|
||||
} else {
|
||||
boolean hasScreen = false;
|
||||
for (int i = 0; i < fragmentManager.getBackStackEntryCount(); i++) {
|
||||
if (key.equals(fragmentManager.getBackStackEntryAt(i).getName())) {
|
||||
fragmentManager.popBackStackImmediate(key, 0);
|
||||
hasScreen = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasScreen) {
|
||||
backToUnexisting();
|
||||
}
|
||||
}
|
||||
} else if (command instanceof SystemMessage) {
|
||||
showSystemMessage(((SystemMessage) command).getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void backToRoot() {
|
||||
fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Fragment matching {@code screenKey}.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param data initialization data
|
||||
* @return instantiated fragment for the passed screen key
|
||||
*/
|
||||
protected abstract Fragment createFragment(String screenKey, Object data);
|
||||
|
||||
/**
|
||||
* Shows system message.
|
||||
*
|
||||
* @param message message to show
|
||||
*/
|
||||
protected abstract void showSystemMessage(String message);
|
||||
|
||||
/**
|
||||
* Called when we try to back from the root.
|
||||
*/
|
||||
protected abstract void exit();
|
||||
|
||||
/**
|
||||
* Called when we tried to back to some specific screen, but didn't found it.
|
||||
*/
|
||||
protected void backToUnexisting() {
|
||||
backToRoot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called if we can't create a screen.
|
||||
*/
|
||||
protected void unknownScreen(Command command) {
|
||||
throw new RuntimeException("Can't create a screen for passed screenKey.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
package ru.terrakok.cicerone.android.pure;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import ru.terrakok.cicerone.Navigator;
|
||||
import ru.terrakok.cicerone.commands.Back;
|
||||
import ru.terrakok.cicerone.commands.BackTo;
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
import ru.terrakok.cicerone.commands.Forward;
|
||||
import ru.terrakok.cicerone.commands.Replace;
|
||||
|
||||
/**
|
||||
* Navigator implementation for launch fragments and activities.<br>
|
||||
* Feature {@link BackTo} works only for fragments.<br>
|
||||
* Recommendation: most useful for Single-Activity application.
|
||||
*/
|
||||
public class AppNavigator implements Navigator {
|
||||
|
||||
private final Activity activity;
|
||||
private final FragmentManager fragmentManager;
|
||||
private final int containerId;
|
||||
private LinkedList<String> localStackCopy;
|
||||
|
||||
public AppNavigator(Activity activity, int containerId) {
|
||||
this(activity, activity.getFragmentManager(), containerId);
|
||||
}
|
||||
|
||||
public AppNavigator(Activity activity, FragmentManager fragmentManager, int containerId) {
|
||||
this.activity = activity;
|
||||
this.fragmentManager = fragmentManager;
|
||||
this.containerId = containerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyCommands(Command[] commands) {
|
||||
fragmentManager.executePendingTransactions();
|
||||
|
||||
//copy stack before apply commands
|
||||
copyStackToLocal();
|
||||
|
||||
for (Command command : commands) {
|
||||
applyCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyStackToLocal() {
|
||||
localStackCopy = new LinkedList<>();
|
||||
|
||||
final int stackSize = fragmentManager.getBackStackEntryCount();
|
||||
for (int i = 0; i < stackSize; i++) {
|
||||
localStackCopy.add(fragmentManager.getBackStackEntryAt(i).getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform transition described by the navigation command
|
||||
*
|
||||
* @param command the navigation command to apply
|
||||
*/
|
||||
protected void applyCommand(Command command) {
|
||||
if (command instanceof Forward) {
|
||||
activityForward((Forward) command);
|
||||
} else if (command instanceof Replace) {
|
||||
activityReplace((Replace) command);
|
||||
} else if (command instanceof BackTo) {
|
||||
backTo((BackTo) command);
|
||||
} else if (command instanceof Back) {
|
||||
fragmentBack();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void activityForward(Forward command) {
|
||||
AppScreen screen = (AppScreen) command.getScreen();
|
||||
Intent activityIntent = screen.getActivityIntent(activity);
|
||||
|
||||
// Start activity
|
||||
if (activityIntent != null) {
|
||||
Bundle options = createStartActivityOptions(command, activityIntent);
|
||||
checkAndStartActivity(screen, activityIntent, options);
|
||||
} else {
|
||||
fragmentForward(command);
|
||||
}
|
||||
}
|
||||
|
||||
protected void fragmentForward(Forward command) {
|
||||
AppScreen screen = (AppScreen) command.getScreen();
|
||||
Fragment fragment = createFragment(screen);
|
||||
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
|
||||
setupFragmentTransaction(
|
||||
command,
|
||||
fragmentManager.findFragmentById(containerId),
|
||||
fragment,
|
||||
fragmentTransaction
|
||||
);
|
||||
|
||||
fragmentTransaction
|
||||
.replace(containerId, fragment)
|
||||
.addToBackStack(screen.getScreenKey())
|
||||
.commit();
|
||||
localStackCopy.add(screen.getScreenKey());
|
||||
}
|
||||
|
||||
protected void fragmentBack() {
|
||||
if (localStackCopy.size() > 0) {
|
||||
fragmentManager.popBackStack();
|
||||
localStackCopy.removeLast();
|
||||
} else {
|
||||
activityBack();
|
||||
}
|
||||
}
|
||||
|
||||
protected void activityBack() {
|
||||
activity.finish();
|
||||
}
|
||||
|
||||
protected void activityReplace(Replace command) {
|
||||
AppScreen screen = (AppScreen) command.getScreen();
|
||||
Intent activityIntent = screen.getActivityIntent(activity);
|
||||
|
||||
// Replace activity
|
||||
if (activityIntent != null) {
|
||||
Bundle options = createStartActivityOptions(command, activityIntent);
|
||||
checkAndStartActivity(screen, activityIntent, options);
|
||||
activity.finish();
|
||||
} else {
|
||||
fragmentReplace(command);
|
||||
}
|
||||
}
|
||||
|
||||
protected void fragmentReplace(Replace command) {
|
||||
AppScreen screen = (AppScreen) command.getScreen();
|
||||
Fragment fragment = createFragment(screen);
|
||||
|
||||
if (localStackCopy.size() > 0) {
|
||||
fragmentManager.popBackStack();
|
||||
localStackCopy.removeLast();
|
||||
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
|
||||
setupFragmentTransaction(
|
||||
command,
|
||||
fragmentManager.findFragmentById(containerId),
|
||||
fragment,
|
||||
fragmentTransaction
|
||||
);
|
||||
|
||||
fragmentTransaction
|
||||
.replace(containerId, fragment)
|
||||
.addToBackStack(screen.getScreenKey())
|
||||
.commit();
|
||||
localStackCopy.add(screen.getScreenKey());
|
||||
|
||||
} else {
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
|
||||
setupFragmentTransaction(
|
||||
command,
|
||||
fragmentManager.findFragmentById(containerId),
|
||||
fragment,
|
||||
fragmentTransaction
|
||||
);
|
||||
|
||||
fragmentTransaction
|
||||
.replace(containerId, fragment)
|
||||
.commit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs {@link BackTo} command transition
|
||||
*/
|
||||
protected void backTo(BackTo command) {
|
||||
if (command.getScreen() == null) {
|
||||
backToRoot();
|
||||
} else {
|
||||
String key = command.getScreen().getScreenKey();
|
||||
int index = localStackCopy.indexOf(key);
|
||||
int size = localStackCopy.size();
|
||||
|
||||
if (index != -1) {
|
||||
for (int i = 1; i < size - index; i++) {
|
||||
localStackCopy.removeLast();
|
||||
}
|
||||
fragmentManager.popBackStack(key, 0);
|
||||
} else {
|
||||
backToUnexisting((AppScreen) command.getScreen());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void backToRoot() {
|
||||
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
localStackCopy.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to setup fragment transaction {@link FragmentTransaction}.
|
||||
* For example: setCustomAnimations(...), addSharedElement(...) or setReorderingAllowed(...)
|
||||
*
|
||||
* @param command current navigation command. Will be only {@link Forward} or {@link Replace}
|
||||
* @param currentFragment current fragment in container
|
||||
* (for {@link Replace} command it will be screen previous in new chain, NOT replaced screen)
|
||||
* @param nextFragment next screen fragment
|
||||
* @param fragmentTransaction fragment transaction
|
||||
*/
|
||||
protected void setupFragmentTransaction(Command command,
|
||||
Fragment currentFragment,
|
||||
Fragment nextFragment,
|
||||
FragmentTransaction fragmentTransaction) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to create option for start activity
|
||||
*
|
||||
* @param command current navigation command. Will be only {@link Forward} or {@link Replace}
|
||||
* @param activityIntent activity intent
|
||||
* @return transition options
|
||||
*/
|
||||
protected Bundle createStartActivityOptions(Command command, Intent activityIntent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void checkAndStartActivity(AppScreen screen, Intent activityIntent, Bundle options) {
|
||||
// Check if we can start activity
|
||||
if (activityIntent.resolveActivity(activity.getPackageManager()) != null) {
|
||||
activity.startActivity(activityIntent, options);
|
||||
} else {
|
||||
unexistingActivity(screen, activityIntent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when there is no activity to open {@code screenKey}.
|
||||
*
|
||||
* @param screen screen
|
||||
* @param activityIntent intent passed to start Activity for the {@code screenKey}
|
||||
*/
|
||||
protected void unexistingActivity(AppScreen screen, Intent activityIntent) {
|
||||
// Do nothing by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Fragment matching {@code screenKey}.
|
||||
*
|
||||
* @param screen screen
|
||||
* @return instantiated fragment for the passed screen
|
||||
*/
|
||||
protected Fragment createFragment(AppScreen screen) {
|
||||
Fragment fragment = screen.getFragment();
|
||||
|
||||
if (fragment == null) {
|
||||
errorWhileCreatingScreen(screen);
|
||||
}
|
||||
return fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we tried to fragmentBack to some specific screen (via {@link BackTo} command),
|
||||
* but didn't found it.
|
||||
*
|
||||
* @param screen screen
|
||||
*/
|
||||
protected void backToUnexisting(AppScreen screen) {
|
||||
backToRoot();
|
||||
}
|
||||
|
||||
protected void errorWhileCreatingScreen(AppScreen screen) {
|
||||
throw new RuntimeException("Can't create a screen: " + screen.getScreenKey());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package ru.terrakok.cicerone.android.pure;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import ru.terrakok.cicerone.Screen;
|
||||
|
||||
/**
|
||||
* AppScreen is base class for description and creation application screen.<br>
|
||||
* NOTE: If you have described the creation of Intent then Activity will be started.<br>
|
||||
* Recommendation: Use Intents for launch external application.
|
||||
*/
|
||||
public abstract class AppScreen extends Screen {
|
||||
|
||||
public Fragment getFragment() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Intent getActivityIntent(Context context) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
package ru.terrakok.cicerone.android.support;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import ru.terrakok.cicerone.Navigator;
|
||||
import ru.terrakok.cicerone.commands.Back;
|
||||
import ru.terrakok.cicerone.commands.BackTo;
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
import ru.terrakok.cicerone.commands.Forward;
|
||||
import ru.terrakok.cicerone.commands.Replace;
|
||||
|
||||
/**
|
||||
* Navigator implementation for launch fragments and activities.<br>
|
||||
* Feature {@link BackTo} works only for fragments.<br>
|
||||
* Recommendation: most useful for Single-Activity application.
|
||||
*/
|
||||
public class SupportAppNavigator implements Navigator {
|
||||
|
||||
private final Activity activity;
|
||||
private final FragmentManager fragmentManager;
|
||||
private final int containerId;
|
||||
private LinkedList<String> localStackCopy;
|
||||
|
||||
public SupportAppNavigator(FragmentActivity activity, int containerId) {
|
||||
this(activity, activity.getSupportFragmentManager(), containerId);
|
||||
}
|
||||
|
||||
public SupportAppNavigator(FragmentActivity activity, FragmentManager fragmentManager, int containerId) {
|
||||
this.activity = activity;
|
||||
this.fragmentManager = fragmentManager;
|
||||
this.containerId = containerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyCommands(Command[] commands) {
|
||||
fragmentManager.executePendingTransactions();
|
||||
|
||||
//copy stack before apply commands
|
||||
copyStackToLocal();
|
||||
|
||||
for (Command command : commands) {
|
||||
applyCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyStackToLocal() {
|
||||
localStackCopy = new LinkedList<>();
|
||||
|
||||
final int stackSize = fragmentManager.getBackStackEntryCount();
|
||||
for (int i = 0; i < stackSize; i++) {
|
||||
localStackCopy.add(fragmentManager.getBackStackEntryAt(i).getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform transition described by the navigation command
|
||||
*
|
||||
* @param command the navigation command to apply
|
||||
*/
|
||||
protected void applyCommand(Command command) {
|
||||
if (command instanceof Forward) {
|
||||
activityForward((Forward) command);
|
||||
} else if (command instanceof Replace) {
|
||||
activityReplace((Replace) command);
|
||||
} else if (command instanceof BackTo) {
|
||||
backTo((BackTo) command);
|
||||
} else if (command instanceof Back) {
|
||||
fragmentBack();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void activityForward(Forward command) {
|
||||
SupportAppScreen screen = (SupportAppScreen) command.getScreen();
|
||||
Intent activityIntent = screen.getActivityIntent(activity);
|
||||
|
||||
// Start activity
|
||||
if (activityIntent != null) {
|
||||
Bundle options = createStartActivityOptions(command, activityIntent);
|
||||
checkAndStartActivity(screen, activityIntent, options);
|
||||
} else {
|
||||
fragmentForward(command);
|
||||
}
|
||||
}
|
||||
|
||||
protected void fragmentForward(Forward command) {
|
||||
SupportAppScreen screen = (SupportAppScreen) command.getScreen();
|
||||
Fragment fragment = createFragment(screen);
|
||||
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
|
||||
setupFragmentTransaction(
|
||||
command,
|
||||
fragmentManager.findFragmentById(containerId),
|
||||
fragment,
|
||||
fragmentTransaction
|
||||
);
|
||||
|
||||
fragmentTransaction
|
||||
.replace(containerId, fragment)
|
||||
.addToBackStack(screen.getScreenKey())
|
||||
.commit();
|
||||
localStackCopy.add(screen.getScreenKey());
|
||||
}
|
||||
|
||||
protected void fragmentBack() {
|
||||
if (localStackCopy.size() > 0) {
|
||||
fragmentManager.popBackStack();
|
||||
localStackCopy.removeLast();
|
||||
} else {
|
||||
activityBack();
|
||||
}
|
||||
}
|
||||
|
||||
protected void activityBack() {
|
||||
activity.finish();
|
||||
}
|
||||
|
||||
protected void activityReplace(Replace command) {
|
||||
SupportAppScreen screen = (SupportAppScreen) command.getScreen();
|
||||
Intent activityIntent = screen.getActivityIntent(activity);
|
||||
|
||||
// Replace activity
|
||||
if (activityIntent != null) {
|
||||
Bundle options = createStartActivityOptions(command, activityIntent);
|
||||
checkAndStartActivity(screen, activityIntent, options);
|
||||
activity.finish();
|
||||
} else {
|
||||
fragmentReplace(command);
|
||||
}
|
||||
}
|
||||
|
||||
protected void fragmentReplace(Replace command) {
|
||||
SupportAppScreen screen = (SupportAppScreen) command.getScreen();
|
||||
Fragment fragment = createFragment(screen);
|
||||
|
||||
if (localStackCopy.size() > 0) {
|
||||
fragmentManager.popBackStack();
|
||||
localStackCopy.removeLast();
|
||||
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
|
||||
setupFragmentTransaction(
|
||||
command,
|
||||
fragmentManager.findFragmentById(containerId),
|
||||
fragment,
|
||||
fragmentTransaction
|
||||
);
|
||||
|
||||
fragmentTransaction
|
||||
.replace(containerId, fragment)
|
||||
.addToBackStack(screen.getScreenKey())
|
||||
.commit();
|
||||
localStackCopy.add(screen.getScreenKey());
|
||||
|
||||
} else {
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
|
||||
setupFragmentTransaction(
|
||||
command,
|
||||
fragmentManager.findFragmentById(containerId),
|
||||
fragment,
|
||||
fragmentTransaction
|
||||
);
|
||||
|
||||
fragmentTransaction
|
||||
.replace(containerId, fragment)
|
||||
.commit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs {@link BackTo} command transition
|
||||
*/
|
||||
protected void backTo(BackTo command) {
|
||||
if (command.getScreen() == null) {
|
||||
backToRoot();
|
||||
} else {
|
||||
String key = command.getScreen().getScreenKey();
|
||||
int index = localStackCopy.indexOf(key);
|
||||
int size = localStackCopy.size();
|
||||
|
||||
if (index != -1) {
|
||||
for (int i = 1; i < size - index; i++) {
|
||||
localStackCopy.removeLast();
|
||||
}
|
||||
fragmentManager.popBackStack(key, 0);
|
||||
} else {
|
||||
backToUnexisting((SupportAppScreen) command.getScreen());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void backToRoot() {
|
||||
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
localStackCopy.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to setup fragment transaction {@link FragmentTransaction}.
|
||||
* For example: setCustomAnimations(...), addSharedElement(...) or setReorderingAllowed(...)
|
||||
*
|
||||
* @param command current navigation command. Will be only {@link Forward} or {@link Replace}
|
||||
* @param currentFragment current fragment in container
|
||||
* (for {@link Replace} command it will be screen previous in new chain, NOT replaced screen)
|
||||
* @param nextFragment next screen fragment
|
||||
* @param fragmentTransaction fragment transaction
|
||||
*/
|
||||
protected void setupFragmentTransaction(Command command,
|
||||
Fragment currentFragment,
|
||||
Fragment nextFragment,
|
||||
FragmentTransaction fragmentTransaction) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to create option for start activity
|
||||
*
|
||||
* @param command current navigation command. Will be only {@link Forward} or {@link Replace}
|
||||
* @param activityIntent activity intent
|
||||
* @return transition options
|
||||
*/
|
||||
protected Bundle createStartActivityOptions(Command command, Intent activityIntent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void checkAndStartActivity(SupportAppScreen screen, Intent activityIntent, Bundle options) {
|
||||
// Check if we can start activity
|
||||
if (activityIntent.resolveActivity(activity.getPackageManager()) != null) {
|
||||
activity.startActivity(activityIntent, options);
|
||||
} else {
|
||||
unexistingActivity(screen, activityIntent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when there is no activity to open {@code screenKey}.
|
||||
*
|
||||
* @param screen screen
|
||||
* @param activityIntent intent passed to start Activity for the {@code screenKey}
|
||||
*/
|
||||
protected void unexistingActivity(SupportAppScreen screen, Intent activityIntent) {
|
||||
// Do nothing by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Fragment matching {@code screenKey}.
|
||||
*
|
||||
* @param screen screen
|
||||
* @return instantiated fragment for the passed screen
|
||||
*/
|
||||
protected Fragment createFragment(SupportAppScreen screen) {
|
||||
Fragment fragment = screen.getFragment();
|
||||
|
||||
if (fragment == null) {
|
||||
errorWhileCreatingScreen(screen);
|
||||
}
|
||||
return fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we tried to fragmentBack to some specific screen (via {@link BackTo} command),
|
||||
* but didn't found it.
|
||||
*
|
||||
* @param screen screen
|
||||
*/
|
||||
protected void backToUnexisting(SupportAppScreen screen) {
|
||||
backToRoot();
|
||||
}
|
||||
|
||||
protected void errorWhileCreatingScreen(SupportAppScreen screen) {
|
||||
throw new RuntimeException("Can't create a screen: " + screen.getScreenKey());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package ru.terrakok.cicerone.android.support;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import ru.terrakok.cicerone.Screen;
|
||||
|
||||
/**
|
||||
* AppScreen is base class for description and creation application screen.<br>
|
||||
* NOTE: If you have described the creation of Intent then Activity will be started.<br>
|
||||
* Recommendation: Use Intents for launch external application.
|
||||
*/
|
||||
public abstract class SupportAppScreen extends Screen {
|
||||
|
||||
public Fragment getFragment() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Intent getActivityIntent(Context context) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
/*
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok)
|
||||
*/
|
||||
|
||||
package ru.terrakok.cicerone.commands;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
*/
|
||||
|
||||
/**
|
||||
* Rolls back the last transition from the screens chain.
|
||||
* Rolls fragmentBack the last transition from the screens chain.
|
||||
*/
|
||||
public class Back implements Command {
|
||||
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
/*
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok)
|
||||
*/
|
||||
|
||||
package ru.terrakok.cicerone.commands;
|
||||
|
||||
import ru.terrakok.cicerone.Navigator;
|
||||
import ru.terrakok.cicerone.Screen;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
*/
|
||||
|
||||
/**
|
||||
* Rolls back to the needed screen from the screens chain.
|
||||
* Rolls fragmentBack to the needed screen from the screens chain.
|
||||
* Behavior in the case when no needed screens found depends on an implementation of the {@link Navigator}.
|
||||
* But the recommended behavior is to return to the root.
|
||||
*/
|
||||
public class BackTo implements Command {
|
||||
private String screenKey;
|
||||
private Screen screen;
|
||||
|
||||
/**
|
||||
* Creates a {@link BackTo} navigation command.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param screen screen
|
||||
*/
|
||||
public BackTo(String screenKey) {
|
||||
this.screenKey = screenKey;
|
||||
public BackTo(Screen screen) {
|
||||
this.screen = screen;
|
||||
}
|
||||
|
||||
public String getScreenKey() {
|
||||
return screenKey;
|
||||
public Screen getScreen() {
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package ru.terrakok.cicerone.commands;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
/*
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok)
|
||||
*/
|
||||
|
||||
package ru.terrakok.cicerone.commands;
|
||||
|
||||
/**
|
||||
* Navigation command describes screens transition.
|
||||
* that can be processed by {@link ru.terrakok.cicerone.Navigator}.
|
||||
|
||||
@@ -1,33 +1,27 @@
|
||||
/*
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok)
|
||||
*/
|
||||
|
||||
package ru.terrakok.cicerone.commands;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
*/
|
||||
import ru.terrakok.cicerone.Screen;
|
||||
|
||||
/**
|
||||
* Opens new screen.
|
||||
*/
|
||||
public class Forward implements Command {
|
||||
private String screenKey;
|
||||
private Object transitionData;
|
||||
private Screen screen;
|
||||
|
||||
/**
|
||||
* Creates a {@link Forward} navigation command.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param transitionData initial data
|
||||
* @param screen screen
|
||||
*/
|
||||
public Forward(String screenKey, Object transitionData) {
|
||||
this.screenKey = screenKey;
|
||||
this.transitionData = transitionData;
|
||||
public Forward(Screen screen) {
|
||||
this.screen = screen;
|
||||
}
|
||||
|
||||
public String getScreenKey() {
|
||||
return screenKey;
|
||||
}
|
||||
|
||||
public Object getTransitionData() {
|
||||
return transitionData;
|
||||
public Screen getScreen() {
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,27 @@
|
||||
/*
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok)
|
||||
*/
|
||||
|
||||
package ru.terrakok.cicerone.commands;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
*/
|
||||
import ru.terrakok.cicerone.Screen;
|
||||
|
||||
/**
|
||||
* Replaces the current screen.
|
||||
*/
|
||||
public class Replace implements Command {
|
||||
private String screenKey;
|
||||
private Object transitionData;
|
||||
private Screen screen;
|
||||
|
||||
/**
|
||||
* Creates a {@link Replace} navigation command.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param transitionData initial data
|
||||
* @param screen screen
|
||||
*/
|
||||
public Replace(String screenKey, Object transitionData) {
|
||||
this.screenKey = screenKey;
|
||||
this.transitionData = transitionData;
|
||||
public Replace(Screen screen) {
|
||||
this.screen = screen;
|
||||
}
|
||||
|
||||
public String getScreenKey() {
|
||||
return screenKey;
|
||||
}
|
||||
|
||||
public Object getTransitionData() {
|
||||
return transitionData;
|
||||
public Screen getScreen() {
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package ru.terrakok.cicerone.commands;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
*/
|
||||
|
||||
/**
|
||||
* Shows system message.
|
||||
*/
|
||||
public class SystemMessage implements Command {
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* Creates a {@link SystemMessage} command.
|
||||
*
|
||||
* @param message message text
|
||||
*/
|
||||
public SystemMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package ru.terrakok.cicerone.result;
|
||||
|
||||
/**
|
||||
* @author Konstantin Tskhovrebov (aka terrakok) on 04.07.17.
|
||||
*/
|
||||
|
||||
public interface ResultListener {
|
||||
|
||||
/**
|
||||
* Received result from screen.
|
||||
*
|
||||
* @param resultData
|
||||
*/
|
||||
void onResult(Object resultData);
|
||||
}
|
||||
@@ -2,3 +2,7 @@ apply plugin: 'java'
|
||||
|
||||
sourceCompatibility = JavaVersion.VERSION_1_7
|
||||
targetCompatibility = JavaVersion.VERSION_1_7
|
||||
|
||||
dependencies {
|
||||
compileOnly 'com.google.android:android:4.1.1.4'
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package android.app;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
/***
|
||||
* Created by laomo on 2016-11-21.
|
||||
*/
|
||||
public class Activity extends Context {
|
||||
public void startActivity(Intent intent) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public void startActivity(Intent intent, Bundle options) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public FragmentManager getFragmentManager() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public void finish() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package android.app;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
/***
|
||||
* Created by laomo on 2016-11-21.
|
||||
*/
|
||||
public class Fragment {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public void onStart() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public void onDestroyView() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
final public boolean isRemoving() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public final Activity getActivity() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package android.app;
|
||||
|
||||
/***
|
||||
* Created by laomo on 2016-11-21.
|
||||
*/
|
||||
public class FragmentManager {
|
||||
public static final int POP_BACK_STACK_INCLUSIVE = 1<<0;
|
||||
|
||||
public FragmentTransaction beginTransaction() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public boolean executePendingTransactions() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public void popBackStack() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public boolean popBackStackImmediate() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public boolean popBackStackImmediate(String name, int flags) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public int getBackStackEntryCount() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public BackStackEntry getBackStackEntryAt(int index) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public Fragment findFragmentById(int id) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public interface BackStackEntry {
|
||||
int getId();
|
||||
|
||||
String getName();
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package android.app;
|
||||
|
||||
/***
|
||||
* Created by laomo on 2016-11-21.
|
||||
*/
|
||||
public class FragmentTransaction {
|
||||
public FragmentTransaction replace(int containerViewId, Fragment fragment) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public FragmentTransaction addToBackStack(String name) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public int commit() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package android.content;
|
||||
|
||||
/**
|
||||
* @author Konstantin Tskhovrebov (aka terrakok). Date: 10.03.17
|
||||
*/
|
||||
|
||||
public class Context {
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package android.content;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 22.02.17
|
||||
*/
|
||||
|
||||
public class Intent {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package android.os;
|
||||
|
||||
/***
|
||||
* Created by laomo on 2016-11-21.
|
||||
*/
|
||||
public class Bundle {
|
||||
}
|
||||
@@ -20,11 +20,7 @@ public class FragmentManager {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public boolean popBackStackImmediate() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public boolean popBackStackImmediate(String name, int flags) {
|
||||
public void popBackStack(String name, int flags) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package android.widget;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* @author Konstantin Tskhovrebov (aka terrakok). Date: 10.03.17
|
||||
*/
|
||||
|
||||
public class Toast {
|
||||
|
||||
public static final int LENGTH_SHORT = 0;
|
||||
|
||||
public void show() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public static Toast makeText(Context context, CharSequence text, int duration) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 754 KiB |
@@ -0,0 +1 @@
|
||||
<mxfile userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:62.0) Gecko/20100101 Firefox/62.0" version="9.1.8" editor="www.draw.io" type="device"><diagram id="7e88c67f-9661-f316-02ff-f99b9ebf4599" name="Page-1">7Vpbc6M2FP41nu4+JMPFYPsxdpLtw26bNjvt7lNHBgHqYkSF8GV/fY9A4iZwnBon0zbxTEY+Erp859O54Ym92uw/MJRGn6iP44ll+PuJfTuxrNnChP9CcCgF07lTCkJG/FJk1oJH8h1LoSGlOfFx1hrIKY05SdtCjyYJ9nhLhhiju/awgMbtVVMUYk3w6KFYl/5OfB6VUsswjLrjR0zCiHd71sj7FjKaJ3LBiWUHxV/ZvUFqMjk+i5BPdw2RfTexV4xSXrY2+xWOBbYKt/K5+4HeauMMJ/yUByy3fGKL4hyrLRcb4weFhjhPKodhxvG+TwdorYYb+h7M6mTAGEw3mLMDDNm3tS7J4kiu7GrkFwreqAH61JZCJLUdVjPXB4aGPPPA+Z2nz1+oE4sHjIm93EWE48cUeaJ3B/QHWcQ3sMCtCc2MM/oNr2hMWfG0bRR/VY/ikxgbkDhujJREATlNeN8MgzpoYl1qVAf7ZeDsQdONYYWlT7bQDEXzgeEMtouZ6oNZG93n4d/B1Hfw3J/26WVurW3XlWg/ytXMsyBW5q/NZ1vdiIYGTKtPAyMowNYU8CvNC6jPArUFkQ4ywvPA6wPZ9eZ4HZxL3X5cLeMFcTVNDUHsg8+QXynjEQ1pguK7WrpsY9zAE+8J/yLE14789lUOAizYodElvn6VT/2JOT9IZ4lyTkFUr/uR0lSOK3cqtvcE0nAcmjMPt+4uRyzEvMEmXR8Mx4iTbXv6c9Cdaqxd0c0GJf4yD4LXJ29EGfkOsyA1peAxgXDhJiZhAjIusB+F47bTJrk57SG520PySniOHuaXILnZpHjN6i9Nxtd9Fya5rZN8+kIk1yMNSXLlBtdMucBfcgxjurqAWDEVTe8QE4CcPU39dambj+tKUIWnP+ccZhm4E9gEvznruxMLd2YjdySyT40O2Rc62fu4Ph+B6nrc+xPakhBx+urmZgxo3dd0lov/vBmZ6mZkQB+jm5GZRtx7hsINbPcTSiAvZbo5EZQ2VsBLvOcXJTc4a9frJbc/W6zPz2EGyP2iEbbKVi8ZCZpHIkHj8ux2dXbPXojdpp5B3niwAuEwzb1iOjR/I3j3oS5MNLTxjAQxocIDLn2URYVy6gRepelWH5lXU/EZjAM76Xs1egzqO4un48PKPzapb40RH5p6oK6sjTh0UQ1S53b/ymmZztvGvfg0RSrTl5ZKCZLSBePP9F3mMYyT940Swbr7GMjKVQfqBoW5O1KckdrvIQSS+vTKMoWu6A3x/eJi95Gtfdlb5LokNUy74/JnJ1pFawxm9NQRnaVXBrjZxLn9F2qnqruNXiGynKejs+mlNKUHEG+aGra37itqajFobSNTWT1V3qtMYt2lhKkSQAgo0MjEXmGrVzHeFu9tpNklNBEWHMWxGAFRBbAAC6NOA9FMsUdQXNh4yRUt0GxsI72AWc6AHyQJQeDU3z4X0c6VNRS9UjhyEBfvWCJgG07+GbPGIJPttLjUZ58XF0p3FR+PcqlTdDuFUo+QL+OsRQqDBDWnitTDpzhLfuBFvIh8AUhQyFu8exeTAF95By/G76/fqPVcanVeopk9YaHpXIhbZg+3OprxcratgMCJfyPe0grPEKMsI56eZQ4DdUI6c/Ttl9NzxZTs5HxGrvBASRH2Km8xbWth1kG3TLLkQzXA+jz2QJSvJipTM20iQBUdGsNSMSA7sl+3y5rW22JolDPWNKggPY0Zejb3P2VGV6HdbOxUZnQIVt3zkYnRtSbzkXmhv6bUvVGjHnvEE4GpTuqZVYYJPimP+R9rum9mnQZHa1E537fGXpmtMTEq3EAtA7M+mLmWqytXiMrYCu+xl0uvVoZOZJMC3buBVu0xi19YwCWAcyRF3LVG3Itwdt04enOpQfGbP1QlQqcda/WVSS7mD/uqJJeweo0SoSjNtIrg5sJSggfMCBxCJGC3zzKW7RJgWZp7LQPqTvtd1fN9a7eCppgytm/trmOdZUPha/2rsHJ4/dM7++5v</diagram></mxfile>
|
||||
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 399 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 3.0 KiB |
@@ -6,10 +6,9 @@ repositories {
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion '25.0.2'
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 1
|
||||
versionName "1.0.0"
|
||||
@@ -35,23 +34,23 @@ ext {
|
||||
|
||||
dependencies {
|
||||
// Support libraries
|
||||
compile "com.android.support:appcompat-v7:$supportLibraryVersion"
|
||||
compile "com.android.support:design:$supportLibraryVersion"
|
||||
implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
|
||||
implementation "com.android.support:design:$supportLibraryVersion"
|
||||
|
||||
//MVP Moxy
|
||||
compile "com.arello-mobile:moxy:$moxyVersion"
|
||||
compile "com.arello-mobile:moxy-app-compat:$moxyVersion"
|
||||
provided "com.arello-mobile:moxy-compiler:$moxyVersion"
|
||||
implementation "com.arello-mobile:moxy:$moxyVersion"
|
||||
implementation "com.arello-mobile:moxy-app-compat:$moxyVersion"
|
||||
annotationProcessor "com.arello-mobile:moxy-compiler:$moxyVersion"
|
||||
|
||||
//Cicerone
|
||||
compile project(':library')
|
||||
implementation project(':library')
|
||||
|
||||
//DI
|
||||
compile "com.google.dagger:dagger:$daggerVersion"
|
||||
implementation "com.google.dagger:dagger:$daggerVersion"
|
||||
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
|
||||
|
||||
//Bottom Navigation Bar
|
||||
compile ('com.ashokvarma.android:bottom-navigation-bar:1.3.0') {
|
||||
implementation ('com.ashokvarma.android:bottom-navigation-bar:1.3.0') {
|
||||
exclude group: "com.android.support", module: "design"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,115 @@
|
||||
package ru.terrakok.cicerone.sample;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import ru.terrakok.cicerone.android.support.SupportAppScreen;
|
||||
import ru.terrakok.cicerone.sample.ui.animations.ProfileActivity;
|
||||
import ru.terrakok.cicerone.sample.ui.animations.photos.SelectPhotoFragment;
|
||||
import ru.terrakok.cicerone.sample.ui.animations.profile.ProfileFragment;
|
||||
import ru.terrakok.cicerone.sample.ui.bottom.BottomNavigationActivity;
|
||||
import ru.terrakok.cicerone.sample.ui.bottom.ForwardFragment;
|
||||
import ru.terrakok.cicerone.sample.ui.bottom.TabContainerFragment;
|
||||
import ru.terrakok.cicerone.sample.ui.main.MainActivity;
|
||||
import ru.terrakok.cicerone.sample.ui.main.SampleFragment;
|
||||
import ru.terrakok.cicerone.sample.ui.start.StartActivity;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
*/
|
||||
|
||||
public class Screens {
|
||||
public static final String SAMPLE_SCREEN = "sample_screen_";
|
||||
public static final String START_ACTIVITY_SCREEN = "start activity screen";
|
||||
public static final String MAIN_ACTIVITY_SCREEN = "main activity screen";
|
||||
public static final class SampleScreen extends SupportAppScreen {
|
||||
private final int number;
|
||||
|
||||
public static final String BOTTOM_NAVIGATION_ACTIVITY_SCREEN = "bna screen";
|
||||
public SampleScreen(int number) {
|
||||
this.number = number;
|
||||
this.screenKey = getClass().getSimpleName() + "_" + number;
|
||||
}
|
||||
|
||||
public static final String ANDROID_SCREEN = "android screen";
|
||||
public static final String BUG_SCREEN = "bug screen";
|
||||
public static final String DOG_SCREEN = "dog screen";
|
||||
@Override
|
||||
public Fragment getFragment() {
|
||||
return SampleFragment.getNewInstance(number);
|
||||
}
|
||||
}
|
||||
|
||||
public static final String FORWARD_SCREEN = "forward screen";
|
||||
public static final String GITHUB_SCREEN = "github screen";
|
||||
public static final class StartScreen extends SupportAppScreen {
|
||||
@Override
|
||||
public Intent getActivityIntent(Context context) {
|
||||
return new Intent(context, StartActivity.class);
|
||||
}
|
||||
}
|
||||
|
||||
public static final String PROFILE_SCREEN = "profile screen";
|
||||
public static final String SELECT_PHOTO_SCREEN = "select photo screen";
|
||||
public static final class MainScreen extends SupportAppScreen {
|
||||
@Override
|
||||
public Intent getActivityIntent(Context context) {
|
||||
return new Intent(context, MainActivity.class);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class BottomNavigationScreen extends SupportAppScreen {
|
||||
@Override
|
||||
public Intent getActivityIntent(Context context) {
|
||||
return new Intent(context, BottomNavigationActivity.class);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class TabScreen extends SupportAppScreen {
|
||||
private final String tabName;
|
||||
|
||||
public TabScreen(String tabName) {
|
||||
this.tabName = tabName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getFragment() {
|
||||
return TabContainerFragment.getNewInstance(tabName);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ForwardScreen extends SupportAppScreen {
|
||||
private final String containerName;
|
||||
private final int number;
|
||||
|
||||
public ForwardScreen(String containerName, int number) {
|
||||
this.containerName = containerName;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getFragment() {
|
||||
return ForwardFragment.getNewInstance(containerName, number);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class GithubScreen extends SupportAppScreen {
|
||||
@Override
|
||||
public Intent getActivityIntent(Context context) {
|
||||
return new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/terrakok/Cicerone"));
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ProfileScreen extends SupportAppScreen {
|
||||
@Override
|
||||
public Intent getActivityIntent(Context context) {
|
||||
return new Intent(context, ProfileActivity.class);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ProfileInfoScreen extends SupportAppScreen {
|
||||
@Override
|
||||
public Fragment getFragment() {
|
||||
return new ProfileFragment();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SelectPhotoScreen extends SupportAppScreen {
|
||||
@Override
|
||||
public Fragment getFragment() {
|
||||
return new SelectPhotoFragment();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import javax.inject.Singleton;
|
||||
import dagger.Component;
|
||||
import ru.terrakok.cicerone.sample.dagger.module.LocalNavigationModule;
|
||||
import ru.terrakok.cicerone.sample.dagger.module.NavigationModule;
|
||||
import ru.terrakok.cicerone.sample.dagger.module.PhotoSelectionModule;
|
||||
import ru.terrakok.cicerone.sample.ui.animations.ProfileActivity;
|
||||
import ru.terrakok.cicerone.sample.ui.animations.photos.SelectPhotoFragment;
|
||||
import ru.terrakok.cicerone.sample.ui.animations.profile.ProfileFragment;
|
||||
@@ -21,7 +22,8 @@ import ru.terrakok.cicerone.sample.ui.start.StartActivity;
|
||||
@Singleton
|
||||
@Component(modules = {
|
||||
NavigationModule.class,
|
||||
LocalNavigationModule.class
|
||||
LocalNavigationModule.class,
|
||||
PhotoSelectionModule.class
|
||||
})
|
||||
public interface AppComponent {
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package ru.terrakok.cicerone.sample.dagger.module;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import ru.terrakok.cicerone.sample.R;
|
||||
import ru.terrakok.cicerone.sample.mvp.animation.PhotoSelection;
|
||||
|
||||
/**
|
||||
* Created by terrakok 24.11.16
|
||||
*/
|
||||
|
||||
@Module
|
||||
public class PhotoSelectionModule {
|
||||
private PhotoSelection photoSelection = new PhotoSelection(R.drawable.ava_1);
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
PhotoSelection providePhotoSelectionr() {
|
||||
return photoSelection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package ru.terrakok.cicerone.sample.mvp.animation;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok) on 22.09.18.
|
||||
*/
|
||||
public class PhotoSelection {
|
||||
private int selectedPhoto;
|
||||
private Listener listener;
|
||||
|
||||
public PhotoSelection(int defaultPhoto) {
|
||||
this.selectedPhoto = defaultPhoto;
|
||||
}
|
||||
|
||||
public int getSelectedPhoto() {
|
||||
return selectedPhoto;
|
||||
}
|
||||
|
||||
public void setSelectedPhoto(int selectedPhoto) {
|
||||
this.selectedPhoto = selectedPhoto;
|
||||
if (listener != null) {
|
||||
listener.onChange(selectedPhoto);
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener(Listener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void onChange(int selectedPhoto);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.arellomobile.mvp.MvpPresenter;
|
||||
|
||||
import ru.terrakok.cicerone.Router;
|
||||
import ru.terrakok.cicerone.sample.R;
|
||||
import ru.terrakok.cicerone.sample.mvp.animation.PhotoSelection;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok) on 14.07.17.
|
||||
@@ -13,11 +14,11 @@ import ru.terrakok.cicerone.sample.R;
|
||||
@InjectViewState
|
||||
public class SelectPhotoPresenter extends MvpPresenter<SelectPhotoView> {
|
||||
private Router router;
|
||||
private final int RESULT_CODE;
|
||||
private PhotoSelection photoSelection;
|
||||
|
||||
public SelectPhotoPresenter(Router router, int resultCode) {
|
||||
public SelectPhotoPresenter(PhotoSelection photoSelection, Router router) {
|
||||
this.photoSelection = photoSelection;
|
||||
this.router = router;
|
||||
RESULT_CODE = resultCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -33,7 +34,8 @@ public class SelectPhotoPresenter extends MvpPresenter<SelectPhotoView> {
|
||||
}
|
||||
|
||||
public void onPhotoClick(int photoRes) {
|
||||
router.exitWithResult(RESULT_CODE, photoRes);
|
||||
photoSelection.setSelectedPhoto(photoRes);
|
||||
router.exit();
|
||||
}
|
||||
|
||||
public void onBackPressed() {
|
||||
|
||||
@@ -4,8 +4,8 @@ import com.arellomobile.mvp.InjectViewState;
|
||||
import com.arellomobile.mvp.MvpPresenter;
|
||||
|
||||
import ru.terrakok.cicerone.Router;
|
||||
import ru.terrakok.cicerone.result.ResultListener;
|
||||
import ru.terrakok.cicerone.sample.Screens;
|
||||
import ru.terrakok.cicerone.sample.mvp.animation.PhotoSelection;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tskhovrebov (aka @terrakok) on 14.07.17.
|
||||
@@ -13,19 +13,17 @@ import ru.terrakok.cicerone.sample.Screens;
|
||||
|
||||
@InjectViewState
|
||||
public class ProfilePresenter extends MvpPresenter<ProfileView> {
|
||||
private static final int PHOTO_RESULT_CODE = 42;
|
||||
|
||||
private Router router;
|
||||
private int currentPhoto;
|
||||
private PhotoSelection photoSelection;
|
||||
|
||||
public ProfilePresenter(int defaultPhoto, Router router) {
|
||||
currentPhoto = defaultPhoto;
|
||||
public ProfilePresenter(PhotoSelection photoSelection, Router router) {
|
||||
this.photoSelection = photoSelection;
|
||||
this.router = router;
|
||||
|
||||
router.setResultListener(PHOTO_RESULT_CODE, new ResultListener() {
|
||||
photoSelection.setListener(new PhotoSelection.Listener() {
|
||||
@Override
|
||||
public void onResult(Object resultData) {
|
||||
currentPhoto = (int) resultData;
|
||||
public void onChange(int selectedPhoto) {
|
||||
updatePhoto();
|
||||
}
|
||||
});
|
||||
@@ -39,16 +37,16 @@ public class ProfilePresenter extends MvpPresenter<ProfileView> {
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
router.removeResultListener(PHOTO_RESULT_CODE);
|
||||
photoSelection.setListener(null);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void updatePhoto() {
|
||||
getViewState().showPhoto(currentPhoto);
|
||||
getViewState().showPhoto(photoSelection.getSelectedPhoto());
|
||||
}
|
||||
|
||||
public void onPhotoClicked() {
|
||||
router.navigateTo(Screens.SELECT_PHOTO_SCREEN, PHOTO_RESULT_CODE);
|
||||
router.navigateTo(new Screens.SelectPhotoScreen());
|
||||
}
|
||||
|
||||
public void onBackPressed() {
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.arellomobile.mvp.InjectViewState;
|
||||
import com.arellomobile.mvp.MvpPresenter;
|
||||
|
||||
import ru.terrakok.cicerone.Router;
|
||||
import ru.terrakok.cicerone.sample.Screens;
|
||||
|
||||
/**
|
||||
* Created by terrakok 25.11.16
|
||||
@@ -17,21 +16,6 @@ public class BottomNavigationPresenter extends MvpPresenter<BottomNavigationView
|
||||
this.router = router;
|
||||
}
|
||||
|
||||
public void onTabAndroidClick() {
|
||||
getViewState().highlightTab(BottomNavigationView.ANDROID_TAB_POSITION);
|
||||
router.replaceScreen(Screens.ANDROID_SCREEN);
|
||||
}
|
||||
|
||||
public void onTabBugClick() {
|
||||
getViewState().highlightTab(BottomNavigationView.BUG_TAB_POSITION);
|
||||
router.replaceScreen(Screens.BUG_SCREEN);
|
||||
}
|
||||
|
||||
public void onTabDogClick() {
|
||||
getViewState().highlightTab(BottomNavigationView.DOG_TAB_POSITION);
|
||||
router.replaceScreen(Screens.DOG_SCREEN);
|
||||
}
|
||||
|
||||
public void onBackPressed() {
|
||||
router.exit();
|
||||
}
|
||||
|
||||
@@ -9,9 +9,4 @@ import com.arellomobile.mvp.viewstate.strategy.StateStrategyType;
|
||||
*/
|
||||
@StateStrategyType(AddToEndSingleStrategy.class)
|
||||
public interface BottomNavigationView extends MvpView {
|
||||
int ANDROID_TAB_POSITION = 0;
|
||||
int BUG_TAB_POSITION = 1;
|
||||
int DOG_TAB_POSITION = 2;
|
||||
|
||||
void highlightTab(int position);
|
||||
}
|
||||
|
||||
@@ -12,10 +12,12 @@ import ru.terrakok.cicerone.sample.Screens;
|
||||
|
||||
@InjectViewState
|
||||
public class ForwardPresenter extends MvpPresenter<ForwardView> {
|
||||
private String container;
|
||||
private Router router;
|
||||
private int number;
|
||||
|
||||
public ForwardPresenter(Router router, int number) {
|
||||
public ForwardPresenter(String container, Router router, int number) {
|
||||
this.container = container;
|
||||
this.router = router;
|
||||
this.number = number;
|
||||
|
||||
@@ -33,11 +35,11 @@ public class ForwardPresenter extends MvpPresenter<ForwardView> {
|
||||
}
|
||||
|
||||
public void onForwardPressed() {
|
||||
router.navigateTo(Screens.FORWARD_SCREEN, number + 1);
|
||||
router.navigateTo(new Screens.ForwardScreen(container, number + 1));
|
||||
}
|
||||
|
||||
public void onGithubPressed() {
|
||||
router.navigateTo(Screens.GITHUB_SCREEN);
|
||||
router.navigateTo(new Screens.GithubScreen());
|
||||
}
|
||||
|
||||
public void onBackPressed() {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package ru.terrakok.cicerone.sample.mvp.main;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.arellomobile.mvp.InjectViewState;
|
||||
import com.arellomobile.mvp.MvpPresenter;
|
||||
|
||||
@@ -36,23 +39,27 @@ public class SamplePresenter extends MvpPresenter<SampleView> {
|
||||
}
|
||||
|
||||
public void onForwardCommandClick() {
|
||||
router.navigateTo(Screens.SAMPLE_SCREEN + (screenNumber + 1), screenNumber + 1);
|
||||
router.navigateTo(new Screens.SampleScreen(screenNumber + 1));
|
||||
}
|
||||
|
||||
public void onReplaceCommandClick() {
|
||||
router.replaceScreen(Screens.SAMPLE_SCREEN + (screenNumber + 1), screenNumber + 1);
|
||||
router.replaceScreen(new Screens.SampleScreen(screenNumber + 1));
|
||||
}
|
||||
|
||||
public void onNewChainCommandClick() {
|
||||
router.newScreenChain(Screens.SAMPLE_SCREEN + (screenNumber + 1), screenNumber + 1);
|
||||
router.newChain(
|
||||
new Screens.SampleScreen(screenNumber + 1),
|
||||
new Screens.SampleScreen(screenNumber + 2),
|
||||
new Screens.SampleScreen(screenNumber + 3)
|
||||
);
|
||||
}
|
||||
|
||||
public void onFinishChainCommandClick() {
|
||||
router.finishChain();
|
||||
}
|
||||
|
||||
public void onNewRootCommandClick() {
|
||||
router.newRootScreen(Screens.SAMPLE_SCREEN + (screenNumber + 1), screenNumber + 1);
|
||||
}
|
||||
|
||||
public void onBackWithMessageCommandClick() {
|
||||
router.exitWithMessage("Exit from 'Screen " + screenNumber + "'");
|
||||
router.newRootScreen(new Screens.SampleScreen(screenNumber + 1));
|
||||
}
|
||||
|
||||
public void onForwardWithDelayCommandClick() {
|
||||
@@ -60,13 +67,20 @@ public class SamplePresenter extends MvpPresenter<SampleView> {
|
||||
future = executorService.schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//WARNING! Navigation must be only in UI thread. this method works only for sample :)
|
||||
router.navigateTo(Screens.SAMPLE_SCREEN + (screenNumber + 1), screenNumber + 1);
|
||||
//WARNING! Navigation must be only in UI thread.
|
||||
new Handler(Looper.getMainLooper()).post(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
router.navigateTo(new Screens.SampleScreen(screenNumber + 1));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}, 5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void onBackToCommandClick() {
|
||||
router.backTo(Screens.SAMPLE_SCREEN + 3);
|
||||
router.backTo(new Screens.SampleScreen(3));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,15 +16,15 @@ public class StartActivityPresenter extends MvpPresenter<StartActivityView> {
|
||||
}
|
||||
|
||||
public void onOrdinaryPressed() {
|
||||
router.navigateTo(Screens.MAIN_ACTIVITY_SCREEN);
|
||||
router.navigateTo(new Screens.MainScreen());
|
||||
}
|
||||
|
||||
public void onMultiPressed() {
|
||||
router.navigateTo(Screens.BOTTOM_NAVIGATION_ACTIVITY_SCREEN);
|
||||
router.navigateTo(new Screens.BottomNavigationScreen());
|
||||
}
|
||||
|
||||
public void onResultWithAnimationPressed() {
|
||||
router.navigateTo(Screens.PROFILE_SCREEN);
|
||||
router.navigateTo(new Screens.ProfileScreen());
|
||||
}
|
||||
|
||||
public void onBackPressed() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ru.terrakok.cicerone.sample.ui.animations;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
@@ -13,7 +12,7 @@ import javax.inject.Inject;
|
||||
|
||||
import ru.terrakok.cicerone.Navigator;
|
||||
import ru.terrakok.cicerone.NavigatorHolder;
|
||||
import ru.terrakok.cicerone.android.SupportAppNavigator;
|
||||
import ru.terrakok.cicerone.android.support.SupportAppNavigator;
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
import ru.terrakok.cicerone.commands.Forward;
|
||||
import ru.terrakok.cicerone.commands.Replace;
|
||||
@@ -42,7 +41,7 @@ public class ProfileActivity extends AppCompatActivity {
|
||||
setContentView(R.layout.activity_container);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
navigator.applyCommand(new Replace(Screens.PROFILE_SCREEN, null));
|
||||
navigator.applyCommands(new Command[]{new Replace(new Screens.ProfileInfoScreen())});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,23 +59,7 @@ public class ProfileActivity extends AppCompatActivity {
|
||||
|
||||
private Navigator navigator = new SupportAppNavigator(this, R.id.container) {
|
||||
@Override
|
||||
protected Intent createActivityIntent(String screenKey, Object data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Fragment createFragment(String screenKey, Object data) {
|
||||
switch (screenKey) {
|
||||
case Screens.PROFILE_SCREEN:
|
||||
return new ProfileFragment();
|
||||
case Screens.SELECT_PHOTO_SCREEN:
|
||||
return SelectPhotoFragment.getNewInstance((int) data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupFragmentTransactionAnimation(Command command, Fragment currentFragment, Fragment nextFragment, FragmentTransaction fragmentTransaction) {
|
||||
protected void setupFragmentTransaction(Command command, Fragment currentFragment, Fragment nextFragment, FragmentTransaction fragmentTransaction) {
|
||||
if (command instanceof Forward
|
||||
&& currentFragment instanceof ProfileFragment
|
||||
&& nextFragment instanceof SelectPhotoFragment) {
|
||||
|
||||
@@ -16,6 +16,7 @@ import javax.inject.Inject;
|
||||
import ru.terrakok.cicerone.Router;
|
||||
import ru.terrakok.cicerone.sample.R;
|
||||
import ru.terrakok.cicerone.sample.SampleApplication;
|
||||
import ru.terrakok.cicerone.sample.mvp.animation.PhotoSelection;
|
||||
import ru.terrakok.cicerone.sample.mvp.animation.photos.SelectPhotoPresenter;
|
||||
import ru.terrakok.cicerone.sample.mvp.animation.photos.SelectPhotoView;
|
||||
import ru.terrakok.cicerone.sample.ui.animations.ProfileActivity;
|
||||
@@ -26,7 +27,6 @@ import ru.terrakok.cicerone.sample.ui.common.BackButtonListener;
|
||||
*/
|
||||
|
||||
public class SelectPhotoFragment extends MvpAppCompatFragment implements SelectPhotoView, BackButtonListener {
|
||||
private static final String ARG_RESULT_CODE = "arg_result_code";
|
||||
private static final String ARG_ANIM_DESTINATION = "arg_anim_dest";
|
||||
|
||||
private ImageView photo1;
|
||||
@@ -37,19 +37,15 @@ public class SelectPhotoFragment extends MvpAppCompatFragment implements SelectP
|
||||
@Inject
|
||||
Router router;
|
||||
|
||||
@Inject
|
||||
PhotoSelection photoSelection;
|
||||
|
||||
@InjectPresenter
|
||||
SelectPhotoPresenter presenter;
|
||||
|
||||
public static SelectPhotoFragment getNewInstance(int resultCode) {
|
||||
SelectPhotoFragment fragment = new SelectPhotoFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(ARG_RESULT_CODE, resultCode);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public void setAnimationDestinationId(int resId) {
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments == null) arguments = new Bundle();
|
||||
arguments.putInt(ARG_ANIM_DESTINATION, resId);
|
||||
setArguments(arguments);
|
||||
}
|
||||
@@ -60,7 +56,7 @@ public class SelectPhotoFragment extends MvpAppCompatFragment implements SelectP
|
||||
|
||||
@ProvidePresenter
|
||||
SelectPhotoPresenter providePresenter() {
|
||||
return new SelectPhotoPresenter(router, getArguments().getInt(ARG_RESULT_CODE));
|
||||
return new SelectPhotoPresenter(photoSelection, router);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,7 @@ import javax.inject.Inject;
|
||||
import ru.terrakok.cicerone.Router;
|
||||
import ru.terrakok.cicerone.sample.R;
|
||||
import ru.terrakok.cicerone.sample.SampleApplication;
|
||||
import ru.terrakok.cicerone.sample.mvp.animation.PhotoSelection;
|
||||
import ru.terrakok.cicerone.sample.mvp.animation.profile.ProfilePresenter;
|
||||
import ru.terrakok.cicerone.sample.mvp.animation.profile.ProfileView;
|
||||
import ru.terrakok.cicerone.sample.ui.animations.ProfileActivity;
|
||||
@@ -34,9 +35,12 @@ public class ProfileFragment extends MvpAppCompatFragment implements ProfileView
|
||||
@InjectPresenter
|
||||
ProfilePresenter presenter;
|
||||
|
||||
@Inject
|
||||
PhotoSelection photoSelection;
|
||||
|
||||
@ProvidePresenter
|
||||
ProfilePresenter providePresenter() {
|
||||
return new ProfilePresenter(R.drawable.ava_1, router);
|
||||
return new ProfilePresenter(photoSelection, router);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,7 @@ package ru.terrakok.cicerone.sample.ui.bottom;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.widget.Toast;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
|
||||
import com.arellomobile.mvp.MvpAppCompatActivity;
|
||||
import com.arellomobile.mvp.presenter.InjectPresenter;
|
||||
@@ -11,15 +11,11 @@ import com.arellomobile.mvp.presenter.ProvidePresenter;
|
||||
import com.ashokvarma.bottomnavigation.BottomNavigationBar;
|
||||
import com.ashokvarma.bottomnavigation.BottomNavigationItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import ru.terrakok.cicerone.Navigator;
|
||||
import ru.terrakok.cicerone.NavigatorHolder;
|
||||
import ru.terrakok.cicerone.Router;
|
||||
import ru.terrakok.cicerone.commands.Back;
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
import ru.terrakok.cicerone.commands.Replace;
|
||||
import ru.terrakok.cicerone.commands.SystemMessage;
|
||||
import ru.terrakok.cicerone.sample.R;
|
||||
import ru.terrakok.cicerone.sample.SampleApplication;
|
||||
import ru.terrakok.cicerone.sample.Screens;
|
||||
@@ -33,16 +29,10 @@ import ru.terrakok.cicerone.sample.ui.common.RouterProvider;
|
||||
*/
|
||||
public class BottomNavigationActivity extends MvpAppCompatActivity implements BottomNavigationView, RouterProvider {
|
||||
private BottomNavigationBar bottomNavigationBar;
|
||||
private TabContainerFragment androidTabFragment;
|
||||
private TabContainerFragment bugTabFragment;
|
||||
private TabContainerFragment dogTabFragment;
|
||||
|
||||
@Inject
|
||||
Router router;
|
||||
|
||||
@Inject
|
||||
NavigatorHolder navigatorHolder;
|
||||
|
||||
@InjectPresenter
|
||||
BottomNavigationPresenter presenter;
|
||||
|
||||
@@ -60,10 +50,9 @@ public class BottomNavigationActivity extends MvpAppCompatActivity implements Bo
|
||||
bottomNavigationBar = (BottomNavigationBar) findViewById(R.id.ab_bottom_navigation_bar);
|
||||
|
||||
initViews();
|
||||
initContainers();
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
bottomNavigationBar.selectTab(ANDROID_TAB_POSITION, true);
|
||||
bottomNavigationBar.selectTab(0, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,16 +66,17 @@ public class BottomNavigationActivity extends MvpAppCompatActivity implements Bo
|
||||
@Override
|
||||
public void onTabSelected(int position) {
|
||||
switch (position) {
|
||||
case ANDROID_TAB_POSITION:
|
||||
presenter.onTabAndroidClick();
|
||||
case 0:
|
||||
selectTab("ANDROID");
|
||||
break;
|
||||
case BUG_TAB_POSITION:
|
||||
presenter.onTabBugClick();
|
||||
case 1:
|
||||
selectTab("BUG");
|
||||
break;
|
||||
case DOG_TAB_POSITION:
|
||||
presenter.onTabDogClick();
|
||||
case 2:
|
||||
selectTab("DOG");
|
||||
break;
|
||||
}
|
||||
bottomNavigationBar.selectTab(position, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,48 +92,50 @@ public class BottomNavigationActivity extends MvpAppCompatActivity implements Bo
|
||||
|
||||
}
|
||||
|
||||
private void initContainers() {
|
||||
private void selectTab(String tab) {
|
||||
FragmentManager fm = getSupportFragmentManager();
|
||||
androidTabFragment = (TabContainerFragment) fm.findFragmentByTag("ANDROID");
|
||||
if (androidTabFragment == null) {
|
||||
androidTabFragment = TabContainerFragment.getNewInstance("ANDROID");
|
||||
fm.beginTransaction()
|
||||
.add(R.id.ab_container, androidTabFragment, "ANDROID")
|
||||
.detach(androidTabFragment).commitNow();
|
||||
Fragment currentFragment = null;
|
||||
List<Fragment> fragments = fm.getFragments();
|
||||
if (fragments != null) {
|
||||
for (Fragment f : fragments) {
|
||||
if (f.isVisible()) {
|
||||
currentFragment = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Fragment newFragment = fm.findFragmentByTag(tab);
|
||||
|
||||
if (currentFragment != null && newFragment != null && currentFragment == newFragment) return;
|
||||
|
||||
FragmentTransaction transaction = fm.beginTransaction();
|
||||
if (newFragment == null) {
|
||||
transaction.add(R.id.ab_container, new Screens.TabScreen(tab).getFragment(), tab);
|
||||
}
|
||||
|
||||
bugTabFragment = (TabContainerFragment) fm.findFragmentByTag("BUG");
|
||||
if (bugTabFragment == null) {
|
||||
bugTabFragment = TabContainerFragment.getNewInstance("BUG");
|
||||
fm.beginTransaction()
|
||||
.add(R.id.ab_container, bugTabFragment, "BUG")
|
||||
.detach(bugTabFragment).commitNow();
|
||||
if (currentFragment != null) {
|
||||
transaction.hide(currentFragment);
|
||||
}
|
||||
|
||||
dogTabFragment = (TabContainerFragment) fm.findFragmentByTag("DOG");
|
||||
if (dogTabFragment == null) {
|
||||
dogTabFragment = TabContainerFragment.getNewInstance("DOG");
|
||||
fm.beginTransaction()
|
||||
.add(R.id.ab_container, dogTabFragment, "DOG")
|
||||
.detach(dogTabFragment).commitNow();
|
||||
if (newFragment != null) {
|
||||
transaction.show(newFragment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResumeFragments() {
|
||||
super.onResumeFragments();
|
||||
navigatorHolder.setNavigator(navigator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
navigatorHolder.removeNavigator();
|
||||
super.onPause();
|
||||
transaction.commitNow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.ab_container);
|
||||
FragmentManager fm = getSupportFragmentManager();
|
||||
Fragment fragment = null;
|
||||
List<Fragment> fragments = fm.getFragments();
|
||||
if (fragments != null) {
|
||||
for (Fragment f : fragments) {
|
||||
if (f.isVisible()) {
|
||||
fragment = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fragment != null
|
||||
&& fragment instanceof BackButtonListener
|
||||
&& ((BackButtonListener) fragment).onBackPressed()) {
|
||||
@@ -153,48 +145,6 @@ public class BottomNavigationActivity extends MvpAppCompatActivity implements Bo
|
||||
}
|
||||
}
|
||||
|
||||
private Navigator navigator = new Navigator() {
|
||||
@Override
|
||||
public void applyCommand(Command command) {
|
||||
if (command instanceof Back) {
|
||||
finish();
|
||||
} else if (command instanceof SystemMessage) {
|
||||
Toast.makeText(BottomNavigationActivity.this, ((SystemMessage) command).getMessage(), Toast.LENGTH_SHORT).show();
|
||||
} else if (command instanceof Replace) {
|
||||
FragmentManager fm = getSupportFragmentManager();
|
||||
|
||||
switch (((Replace) command).getScreenKey()) {
|
||||
case Screens.ANDROID_SCREEN:
|
||||
fm.beginTransaction()
|
||||
.detach(bugTabFragment)
|
||||
.detach(dogTabFragment)
|
||||
.attach(androidTabFragment)
|
||||
.commitNow();
|
||||
break;
|
||||
case Screens.BUG_SCREEN:
|
||||
fm.beginTransaction()
|
||||
.detach(androidTabFragment)
|
||||
.detach(dogTabFragment)
|
||||
.attach(bugTabFragment)
|
||||
.commitNow();
|
||||
break;
|
||||
case Screens.DOG_SCREEN:
|
||||
fm.beginTransaction()
|
||||
.detach(androidTabFragment)
|
||||
.detach(bugTabFragment)
|
||||
.attach(dogTabFragment)
|
||||
.commitNow();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void highlightTab(int position) {
|
||||
bottomNavigationBar.selectTab(position, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Router getRouter() {
|
||||
return router;
|
||||
|
||||
@@ -36,6 +36,7 @@ public class ForwardFragment extends MvpAppCompatFragment implements ForwardView
|
||||
@ProvidePresenter
|
||||
ForwardPresenter provideForwardPresenter() {
|
||||
return new ForwardPresenter(
|
||||
getArguments().getString(EXTRA_NAME),
|
||||
((RouterProvider) getParentFragment()).getRouter(),
|
||||
getArguments().getInt(EXTRA_NUMBER)
|
||||
);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package ru.terrakok.cicerone.sample.ui.bottom;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
@@ -14,7 +12,7 @@ import javax.inject.Inject;
|
||||
import ru.terrakok.cicerone.Cicerone;
|
||||
import ru.terrakok.cicerone.Navigator;
|
||||
import ru.terrakok.cicerone.Router;
|
||||
import ru.terrakok.cicerone.android.SupportAppNavigator;
|
||||
import ru.terrakok.cicerone.android.support.SupportAppNavigator;
|
||||
import ru.terrakok.cicerone.sample.R;
|
||||
import ru.terrakok.cicerone.sample.SampleApplication;
|
||||
import ru.terrakok.cicerone.sample.Screens;
|
||||
@@ -68,7 +66,7 @@ public class TabContainerFragment extends Fragment implements RouterProvider, Ba
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
if (getChildFragmentManager().findFragmentById(R.id.ftc_container) == null) {
|
||||
getCicerone().getRouter().replaceScreen(Screens.FORWARD_SCREEN, 0);
|
||||
getCicerone().getRouter().replaceScreen(new Screens.ForwardScreen(getContainerName(), 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,29 +84,7 @@ public class TabContainerFragment extends Fragment implements RouterProvider, Ba
|
||||
|
||||
private Navigator getNavigator() {
|
||||
if (navigator == null) {
|
||||
navigator = new SupportAppNavigator(getActivity(), getChildFragmentManager(), R.id.ftc_container) {
|
||||
|
||||
@Override
|
||||
protected Intent createActivityIntent(String screenKey, Object data) {
|
||||
if (screenKey.equals(Screens.GITHUB_SCREEN)) {
|
||||
return new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/terrakok/Cicerone"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Fragment createFragment(String screenKey, Object data) {
|
||||
if (screenKey.equals(Screens.FORWARD_SCREEN)) {
|
||||
return ForwardFragment.getNewInstance(getContainerName(), (int) data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exit() {
|
||||
((RouterProvider) getActivity()).getRouter().exit();
|
||||
}
|
||||
};
|
||||
navigator = new SupportAppNavigator(getActivity(), getChildFragmentManager(), R.id.ftc_container);
|
||||
}
|
||||
return navigator;
|
||||
}
|
||||
|
||||
@@ -4,23 +4,19 @@ import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.arellomobile.mvp.MvpAppCompatActivity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import ru.terrakok.cicerone.Navigator;
|
||||
import ru.terrakok.cicerone.NavigatorHolder;
|
||||
import ru.terrakok.cicerone.android.SupportFragmentNavigator;
|
||||
import ru.terrakok.cicerone.commands.Back;
|
||||
import ru.terrakok.cicerone.commands.BackTo;
|
||||
import ru.terrakok.cicerone.android.support.SupportAppNavigator;
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
import ru.terrakok.cicerone.commands.Forward;
|
||||
import ru.terrakok.cicerone.commands.Replace;
|
||||
import ru.terrakok.cicerone.sample.R;
|
||||
import ru.terrakok.cicerone.sample.SampleApplication;
|
||||
@@ -33,34 +29,17 @@ import ru.terrakok.cicerone.sample.ui.common.BackButtonListener;
|
||||
*/
|
||||
|
||||
public class MainActivity extends MvpAppCompatActivity {
|
||||
private static final String STATE_SCREEN_NAMES = "state_screen_names";
|
||||
|
||||
private List<String> screenNames = new ArrayList<>();
|
||||
private TextView screensSchemeTV;
|
||||
|
||||
@Inject
|
||||
NavigatorHolder navigatorHolder;
|
||||
|
||||
private Navigator navigator = new SupportFragmentNavigator(getSupportFragmentManager(), R.id.main_container) {
|
||||
private Navigator navigator = new SupportAppNavigator(this, R.id.main_container) {
|
||||
@Override
|
||||
protected Fragment createFragment(String screenKey, Object data) {
|
||||
return SampleFragment.getNewInstance((int) data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showSystemMessage(String message) {
|
||||
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exit() {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyCommand(Command command) {
|
||||
super.applyCommand(command);
|
||||
updateScreenNames(command);
|
||||
public void applyCommands(Command[] commands) {
|
||||
super.applyCommands(commands);
|
||||
getSupportFragmentManager().executePendingTransactions();
|
||||
printScreensScheme();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -73,9 +52,8 @@ public class MainActivity extends MvpAppCompatActivity {
|
||||
screensSchemeTV = (TextView) findViewById(R.id.screens_scheme);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
navigator.applyCommand(new Replace(Screens.SAMPLE_SCREEN, 1));
|
||||
navigator.applyCommands(new Command[]{new Replace(new Screens.SampleScreen(1))});
|
||||
} else {
|
||||
screenNames = (List<String>) savedInstanceState.getSerializable(STATE_SCREEN_NAMES);
|
||||
printScreensScheme();
|
||||
}
|
||||
}
|
||||
@@ -104,41 +82,27 @@ public class MainActivity extends MvpAppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putSerializable(STATE_SCREEN_NAMES, (Serializable) screenNames);
|
||||
}
|
||||
|
||||
private void updateScreenNames(Command command) {
|
||||
if (command instanceof Back) {
|
||||
if (screenNames.size() > 0) {
|
||||
screenNames.remove(screenNames.size() - 1);
|
||||
}
|
||||
} else if (command instanceof Forward) {
|
||||
int i = (int) ((Forward) command).getTransitionData();
|
||||
screenNames.add(i + "");
|
||||
} else if (command instanceof Replace) {
|
||||
int i = (int) ((Replace) command).getTransitionData();
|
||||
if (screenNames.size() > 0) {
|
||||
screenNames.remove(screenNames.size() - 1);
|
||||
}
|
||||
screenNames.add(i + "");
|
||||
} else if (command instanceof BackTo) {
|
||||
screenNames = new ArrayList<>(screenNames.subList(0, getSupportFragmentManager().getBackStackEntryCount() + 1));
|
||||
}
|
||||
printScreensScheme();
|
||||
}
|
||||
|
||||
private void printScreensScheme() {
|
||||
String str = "";
|
||||
for (String name : screenNames) {
|
||||
if (!str.isEmpty()) {
|
||||
str += "➔" + name;
|
||||
} else {
|
||||
str = "[" + name + "]";
|
||||
ArrayList<SampleFragment> fragments = new ArrayList<>();
|
||||
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
|
||||
if (fragment instanceof SampleFragment) {
|
||||
fragments.add((SampleFragment) fragment);
|
||||
}
|
||||
}
|
||||
screensSchemeTV.setText("Chain: " + str + "");
|
||||
Collections.sort(fragments, new Comparator<SampleFragment>() {
|
||||
@Override
|
||||
public int compare(SampleFragment f1, SampleFragment f2) {
|
||||
long t = f1.getCreationTime() - f2.getCreationTime();
|
||||
if (t > 0) return 1;
|
||||
else if (t < 0) return -1;
|
||||
else return 0;
|
||||
}
|
||||
});
|
||||
|
||||
ArrayList<Integer> keys = new ArrayList<>();
|
||||
for (SampleFragment fragment : fragments) {
|
||||
keys.add(fragment.getNumber());
|
||||
}
|
||||
screensSchemeTV.setText("Chain: " + keys.toString() + "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import ru.terrakok.cicerone.sample.ui.common.BackButtonListener;
|
||||
|
||||
public class SampleFragment extends MvpAppCompatFragment implements SampleView, BackButtonListener {
|
||||
private static final String EXTRA_NUMBER = "extra_number";
|
||||
private static final String EXTRA_TIME = "extra_time";
|
||||
|
||||
private Toolbar toolbar;
|
||||
private View backCommandBt;
|
||||
@@ -34,9 +35,9 @@ public class SampleFragment extends MvpAppCompatFragment implements SampleView,
|
||||
private View replaceCommandBt;
|
||||
private View newChainCommandBt;
|
||||
private View newRootCommandBt;
|
||||
private View backWithMessageCommandBt;
|
||||
private View forwardWithDelayCommandBt;
|
||||
private View backToCommandBt;
|
||||
private View finishChainCommandBt;
|
||||
|
||||
@Inject
|
||||
Router router;
|
||||
@@ -54,11 +55,20 @@ public class SampleFragment extends MvpAppCompatFragment implements SampleView,
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(EXTRA_NUMBER, number);
|
||||
args.putLong(EXTRA_TIME, System.currentTimeMillis());
|
||||
fragment.setArguments(args);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return getArguments().getInt(EXTRA_NUMBER);
|
||||
}
|
||||
|
||||
public long getCreationTime() {
|
||||
return getArguments().getLong(EXTRA_TIME, 0L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
SampleApplication.INSTANCE.getAppComponent().inject(this);
|
||||
@@ -80,9 +90,9 @@ public class SampleFragment extends MvpAppCompatFragment implements SampleView,
|
||||
replaceCommandBt = view.findViewById(R.id.replace_command);
|
||||
newChainCommandBt = view.findViewById(R.id.new_chain_command);
|
||||
newRootCommandBt = view.findViewById(R.id.new_root_command);
|
||||
backWithMessageCommandBt = view.findViewById(R.id.back_with_message_command);
|
||||
forwardWithDelayCommandBt = view.findViewById(R.id.forward_delay_command);
|
||||
backToCommandBt = view.findViewById(R.id.back_to_command);
|
||||
finishChainCommandBt = view.findViewById(R.id.finish_chain_command);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -124,12 +134,6 @@ public class SampleFragment extends MvpAppCompatFragment implements SampleView,
|
||||
presenter.onNewRootCommandClick();
|
||||
}
|
||||
});
|
||||
backWithMessageCommandBt.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
presenter.onBackWithMessageCommandClick();
|
||||
}
|
||||
});
|
||||
forwardWithDelayCommandBt.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
@@ -142,6 +146,12 @@ public class SampleFragment extends MvpAppCompatFragment implements SampleView,
|
||||
presenter.onBackToCommandClick();
|
||||
}
|
||||
});
|
||||
finishChainCommandBt.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
presenter.onFinishChainCommandClick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package ru.terrakok.cicerone.sample.ui.start;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.arellomobile.mvp.MvpAppCompatActivity;
|
||||
import com.arellomobile.mvp.presenter.InjectPresenter;
|
||||
@@ -15,19 +12,11 @@ import javax.inject.Inject;
|
||||
import ru.terrakok.cicerone.Navigator;
|
||||
import ru.terrakok.cicerone.NavigatorHolder;
|
||||
import ru.terrakok.cicerone.Router;
|
||||
import ru.terrakok.cicerone.commands.Back;
|
||||
import ru.terrakok.cicerone.commands.Command;
|
||||
import ru.terrakok.cicerone.commands.Forward;
|
||||
import ru.terrakok.cicerone.commands.Replace;
|
||||
import ru.terrakok.cicerone.commands.SystemMessage;
|
||||
import ru.terrakok.cicerone.android.support.SupportAppNavigator;
|
||||
import ru.terrakok.cicerone.sample.R;
|
||||
import ru.terrakok.cicerone.sample.SampleApplication;
|
||||
import ru.terrakok.cicerone.sample.Screens;
|
||||
import ru.terrakok.cicerone.sample.mvp.start.StartActivityPresenter;
|
||||
import ru.terrakok.cicerone.sample.mvp.start.StartActivityView;
|
||||
import ru.terrakok.cicerone.sample.ui.animations.ProfileActivity;
|
||||
import ru.terrakok.cicerone.sample.ui.bottom.BottomNavigationActivity;
|
||||
import ru.terrakok.cicerone.sample.ui.main.MainActivity;
|
||||
|
||||
/**
|
||||
* Created by terrakok 21.11.16
|
||||
@@ -42,6 +31,8 @@ public class StartActivity extends MvpAppCompatActivity implements StartActivity
|
||||
@InjectPresenter
|
||||
StartActivityPresenter presenter;
|
||||
|
||||
private Navigator navigator = new SupportAppNavigator(this, -1);
|
||||
|
||||
@ProvidePresenter
|
||||
public StartActivityPresenter createStartActivityPresenter() {
|
||||
return new StartActivityPresenter(router);
|
||||
@@ -93,61 +84,4 @@ public class StartActivity extends MvpAppCompatActivity implements StartActivity
|
||||
public void onBackPressed() {
|
||||
presenter.onBackPressed();
|
||||
}
|
||||
|
||||
//Sample fully custom navigator:
|
||||
private Navigator navigator = new Navigator() {
|
||||
@Override
|
||||
public void applyCommand(Command command) {
|
||||
if (command instanceof Forward) {
|
||||
forward((Forward) command);
|
||||
} else if (command instanceof Replace) {
|
||||
replace((Replace) command);
|
||||
} else if (command instanceof Back) {
|
||||
back();
|
||||
} else if (command instanceof SystemMessage) {
|
||||
Toast.makeText(StartActivity.this, ((SystemMessage) command).getMessage(), Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Log.e("Cicerone", "Illegal command for this screen: " + command.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
private void forward(Forward command) {
|
||||
switch (command.getScreenKey()) {
|
||||
case Screens.START_ACTIVITY_SCREEN:
|
||||
startActivity(new Intent(StartActivity.this, StartActivity.class));
|
||||
break;
|
||||
case Screens.MAIN_ACTIVITY_SCREEN:
|
||||
startActivity(new Intent(StartActivity.this, MainActivity.class));
|
||||
break;
|
||||
case Screens.BOTTOM_NAVIGATION_ACTIVITY_SCREEN:
|
||||
startActivity(new Intent(StartActivity.this, BottomNavigationActivity.class));
|
||||
break;
|
||||
case Screens.PROFILE_SCREEN:
|
||||
startActivity(new Intent(StartActivity.this, ProfileActivity.class));
|
||||
break;
|
||||
default:
|
||||
Log.e("Cicerone", "Unknown screen: " + command.getScreenKey());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void replace(Replace command) {
|
||||
switch (command.getScreenKey()) {
|
||||
case Screens.START_ACTIVITY_SCREEN:
|
||||
case Screens.MAIN_ACTIVITY_SCREEN:
|
||||
case Screens.BOTTOM_NAVIGATION_ACTIVITY_SCREEN:
|
||||
case Screens.PROFILE_SCREEN:
|
||||
forward(new Forward(command.getScreenKey(), command.getTransitionData()));
|
||||
finish();
|
||||
break;
|
||||
default:
|
||||
Log.e("Cicerone", "Unknown screen: " + command.getScreenKey());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void back() {
|
||||
finish();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,26 +13,30 @@
|
||||
app:navigationIcon="@drawable/ic_arrow_back_white_24dp"
|
||||
app:title="@string/app_name"/>
|
||||
|
||||
<LinearLayout
|
||||
<GridLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
android:columnCount="2">
|
||||
|
||||
<TextView
|
||||
android:layout_margin="4dp"
|
||||
android:id="@+id/back_command"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:background="@color/carrot"
|
||||
android:gravity="center"
|
||||
android:text="Back"
|
||||
android:layout_columnWeight="1"
|
||||
android:textSize="28sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/forward_command"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:background="@color/sunflower"
|
||||
android:gravity="center"
|
||||
android:text="Forward"
|
||||
@@ -40,9 +44,11 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/replace_command"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:background="@color/greensea"
|
||||
android:gravity="center"
|
||||
android:text="Replace"
|
||||
@@ -50,9 +56,11 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/new_chain_command"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:background="@color/nephritis"
|
||||
android:gravity="center"
|
||||
android:text="New chain"
|
||||
@@ -60,29 +68,23 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/new_root_command"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:background="@color/belizehole"
|
||||
android:gravity="center"
|
||||
android:text="New root"
|
||||
android:textSize="28sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/back_with_message_command"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/alizarin"
|
||||
android:gravity="center"
|
||||
android:text="Back with message"
|
||||
android:textSize="28sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/forward_delay_command"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:background="@color/carrot"
|
||||
android:gravity="center"
|
||||
android:text="Forward with 5 sec delay"
|
||||
@@ -90,13 +92,27 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/back_to_command"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:background="@color/sunflower"
|
||||
android:gravity="center"
|
||||
android:text="Back to '3'"
|
||||
android:textSize="28sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/finish_chain_command"
|
||||
android:layout_width="0dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_rowWeight="1"
|
||||
android:background="@color/greensea"
|
||||
android:gravity="center"
|
||||
android:text="Finish chain"
|
||||
android:textSize="28sp"/>
|
||||
|
||||
</GridLayout>
|
||||
</LinearLayout>
|
||||