Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bec83313c7 | |||
| d3398ae8e6 | |||
| 12e925cbec | |||
| 3e1d0fba75 | |||
| a8bf9a331f | |||
| 2862752da9 | |||
| ce90bbf617 | |||
| 237be41c07 | |||
| 5f1d9eb039 | |||
| 920868c1f2 | |||
| ebcbf503cf | |||
| af338d04b9 | |||
| 50eafba93a | |||
| 30c284b5a2 | |||
| 771f837e64 | |||
| ecb8b1a430 | |||
| 2836c63126 | |||
| de7422144b | |||
| b044d560f2 | |||
| 39d9657c8c | |||
| 5033949e48 | |||
| 60beb90e11 | |||
| 4226595a71 | |||
| ed837a0c43 | |||
| 5518c16789 | |||
| 96ae7361f8 | |||
| a7e713865a | |||
| 427592e309 | |||
| b3e32c154f | |||
| 69feb03db6 | |||
| 1505ba87af | |||
| 3dfb107a21 | |||
| 458d9b053e | |||
| 93cecdee1d | |||
| 457c70e026 | |||
| e88b08d8ce | |||
| 4e896d3631 | |||
| a5404b0939 | |||
| 4d096351cc |
@@ -1,31 +1,36 @@
|
||||
# Cicerone
|
||||
[](https://bintray.com/terrakok/terramaven/cicerone/_latestVersion)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://android-arsenal.com/details/1/4700)
|
||||
[](http://androidweekly.net/issues/issue-250)
|
||||
[](https://t.me/Cicerone_ENG)
|
||||
[](https://t.me/Cicerone_RUS)
|
||||
|
||||
Cicerone (a guide who gives information to sightseers) is a lightweight library that makes the navigation in an Android app easy.
|
||||
It designed for using with MVP architecture (try [Moxy](https://github.com/Arello-Mobile/Moxy)), but it fits to work in other ways.
|
||||

|
||||
|
||||
Cicerone (a guide, one who conducts sightseers) is a lightweight library that makes the navigation in an Android app easy.
|
||||
It was designed to be used with the MVP pattern (try [Moxy](https://github.com/Arello-Mobile/Moxy)), but will work great with any architecture.
|
||||
|
||||
[Russian version readme](https://github.com/terrakok/Cicerone/blob/develop/README_RUS.md)
|
||||
|
||||
## Main advantages
|
||||
+ not tied to Fragments
|
||||
+ not framework
|
||||
+ is not tied to Fragments
|
||||
+ not a framework
|
||||
+ short navigation calls (no builders)
|
||||
+ lifecycle-safely!
|
||||
+ functional is simple to extent
|
||||
+ adapted for Unit Testing
|
||||
+ lifecycle-safe!
|
||||
+ functionality is simple to extend
|
||||
+ suitable for Unit Testing
|
||||
|
||||
## How to connect?
|
||||
Add the following lines to build.gradle:
|
||||
## How to add
|
||||
Add the dependency in your build.gradle:
|
||||
```groovy
|
||||
repositories {
|
||||
maven {
|
||||
url 'https://dl.bintray.com/terrakok/terramaven/'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
//Cicerone
|
||||
compile 'ru.terrakok.cicerone:cicerone:1.0'
|
||||
compile 'ru.terrakok.cicerone:cicerone:X.X'
|
||||
}
|
||||
```
|
||||
And initialise library for example with application:
|
||||
|
||||
Initialize the library (for example in your Application class):
|
||||
```java
|
||||
public class SampleApplication extends MvpApplication {
|
||||
public static SampleApplication INSTANCE;
|
||||
@@ -76,10 +81,11 @@ public class SamplePresenter extends Presenter<SampleView> {
|
||||
}
|
||||
```
|
||||
|
||||
Router converts the navigation calls to Comand sets and sends them to CommandBuffer.
|
||||
Command Buffer checks whether there _"active"_ Navigator.
|
||||
If yes, it caused the necessary commands for the requested transfer.
|
||||
If not, the command added to the queue, which will be applied as soon as _"active"_ Navigator.
|
||||
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.
|
||||
|
||||
```java
|
||||
protected void executeCommand(Command command) {
|
||||
@@ -91,8 +97,8 @@ protected void executeCommand(Command command) {
|
||||
}
|
||||
```
|
||||
|
||||
Navigator - implements the navigation commands, e.g. anonymous class inside the Activity.
|
||||
Activity provides Navigator for CommandBuffer in _onResume_ and remove 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_.
|
||||
|
||||
```java
|
||||
@Override
|
||||
@@ -110,27 +116,27 @@ protected void onPause() {
|
||||
private Navigator navigator = new Navigator() {
|
||||
@Override
|
||||
public void applyCommand(Command command) {
|
||||
//implements commands logic
|
||||
//implement commands logic
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Navigation commands
|
||||
These command set will fulfill needs of the most application. But if you require more - supply your own!
|
||||
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 from the screens chain
|
||||
+ Back - Rolls back the last transition
|
||||

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

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

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

|
||||
|
||||
## Ready navigators
|
||||
The library provides ready navigators for _Activity_.
|
||||
To use them, just give the container and pass _FragmentManager_.
|
||||
## 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.
|
||||
```java
|
||||
private Navigator navigator = new SupportFragmentNavigator(
|
||||
getSupportFragmentManager(), R.id.main_container) {
|
||||
@@ -151,24 +157,35 @@ private Navigator navigator = new SupportFragmentNavigator(
|
||||
};
|
||||
```
|
||||
## Sample
|
||||
Library usage examples, ready navigators and more can be found in the sample application.
|
||||
To see how to add, initialize and use the library and predefined navigators check out the sample.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Participants
|
||||
+ idea and realization - Konstantin Tckhovrebov (@terrakok)
|
||||
+ architectural advice, documentation and publication - Vasily Chirvon (@Jeevuz)
|
||||
+ idea and code - Konstantin Tskhovrebov (@terrakok)
|
||||
+ architecture advice, documentation and publication - Vasili Chyrvon (@Jeevuz)
|
||||
|
||||
## License
|
||||
```
|
||||
The MIT License (MIT)
|
||||
|
||||
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
|
||||
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:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
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.
|
||||
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.
|
||||
```
|
||||
|
||||
@@ -12,17 +12,11 @@ Cicerone (_"чи-че-ро́-не"_ - устар. гид) - легкая биб
|
||||
+ приспособлена для Unit тестов
|
||||
|
||||
## Как подключить?
|
||||
Добавьте в build.gradle следующие строки:
|
||||
Добавьте в build.gradle зависимость:
|
||||
```groovy
|
||||
repositories {
|
||||
maven {
|
||||
url 'https://dl.bintray.com/terrakok/terramaven/'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
//Cicerone
|
||||
compile 'ru.terrakok.cicerone:cicerone:1.0'
|
||||
compile 'ru.terrakok.cicerone:cicerone:X.X'
|
||||
}
|
||||
```
|
||||
И инициализируйте библиотеку, например, так:
|
||||
@@ -157,6 +151,8 @@ private Navigator navigator = new SupportFragmentNavigator(
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Участники
|
||||
+ идея и реализация - Константин Цховребов (@terrakok)
|
||||
+ архитектурные советы, документация и публикация - Василий Чирвон (@Jeevuz)
|
||||
|
||||
@@ -5,7 +5,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.2.2'
|
||||
classpath 'com.android.tools.build:gradle:2.3.0'
|
||||
|
||||
// For the library uploading to the Bintray
|
||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.1'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Tue Sep 06 14:31:17 MSK 2016
|
||||
#Fri Mar 10 17:09:31 MSK 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
|
||||
|
||||
@@ -6,8 +6,7 @@ sourceCompatibility = JavaVersion.VERSION_1_7
|
||||
targetCompatibility = JavaVersion.VERSION_1_7
|
||||
|
||||
dependencies {
|
||||
compileOnly 'com.google.android:android:4.0.1.2'
|
||||
compileOnly project(':stub-appcompat')
|
||||
compileOnly project(':stub-android')
|
||||
}
|
||||
|
||||
ext {
|
||||
@@ -16,9 +15,9 @@ ext {
|
||||
bintrayName = 'cicerone'
|
||||
publishedGroupId = 'ru.terrakok.cicerone'
|
||||
artifact = 'cicerone'
|
||||
libraryVersion = '1.0'
|
||||
libraryVersion = '1.2'
|
||||
gitUrl = 'https://github.com/terrakok/Cicerone'
|
||||
allLicenses = ['Apache-2.0']
|
||||
allLicenses = ['MIT']
|
||||
}
|
||||
|
||||
// Configuration of the library uploading to the Bintray
|
||||
|
||||
@@ -120,6 +120,15 @@ public class Router extends BaseRouter {
|
||||
executeCommand(new BackTo(screenKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all screens from the chain and exit.
|
||||
* It's mostly used to finish the application or close a supplementary navigation chain.
|
||||
*/
|
||||
public void finishChain() {
|
||||
executeCommand(new BackTo(null));
|
||||
executeCommand(new Back());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return to the previous screen in the chain.
|
||||
* Behavior in the case when the current screen is the root depends on
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package ru.terrakok.cicerone.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.FragmentManager;
|
||||
import android.content.Intent;
|
||||
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
|
||||
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) {
|
||||
activity.startActivity(activityIntent);
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (command instanceof Replace) {
|
||||
Replace replace = (Replace) command;
|
||||
Intent activityIntent = createActivityIntent(replace.getScreenKey(), replace.getTransitionData());
|
||||
|
||||
// Replace activity
|
||||
if (activityIntent != null) {
|
||||
activity.startActivity(activityIntent);
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -33,8 +33,9 @@ public abstract class FragmentNavigator implements Navigator {
|
||||
|
||||
/**
|
||||
* Creates FragmentNavigator.
|
||||
*
|
||||
* @param fragmentManager fragment manager
|
||||
* @param containerId id of the fragments container layout
|
||||
* @param containerId id of the fragments container layout
|
||||
*/
|
||||
public FragmentNavigator(FragmentManager fragmentManager, int containerId) {
|
||||
this.fragmentManager = fragmentManager;
|
||||
@@ -45,9 +46,14 @@ public abstract class FragmentNavigator implements Navigator {
|
||||
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;
|
||||
}
|
||||
fragmentManager
|
||||
.beginTransaction()
|
||||
.replace(containerId, createFragment(forward.getScreenKey(), forward.getTransitionData()))
|
||||
.replace(containerId, fragment)
|
||||
.addToBackStack(forward.getScreenKey())
|
||||
.commit();
|
||||
} else if (command instanceof Back) {
|
||||
@@ -58,17 +64,22 @@ public abstract class FragmentNavigator implements Navigator {
|
||||
}
|
||||
} 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();
|
||||
fragmentManager
|
||||
.beginTransaction()
|
||||
.replace(containerId, createFragment(replace.getScreenKey(), replace.getTransitionData()))
|
||||
.replace(containerId, fragment)
|
||||
.addToBackStack(replace.getScreenKey())
|
||||
.commit();
|
||||
} else {
|
||||
fragmentManager
|
||||
.beginTransaction()
|
||||
.replace(containerId, createFragment(replace.getScreenKey(), replace.getTransitionData()))
|
||||
.replace(containerId, fragment)
|
||||
.commit();
|
||||
}
|
||||
} else if (command instanceof BackTo) {
|
||||
@@ -103,14 +114,16 @@ public abstract class FragmentNavigator implements Navigator {
|
||||
|
||||
/**
|
||||
* Creates Fragment matching {@code screenKey}.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param data initialization data
|
||||
* @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);
|
||||
@@ -126,4 +139,11 @@ public abstract class FragmentNavigator implements Navigator {
|
||||
protected void backToUnexisting() {
|
||||
backToRoot();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called if we can't create a screen.
|
||||
*/
|
||||
protected void unknownScreen(Command command) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package ru.terrakok.cicerone.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
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
|
||||
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) {
|
||||
activity.startActivity(activityIntent);
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (command instanceof Replace) {
|
||||
Replace replace = (Replace) command;
|
||||
Intent activityIntent = createActivityIntent(replace.getScreenKey(), replace.getTransitionData());
|
||||
|
||||
// Replace activity
|
||||
if (activityIntent != null) {
|
||||
activity.startActivity(activityIntent);
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -33,8 +33,9 @@ public abstract class SupportFragmentNavigator implements Navigator {
|
||||
|
||||
/**
|
||||
* Creates SupportFragmentNavigator.
|
||||
*
|
||||
* @param fragmentManager support fragment manager
|
||||
* @param containerId id of the fragments container layout
|
||||
* @param containerId id of the fragments container layout
|
||||
*/
|
||||
public SupportFragmentNavigator(FragmentManager fragmentManager, int containerId) {
|
||||
this.fragmentManager = fragmentManager;
|
||||
@@ -45,9 +46,14 @@ public abstract class SupportFragmentNavigator implements Navigator {
|
||||
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;
|
||||
}
|
||||
fragmentManager
|
||||
.beginTransaction()
|
||||
.replace(containerId, createFragment(forward.getScreenKey(), forward.getTransitionData()))
|
||||
.replace(containerId, fragment)
|
||||
.addToBackStack(forward.getScreenKey())
|
||||
.commit();
|
||||
} else if (command instanceof Back) {
|
||||
@@ -58,17 +64,22 @@ public abstract class SupportFragmentNavigator implements Navigator {
|
||||
}
|
||||
} 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();
|
||||
fragmentManager
|
||||
.beginTransaction()
|
||||
.replace(containerId, createFragment(replace.getScreenKey(), replace.getTransitionData()))
|
||||
.replace(containerId, fragment)
|
||||
.addToBackStack(replace.getScreenKey())
|
||||
.commit();
|
||||
} else {
|
||||
fragmentManager
|
||||
.beginTransaction()
|
||||
.replace(containerId, createFragment(replace.getScreenKey(), replace.getTransitionData()))
|
||||
.replace(containerId, fragment)
|
||||
.commit();
|
||||
}
|
||||
} else if (command instanceof BackTo) {
|
||||
@@ -103,14 +114,16 @@ public abstract class SupportFragmentNavigator implements Navigator {
|
||||
|
||||
/**
|
||||
* Creates Fragment matching {@code screenKey}.
|
||||
*
|
||||
* @param screenKey screen key
|
||||
* @param data initialization data
|
||||
* @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);
|
||||
@@ -126,4 +139,10 @@ public abstract class SupportFragmentNavigator implements Navigator {
|
||||
protected void backToUnexisting() {
|
||||
backToRoot();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called if we can't create a screen.
|
||||
*/
|
||||
protected void unknownScreen(Command command) {
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,3 @@ apply plugin: 'java'
|
||||
|
||||
sourceCompatibility = JavaVersion.VERSION_1_7
|
||||
targetCompatibility = JavaVersion.VERSION_1_7
|
||||
|
||||
dependencies {
|
||||
compileOnly 'com.google.android:android:4.0.1.2'
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package android.app;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
/***
|
||||
* Created by laomo on 2016-11-21.
|
||||
*/
|
||||
public class Activity extends Context {
|
||||
public void startActivity(Intent intent) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public FragmentManager getFragmentManager() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public void finish() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
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!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package android.app;
|
||||
|
||||
/***
|
||||
* Created by laomo on 2016-11-21.
|
||||
*/
|
||||
public class FragmentManager {
|
||||
|
||||
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 interface BackStackEntry {
|
||||
int getId();
|
||||
|
||||
String getName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
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!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package android.content;
|
||||
|
||||
/**
|
||||
* @author Konstantin Tskhovrebov (aka terrakok). Date: 10.03.17
|
||||
*/
|
||||
|
||||
public class Context {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package android.content;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 22.02.17
|
||||
*/
|
||||
|
||||
public class Intent {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package android.os;
|
||||
|
||||
/***
|
||||
* Created by laomo on 2016-11-21.
|
||||
*/
|
||||
public class Bundle {
|
||||
}
|
||||
@@ -8,4 +8,7 @@ import android.app.Activity;
|
||||
*/
|
||||
|
||||
public class FragmentActivity extends Activity {
|
||||
public FragmentManager getSupportFragmentManager() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
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!");
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,12 @@ repositories {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 24
|
||||
buildToolsVersion '24'
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion '25.0.2'
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 24
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 25
|
||||
versionCode 1
|
||||
versionName "1.0.0"
|
||||
applicationId "ru.terrakok.cicerone.sample"
|
||||
@@ -28,20 +28,30 @@ android {
|
||||
}
|
||||
|
||||
ext {
|
||||
supportLibraryVersion = "24.2.1"
|
||||
moxyVersion = "1.0.2"
|
||||
supportLibraryVersion = "25.3.0"
|
||||
moxyVersion = "1.4.6"
|
||||
daggerVersion = "2.10"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Support libraries
|
||||
compile "com.android.support:appcompat-v7:$supportLibraryVersion"
|
||||
compile "com.android.support:design:$supportLibraryVersion"
|
||||
|
||||
//MVP Moxy
|
||||
compile "com.arello-mobile:moxy:$moxyVersion"
|
||||
compile "com.arello-mobile:moxy-android:$moxyVersion"
|
||||
compile "com.arello-mobile:moxy-app-compat:$moxyVersion"
|
||||
provided "com.arello-mobile:moxy-compiler:$moxyVersion"
|
||||
|
||||
//Cicerone
|
||||
compile project(':library')
|
||||
|
||||
//DI
|
||||
compile "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') {
|
||||
exclude group: "com.android.support", module: "design"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,17 +5,20 @@
|
||||
|
||||
<application
|
||||
android:name=".SampleApplication"
|
||||
android:allowBackup="false"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:theme="@style/AppTheme"
|
||||
android:label="@string/app_name">
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<activity
|
||||
android:name=".ui.main.MainActivity">
|
||||
android:name=".ui.start.StartActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".ui.main.MainActivity"/>
|
||||
<activity android:name=".ui.bottom.BottomNavigationActivity"/>
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -1,37 +1,29 @@
|
||||
package ru.terrakok.cicerone.sample;
|
||||
|
||||
import com.arellomobile.mvp.MvpApplication;
|
||||
import android.app.Application;
|
||||
|
||||
import ru.terrakok.cicerone.Cicerone;
|
||||
import ru.terrakok.cicerone.NavigatorHolder;
|
||||
import ru.terrakok.cicerone.Router;
|
||||
import ru.terrakok.cicerone.sample.dagger.AppComponent;
|
||||
import ru.terrakok.cicerone.sample.dagger.DaggerAppComponent;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
*/
|
||||
|
||||
public class SampleApplication extends MvpApplication {
|
||||
public class SampleApplication extends Application {
|
||||
public static SampleApplication INSTANCE;
|
||||
private Cicerone<Router> cicerone;
|
||||
private AppComponent appComponent;
|
||||
|
||||
@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();
|
||||
public AppComponent getAppComponent() {
|
||||
if (appComponent == null) {
|
||||
appComponent = DaggerAppComponent.builder().build();
|
||||
}
|
||||
return appComponent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,4 +7,15 @@ package ru.terrakok.cicerone.sample;
|
||||
|
||||
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 String BOTTOM_NAVIGATION_ACTIVITY_SCREEN = "bna screen";
|
||||
|
||||
public static final String ANDROID_SCREEN = "android screen";
|
||||
public static final String BUG_SCREEN = "bug screen";
|
||||
public static final String DOG_SCREEN = "dog screen";
|
||||
|
||||
public static final String FORWARD_SCREEN = "forward screen";
|
||||
public static final String GITHUB_SCREEN = "github screen";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package ru.terrakok.cicerone.sample.dagger;
|
||||
|
||||
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.ui.bottom.BottomNavigationActivity;
|
||||
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 terrakok 24.11.16
|
||||
*/
|
||||
|
||||
@Singleton
|
||||
@Component(modules = {
|
||||
NavigationModule.class,
|
||||
LocalNavigationModule.class
|
||||
})
|
||||
public interface AppComponent {
|
||||
|
||||
void inject(StartActivity activity);
|
||||
|
||||
void inject(MainActivity activity);
|
||||
|
||||
void inject(SampleFragment fragment);
|
||||
|
||||
void inject(BottomNavigationActivity activity);
|
||||
|
||||
void inject(TabContainerFragment fragment);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package ru.terrakok.cicerone.sample.dagger.module;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import ru.terrakok.cicerone.sample.subnavigation.LocalCiceroneHolder;
|
||||
|
||||
/**
|
||||
* Created by terrakok 24.11.16
|
||||
*/
|
||||
|
||||
@Module
|
||||
public class LocalNavigationModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
LocalCiceroneHolder provideLocalNavigationHolder() {
|
||||
return new LocalCiceroneHolder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package ru.terrakok.cicerone.sample.dagger.module;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import ru.terrakok.cicerone.Cicerone;
|
||||
import ru.terrakok.cicerone.NavigatorHolder;
|
||||
import ru.terrakok.cicerone.Router;
|
||||
|
||||
/**
|
||||
* Created by terrakok 24.11.16
|
||||
*/
|
||||
|
||||
@Module
|
||||
public class NavigationModule {
|
||||
private Cicerone<Router> cicerone;
|
||||
|
||||
public NavigationModule() {
|
||||
cicerone = Cicerone.create();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Router provideRouter() {
|
||||
return cicerone.getRouter();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
NavigatorHolder provideNavigatorHolder() {
|
||||
return cicerone.getNavigatorHolder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package ru.terrakok.cicerone.sample.mvp.bottom;
|
||||
|
||||
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
|
||||
*/
|
||||
@InjectViewState
|
||||
public class BottomNavigationPresenter extends MvpPresenter<BottomNavigationView> {
|
||||
private Router router;
|
||||
|
||||
public BottomNavigationPresenter(Router router) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package ru.terrakok.cicerone.sample.mvp.bottom;
|
||||
|
||||
import com.arellomobile.mvp.MvpView;
|
||||
import com.arellomobile.mvp.viewstate.strategy.AddToEndSingleStrategy;
|
||||
import com.arellomobile.mvp.viewstate.strategy.StateStrategyType;
|
||||
|
||||
/**
|
||||
* Created by terrakok 25.11.16
|
||||
*/
|
||||
@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);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package ru.terrakok.cicerone.sample.mvp.bottom.forward;
|
||||
|
||||
import com.arellomobile.mvp.InjectViewState;
|
||||
import com.arellomobile.mvp.MvpPresenter;
|
||||
|
||||
import ru.terrakok.cicerone.Router;
|
||||
import ru.terrakok.cicerone.sample.Screens;
|
||||
|
||||
/**
|
||||
* Created by terrakok 26.11.16
|
||||
*/
|
||||
|
||||
@InjectViewState
|
||||
public class ForwardPresenter extends MvpPresenter<ForwardView> {
|
||||
private Router router;
|
||||
private int number;
|
||||
|
||||
public ForwardPresenter(Router router, int number) {
|
||||
this.router = router;
|
||||
this.number = number;
|
||||
|
||||
getViewState().setChainText(createChain(number));
|
||||
}
|
||||
|
||||
private String createChain(int number) {
|
||||
String chain = "[0]";
|
||||
|
||||
for (int i = 0; i < number; i++) {
|
||||
chain += "➔" + (i + 1);
|
||||
}
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
public void onForwardPressed() {
|
||||
router.navigateTo(Screens.FORWARD_SCREEN, number + 1);
|
||||
}
|
||||
|
||||
public void onGithubPressed() {
|
||||
router.navigateTo(Screens.GITHUB_SCREEN);
|
||||
}
|
||||
|
||||
public void onBackPressed() {
|
||||
router.exit();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package ru.terrakok.cicerone.sample.mvp.bottom.forward;
|
||||
|
||||
import com.arellomobile.mvp.MvpView;
|
||||
import com.arellomobile.mvp.viewstate.strategy.AddToEndSingleStrategy;
|
||||
import com.arellomobile.mvp.viewstate.strategy.StateStrategyType;
|
||||
|
||||
/**
|
||||
* Created by terrakok 26.11.16
|
||||
*/
|
||||
|
||||
@StateStrategyType(AddToEndSingleStrategy.class)
|
||||
public interface ForwardView extends MvpView {
|
||||
void setChainText(String chainText);
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import ru.terrakok.cicerone.Router;
|
||||
import ru.terrakok.cicerone.sample.SampleApplication;
|
||||
import ru.terrakok.cicerone.sample.Screens;
|
||||
|
||||
/**
|
||||
@@ -24,18 +23,11 @@ public class SamplePresenter extends MvpPresenter<SampleView> {
|
||||
private ScheduledExecutorService executorService;
|
||||
private ScheduledFuture<?> future;
|
||||
|
||||
public SamplePresenter() {
|
||||
router = SampleApplication.INSTANCE.getRouter();
|
||||
executorService = Executors.newSingleThreadScheduledExecutor();
|
||||
}
|
||||
|
||||
public void init(int screenNumber) {
|
||||
public SamplePresenter(Router router, int screenNumber) {
|
||||
this.router = router;
|
||||
this.screenNumber = screenNumber;
|
||||
}
|
||||
executorService = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
@Override
|
||||
protected void onFirstViewAttach() {
|
||||
super.onFirstViewAttach();
|
||||
getViewState().setTitle("Screen " + screenNumber);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package ru.terrakok.cicerone.sample.mvp.start;
|
||||
|
||||
import com.arellomobile.mvp.MvpPresenter;
|
||||
|
||||
import ru.terrakok.cicerone.Router;
|
||||
import ru.terrakok.cicerone.sample.Screens;
|
||||
|
||||
/**
|
||||
* Created by terrakok 21.11.16
|
||||
*/
|
||||
public class StartActivityPresenter extends MvpPresenter<StartActivityView> {
|
||||
private Router router;
|
||||
|
||||
public StartActivityPresenter(Router router) {
|
||||
this.router = router;
|
||||
}
|
||||
|
||||
public void onOrdinaryPressed() {
|
||||
router.navigateTo(Screens.MAIN_ACTIVITY_SCREEN);
|
||||
}
|
||||
|
||||
public void onMultiPressed() {
|
||||
router.navigateTo(Screens.BOTTOM_NAVIGATION_ACTIVITY_SCREEN);
|
||||
}
|
||||
|
||||
public void onBackPressed() {
|
||||
router.exit();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package ru.terrakok.cicerone.sample.mvp.start;
|
||||
|
||||
import com.arellomobile.mvp.MvpView;
|
||||
|
||||
/**
|
||||
* Created by terrakok 21.11.16
|
||||
*/
|
||||
public interface StartActivityView extends MvpView {
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package ru.terrakok.cicerone.sample.subnavigation;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import ru.terrakok.cicerone.Cicerone;
|
||||
import ru.terrakok.cicerone.Router;
|
||||
|
||||
/**
|
||||
* Created by terrakok 27.11.16
|
||||
*/
|
||||
public class LocalCiceroneHolder {
|
||||
private HashMap<String, Cicerone<Router>> containers;
|
||||
|
||||
public LocalCiceroneHolder() {
|
||||
containers = new HashMap<>();
|
||||
}
|
||||
|
||||
public Cicerone<Router> getCicerone(String containerTag) {
|
||||
if (!containers.containsKey(containerTag)) {
|
||||
containers.put(containerTag, Cicerone.create());
|
||||
}
|
||||
return containers.get(containerTag);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
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 com.arellomobile.mvp.MvpAppCompatActivity;
|
||||
import com.arellomobile.mvp.presenter.InjectPresenter;
|
||||
import com.arellomobile.mvp.presenter.ProvidePresenter;
|
||||
import com.ashokvarma.bottomnavigation.BottomNavigationBar;
|
||||
import com.ashokvarma.bottomnavigation.BottomNavigationItem;
|
||||
|
||||
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;
|
||||
import ru.terrakok.cicerone.sample.mvp.bottom.BottomNavigationPresenter;
|
||||
import ru.terrakok.cicerone.sample.mvp.bottom.BottomNavigationView;
|
||||
import ru.terrakok.cicerone.sample.ui.common.BackButtonListener;
|
||||
import ru.terrakok.cicerone.sample.ui.common.RouterProvider;
|
||||
|
||||
/**
|
||||
* Created by terrakok 25.11.16
|
||||
*/
|
||||
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;
|
||||
|
||||
@ProvidePresenter
|
||||
public BottomNavigationPresenter createBottomNavigationPresenter() {
|
||||
return new BottomNavigationPresenter(router);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
SampleApplication.INSTANCE.getAppComponent().inject(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_bottom);
|
||||
bottomNavigationBar = (BottomNavigationBar) findViewById(R.id.ab_bottom_navigation_bar);
|
||||
|
||||
initViews();
|
||||
initContainers();
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
bottomNavigationBar.selectTab(ANDROID_TAB_POSITION, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
bottomNavigationBar
|
||||
.addItem(new BottomNavigationItem(R.drawable.ic_android_white_24dp, R.string.tab_android))
|
||||
.addItem(new BottomNavigationItem(R.drawable.ic_bug_report_white_24dp, R.string.tab_bug))
|
||||
.addItem(new BottomNavigationItem(R.drawable.ic_pets_white_24dp, R.string.tab_dog))
|
||||
.initialise();
|
||||
bottomNavigationBar.setTabSelectedListener(new BottomNavigationBar.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(int position) {
|
||||
switch (position) {
|
||||
case ANDROID_TAB_POSITION:
|
||||
presenter.onTabAndroidClick();
|
||||
break;
|
||||
case BUG_TAB_POSITION:
|
||||
presenter.onTabBugClick();
|
||||
break;
|
||||
case DOG_TAB_POSITION:
|
||||
presenter.onTabDogClick();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(int position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(int position) {
|
||||
onTabSelected(position);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void initContainers() {
|
||||
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();
|
||||
}
|
||||
|
||||
bugTabFragment = (TabContainerFragment) fm.findFragmentByTag("BUG");
|
||||
if (bugTabFragment == null) {
|
||||
bugTabFragment = TabContainerFragment.getNewInstance("BUG");
|
||||
fm.beginTransaction()
|
||||
.add(R.id.ab_container, bugTabFragment, "BUG")
|
||||
.detach(bugTabFragment).commitNow();
|
||||
}
|
||||
|
||||
dogTabFragment = (TabContainerFragment) fm.findFragmentByTag("DOG");
|
||||
if (dogTabFragment == null) {
|
||||
dogTabFragment = TabContainerFragment.getNewInstance("DOG");
|
||||
fm.beginTransaction()
|
||||
.add(R.id.ab_container, dogTabFragment, "DOG")
|
||||
.detach(dogTabFragment).commitNow();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
navigatorHolder.setNavigator(navigator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
navigatorHolder.removeNavigator();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.ab_container);
|
||||
if (fragment != null
|
||||
&& fragment instanceof BackButtonListener
|
||||
&& ((BackButtonListener) fragment).onBackPressed()) {
|
||||
return;
|
||||
} else {
|
||||
presenter.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package ru.terrakok.cicerone.sample.ui.bottom;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.arellomobile.mvp.MvpAppCompatFragment;
|
||||
import com.arellomobile.mvp.presenter.InjectPresenter;
|
||||
import com.arellomobile.mvp.presenter.ProvidePresenter;
|
||||
|
||||
import ru.terrakok.cicerone.sample.R;
|
||||
import ru.terrakok.cicerone.sample.mvp.bottom.forward.ForwardPresenter;
|
||||
import ru.terrakok.cicerone.sample.mvp.bottom.forward.ForwardView;
|
||||
import ru.terrakok.cicerone.sample.ui.common.BackButtonListener;
|
||||
import ru.terrakok.cicerone.sample.ui.common.RouterProvider;
|
||||
|
||||
/**
|
||||
* Created by terrakok 26.11.16
|
||||
*/
|
||||
public class ForwardFragment extends MvpAppCompatFragment implements ForwardView, BackButtonListener {
|
||||
private static final String EXTRA_NAME = "extra_name";
|
||||
private static final String EXTRA_NUMBER = "extra_number";
|
||||
|
||||
private Toolbar toolbar;
|
||||
private TextView chainTV;
|
||||
private View forwardBt;
|
||||
private View githubBt;
|
||||
|
||||
@InjectPresenter
|
||||
ForwardPresenter presenter;
|
||||
|
||||
@ProvidePresenter
|
||||
ForwardPresenter provideForwardPresenter() {
|
||||
return new ForwardPresenter(
|
||||
((RouterProvider) getParentFragment()).getRouter(),
|
||||
getArguments().getInt(EXTRA_NUMBER)
|
||||
);
|
||||
}
|
||||
|
||||
public static ForwardFragment getNewInstance(String name, int number) {
|
||||
ForwardFragment fragment = new ForwardFragment();
|
||||
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString(EXTRA_NAME, name);
|
||||
arguments.putInt(EXTRA_NUMBER, number);
|
||||
fragment.setArguments(arguments);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_forward, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
toolbar = (Toolbar) view.findViewById(R.id.toolbar);
|
||||
chainTV = (TextView) view.findViewById(R.id.chain_text);
|
||||
forwardBt = view.findViewById(R.id.forward_button);
|
||||
githubBt = view.findViewById(R.id.github_button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
toolbar.setTitle(getArguments().getString(EXTRA_NAME));
|
||||
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
presenter.onBackPressed();
|
||||
}
|
||||
});
|
||||
forwardBt.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
presenter.onForwardPressed();
|
||||
}
|
||||
});
|
||||
githubBt.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
presenter.onGithubPressed();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChainText(String chainText) {
|
||||
chainTV.setText(chainText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed() {
|
||||
presenter.onBackPressed();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
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;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
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.sample.R;
|
||||
import ru.terrakok.cicerone.sample.SampleApplication;
|
||||
import ru.terrakok.cicerone.sample.Screens;
|
||||
import ru.terrakok.cicerone.sample.subnavigation.LocalCiceroneHolder;
|
||||
import ru.terrakok.cicerone.sample.ui.common.BackButtonListener;
|
||||
import ru.terrakok.cicerone.sample.ui.common.RouterProvider;
|
||||
|
||||
/**
|
||||
* Created by terrakok 25.11.16
|
||||
*/
|
||||
public class TabContainerFragment extends Fragment implements RouterProvider, BackButtonListener {
|
||||
private static final String EXTRA_NAME = "tcf_extra_name";
|
||||
|
||||
private Navigator navigator;
|
||||
|
||||
@Inject
|
||||
LocalCiceroneHolder ciceroneHolder;
|
||||
|
||||
public static TabContainerFragment getNewInstance(String name) {
|
||||
TabContainerFragment fragment = new TabContainerFragment();
|
||||
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString(EXTRA_NAME, name);
|
||||
fragment.setArguments(arguments);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
private String getContainerName() {
|
||||
return getArguments().getString(EXTRA_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
SampleApplication.INSTANCE.getAppComponent().inject(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
private Cicerone<Router> getCicerone() {
|
||||
return ciceroneHolder.getCicerone(getContainerName());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_tab_container, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
if (getChildFragmentManager().findFragmentById(R.id.ftc_container) == null) {
|
||||
getCicerone().getRouter().replaceScreen(Screens.FORWARD_SCREEN, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getCicerone().getNavigatorHolder().setNavigator(getNavigator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
getCicerone().getNavigatorHolder().removeNavigator();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
};
|
||||
}
|
||||
return navigator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Router getRouter() {
|
||||
return getCicerone().getRouter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed() {
|
||||
Fragment fragment = getChildFragmentManager().findFragmentById(R.id.ftc_container);
|
||||
if (fragment != null
|
||||
&& fragment instanceof BackButtonListener
|
||||
&& ((BackButtonListener) fragment).onBackPressed()) {
|
||||
return true;
|
||||
} else {
|
||||
((RouterProvider) getActivity()).getRouter().exit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package ru.terrakok.cicerone.sample.ui.common;
|
||||
|
||||
/**
|
||||
* Created by terrakok 26.11.16
|
||||
*/
|
||||
public interface BackButtonListener {
|
||||
boolean onBackPressed();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package ru.terrakok.cicerone.sample.ui.common;
|
||||
|
||||
import ru.terrakok.cicerone.Router;
|
||||
|
||||
/**
|
||||
* Created by terrakok 25.11.16
|
||||
*/
|
||||
public interface RouterProvider {
|
||||
Router getRouter();
|
||||
}
|
||||
@@ -12,7 +12,10 @@ import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
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;
|
||||
@@ -22,6 +25,7 @@ import ru.terrakok.cicerone.commands.Replace;
|
||||
import ru.terrakok.cicerone.sample.R;
|
||||
import ru.terrakok.cicerone.sample.SampleApplication;
|
||||
import ru.terrakok.cicerone.sample.Screens;
|
||||
import ru.terrakok.cicerone.sample.ui.common.BackButtonListener;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
@@ -30,9 +34,13 @@ import ru.terrakok.cicerone.sample.Screens;
|
||||
|
||||
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) {
|
||||
@Override
|
||||
protected Fragment createFragment(String screenKey, Object data) {
|
||||
@@ -58,7 +66,9 @@ public class MainActivity extends MvpAppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
SampleApplication.INSTANCE.getAppComponent().inject(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
screensSchemeTV = (TextView) findViewById(R.id.screens_scheme);
|
||||
|
||||
@@ -73,20 +83,22 @@ public class MainActivity extends MvpAppCompatActivity {
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
SampleApplication.INSTANCE.getNavigatorHolder().setNavigator(navigator);
|
||||
navigatorHolder.setNavigator(navigator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
navigatorHolder.removeNavigator();
|
||||
super.onPause();
|
||||
SampleApplication.INSTANCE.getNavigatorHolder().removeNavigator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_container);
|
||||
if (fragment != null && fragment instanceof SampleFragment) {
|
||||
((SampleFragment) fragment).onBackPressed();
|
||||
if (fragment != null
|
||||
&& fragment instanceof BackButtonListener
|
||||
&& ((BackButtonListener) fragment).onBackPressed()) {
|
||||
return;
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@@ -9,17 +9,23 @@ import android.view.ViewGroup;
|
||||
|
||||
import com.arellomobile.mvp.MvpAppCompatFragment;
|
||||
import com.arellomobile.mvp.presenter.InjectPresenter;
|
||||
import com.arellomobile.mvp.presenter.ProvidePresenter;
|
||||
|
||||
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.main.SamplePresenter;
|
||||
import ru.terrakok.cicerone.sample.mvp.main.SampleView;
|
||||
import ru.terrakok.cicerone.sample.ui.common.BackButtonListener;
|
||||
|
||||
/**
|
||||
* Created by Konstantin Tckhovrebov (aka @terrakok)
|
||||
* on 11.10.16
|
||||
*/
|
||||
|
||||
public class SampleFragment extends MvpAppCompatFragment implements SampleView {
|
||||
public class SampleFragment extends MvpAppCompatFragment implements SampleView, BackButtonListener {
|
||||
private static final String EXTRA_NUMBER = "extra_number";
|
||||
|
||||
private Toolbar toolbar;
|
||||
@@ -32,9 +38,17 @@ public class SampleFragment extends MvpAppCompatFragment implements SampleView {
|
||||
private View forwardWithDelayCommandBt;
|
||||
private View backToCommandBt;
|
||||
|
||||
@Inject
|
||||
Router router;
|
||||
|
||||
@InjectPresenter
|
||||
SamplePresenter presenter;
|
||||
|
||||
@ProvidePresenter
|
||||
public SamplePresenter createSamplePresenter() {
|
||||
return new SamplePresenter(router, getArguments().getInt(EXTRA_NUMBER));
|
||||
}
|
||||
|
||||
public static SampleFragment getNewInstance(int number) {
|
||||
SampleFragment fragment = new SampleFragment();
|
||||
|
||||
@@ -47,8 +61,8 @@ public class SampleFragment extends MvpAppCompatFragment implements SampleView {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
SampleApplication.INSTANCE.getAppComponent().inject(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
presenter.init(getArguments().getInt(EXTRA_NUMBER));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -135,7 +149,8 @@ public class SampleFragment extends MvpAppCompatFragment implements SampleView {
|
||||
toolbar.setTitle(title);
|
||||
}
|
||||
|
||||
public void onBackPressed() {
|
||||
public boolean onBackPressed() {
|
||||
presenter.onBackCommandClick();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
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;
|
||||
import com.arellomobile.mvp.presenter.ProvidePresenter;
|
||||
|
||||
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.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.bottom.BottomNavigationActivity;
|
||||
import ru.terrakok.cicerone.sample.ui.main.MainActivity;
|
||||
|
||||
/**
|
||||
* Created by terrakok 21.11.16
|
||||
*/
|
||||
public class StartActivity extends MvpAppCompatActivity implements StartActivityView {
|
||||
@Inject
|
||||
Router router;
|
||||
|
||||
@Inject
|
||||
NavigatorHolder navigatorHolder;
|
||||
|
||||
@InjectPresenter
|
||||
StartActivityPresenter presenter;
|
||||
|
||||
@ProvidePresenter
|
||||
public StartActivityPresenter createStartActivityPresenter() {
|
||||
return new StartActivityPresenter(router);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
SampleApplication.INSTANCE.getAppComponent().inject(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_start);
|
||||
initViews();
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
findViewById(R.id.ordinary_nav_button).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
presenter.onOrdinaryPressed();
|
||||
}
|
||||
});
|
||||
findViewById(R.id.multi_nav_button).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
presenter.onMultiPressed();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
navigatorHolder.setNavigator(navigator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
navigatorHolder.removeNavigator();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
presenter.onBackPressed();
|
||||
}
|
||||
|
||||
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;
|
||||
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:
|
||||
forward(new Forward(command.getScreenKey(), command.getTransitionData()));
|
||||
finish();
|
||||
break;
|
||||
default:
|
||||
Log.e("Cicerone", "Unknown screen: " + command.getScreenKey());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void back() {
|
||||
finish();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
After Width: | Height: | Size: 416 B |
|
After Width: | Height: | Size: 307 B |
|
After Width: | Height: | Size: 557 B |
|
After Width: | Height: | Size: 247 B |
|
After Width: | Height: | Size: 233 B |
|
After Width: | Height: | Size: 364 B |
|
After Width: | Height: | Size: 434 B |
|
After Width: | Height: | Size: 371 B |
|
After Width: | Height: | Size: 537 B |
|
After Width: | Height: | Size: 681 B |
|
After Width: | Height: | Size: 576 B |
|
After Width: | Height: | Size: 1009 B |
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/ab_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<com.ashokvarma.bottomnavigation.BottomNavigationBar
|
||||
android:id="@+id/ab_bottom_navigation_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v4.widget.Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:text="@string/cicerone_description"
|
||||
android:textSize="18sp"/>
|
||||
|
||||
<android.support.v4.widget.Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/ordinary_nav_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:text="@string/ordinary_nav"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/multi_nav_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:text="@string/multi_nav"/>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="@color/primary"
|
||||
app:navigationIcon="@drawable/ic_arrow_back_white_24dp"
|
||||
app:title="@string/app_name"/>
|
||||
|
||||
<android.support.v4.widget.Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/chain_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="13sp"
|
||||
tools:text="1➔2➔3➔4➔2➔3➔4➔2➔3➔4➔2➔3➔4➔2➔3➔4➔2➔3➔4"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/forward_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:minWidth="100dp"
|
||||
android:text="➔"
|
||||
android:textSize="20sp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/github_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:minWidth="100dp"
|
||||
android:text="github"
|
||||
android:textSize="20sp"/>
|
||||
|
||||
<android.support.v4.widget.Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
android:id="@+id/ftc_container"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
@@ -1,3 +1,10 @@
|
||||
<resources>
|
||||
<string name="app_name">Cicerone Sample</string>
|
||||
<string name="cicerone_description">Cicerone is a lightweight library that makes the navigation in an Android app easy.</string>
|
||||
<string name="ordinary_nav">Ordinary navigation</string>
|
||||
<string name="multi_nav">Multi navigation</string>
|
||||
|
||||
<string name="tab_android">Android</string>
|
||||
<string name="tab_bug">Bug</string>
|
||||
<string name="tab_dog">Dog</string>
|
||||
</resources>
|
||||
@@ -1,2 +1,2 @@
|
||||
include ':library', ':sample', ':stub-appcompat'
|
||||
project(':stub-appcompat').projectDir = new File('library/stub-appcompat')
|
||||
include ':library', ':sample', ':stub-android'
|
||||
project(':stub-android').projectDir = new File('library/stub-android')
|
||||
|
||||