Skip to content

Instantly share code, notes, and snippets.

@zibellon
Created September 21, 2019 10:40
Show Gist options
  • Save zibellon/a69d75665454e76f74b8d678cf089517 to your computer and use it in GitHub Desktop.
Save zibellon/a69d75665454e76f74b8d678cf089517 to your computer and use it in GitHub Desktop.
Собственный координатор для управления экранами
public class CoordinatorMain {
public interface CustomBackBtnClicker {
void backClick();
}
//Класс который отвечает за навигацию в приложении
private String LOG = "CoordinatorMAIN!";
private Activity rootActivity;
//Несколько контрольных переменных
private Boolean KEYBOARD_VISIBLE = false; //Видна клавиатура или нет - ГЛОБАЛЬНО
private Boolean IS_TAB_SWITCHED = false; //Используется для показа - СМЕНИЛИ МЫ ВКЛАДКУ ИЛИ НЕТ - ДЛЯ КОРНЕВЫХ ЭКРАНОВ, ПРОБЛЕМА С КНОПКОЙ НАЗАД
private Boolean customBackBtn = false; //Переменная которая показывает нужно обработать кнопку назад как всегда или для нее есть свой метод обработки
private CustomBackBtnClicker customBackBtnClicker; //Кастомная кнопка назад - еси ее надо как то по особенному обработать в активити или фрагменте
private List<RouterTransaction> routerTransactionList;
private ViewGroup fullScreenContainer;
private ViewGroup botNavContainer;
private Router navRouter;
private Integer curSwitchIndex = 0;
private Boolean needToPopRoot = false;
private Router currentRouter; //Текущий роутер для детей()
private Router mainRouter; //Главный роутер(Для большого экрана)
private AHBottomNavigation ahBottomNavigation; //Боттом навигатион!
private static CoordinatorMain coordinatorMain;
//Инициализация координатора
public static void init() {
coordinatorMain = new CoordinatorMain();
}
//Получение координатора
public static CoordinatorMain getInstance() {
return coordinatorMain;
}
//Установка корневого активити - для кнопки назад
public void setRootActivity(@NonNull Activity rootActivity) {
this.rootActivity = rootActivity;
KeyboardVisibilityEvent.setEventListener(this.rootActivity, new KeyboardVisibilityEventListener() {
@Override
public void onVisibilityChanged(boolean isOpen) {
Log.d(LOG, "Клавиатура видна = " + isOpen);
KEYBOARD_VISIBLE = isOpen;
}
});
}
//Смена вкладки
public void switchTab(int tabIndex, boolean needToRender) {
Log.d(LOG, "Смена вкладки = " + tabIndex);
//Смотрим видна клава ли нет !
//Если она видна - то мы ее скрываем
if (KEYBOARD_VISIBLE) {
Instruments.getInstance().hideSoftKeyboard(rootActivity);
}
//Предотвращение NPE
if (navRouter == null) {
return;
}
//Смотрим на какой индекс перешли
IS_TAB_SWITCHED = tabIndex != 0;
List<RouterTransaction> backStack = navRouter.getBackstack();
int newActiveIndex = -1; //Новый активный индекс = -1(Ничего не выбрано)
int oldActiveIndex = backStack.size() - 1; //Предыдущий выбранный индекс = ПОСЛЕДНИЙ В БЭКСТЕКЕ
//бЕЖИМ ПО БЭКСТЕКУ - С ПОСЛЕДНЕГО до первого
for (int i = oldActiveIndex; i >= 0; --i) {
RouterTransaction routerTransaction = backStack.get(i); //Берем текущую транзакцию
//Если новый контроллер отличается от того который сечас
if (routerTransactionList.get(tabIndex) != null && routerTransactionList.get(tabIndex).controller() != routerTransaction.controller()) {
continue;
}
//Мы сюда попадаем только после двух проверок
if (i != oldActiveIndex) {
newActiveIndex = i;
}
break; //и сразу выброс)
}
//Если новый индекс не равен -1
//И он не равен тому на который сейчас меняем
if (newActiveIndex != -1) {
backStack.add(backStack.remove(newActiveIndex)); //Немного не понимаю
navRouter.setBackstack(backStack, null);
curSwitchIndex = tabIndex;
// currentRouter = backStack.get(backStack.size() - 1).controller().getChildRouter(); //Ставим в текущий роутер тот, который выбран в ботнаве
//Нужно какой то слушатель
// onActiveControllerChanged();
} else {
return;
}
//Видимо вот тут придется делать сохранение состояния))))
//И его восстановление
//Для боттом навигации!
//Выбираем текущий индекс боттом навигации
if (needToRender) {
ahBottomNavigation.setCurrentItem(tabIndex);
}
}
//Получение текущего активного контроллера(Навигационного)
protected Controller getNavController() {
if (navRouter == null) {
return null;
}
List<RouterTransaction> backStack = navRouter.getBackstack();
if (backStack.isEmpty()) {
return null;
}
return backStack.get(backStack.size() - 1).controller();
}
//переходи далее по роутеру(ФуллСкрин!)
public void goNext(BaseScreen screen) {
Log.d(LOG, "Переходим далее - ФуллСкрин");
mainRouter.pushController(RouterTransaction
.with(screen)
.pushChangeHandler(new FadeChangeHandler())
.popChangeHandler(new FadeChangeHandler()));
Log.d(LOG, "BackStack MAIN NEXT = " + mainRouter.getBackstack().size());
}
//Метод перехода далее с установкой тага
public void goNextTag(BaseScreen screen, String tag) {
Log.d(LOG, "Переходим далее - ФуллСкрин С ТАГОМ");
//Смотрим видна клава или нет !
//Если да - то мы ее убираем!
if (KEYBOARD_VISIBLE) {
Instruments.getInstance().hideSoftKeyboard(rootActivity);
}
mainRouter.pushController(RouterTransaction
.with(screen)
.tag(tag) //Ставим таг!!!(На который потом сделаем выброс)
.pushChangeHandler(new FadeChangeHandler())
.popChangeHandler(new FadeChangeHandler()));
Log.d(LOG, "BackStack MAIN NEXT TAG = " + mainRouter.getBackstack().size());
}
//Метод выьроса на таг
public void popToTag(String tag) {
Log.d(LOG, "Выброс по ТАГУ");
mainRouter.popToTag(tag);
Log.d(LOG, "BackStack MAIN POP TAG = " + mainRouter.getBackstack().size());
}
//Переход далее - для ребенка
public void goNextChild(BaseScreen screen) {
Log.d(LOG, "Переходим далее - РЕБЕНОК");
if (currentRouter == null) return;
currentRouter.pushController(RouterTransaction
.with(screen)
.pushChangeHandler(new FadeChangeHandler())
.popChangeHandler(new FadeChangeHandler()));
Log.d(LOG, "BackStack CHILD = " + currentRouter.getBackstack().size());
}
//Переход назад
//Переход назад - ИМЕННО НАЗАД, КНОПКОЙ БЭК
public void goBack() {
//Смотрим видна клава или нет !
//Если да - то мы ее убираем!
if (KEYBOARD_VISIBLE) {
Instruments.getInstance().hideSoftKeyboard(rootActivity);
}
Log.d(LOG, "BackStack MAIN = " + mainRouter.getBackstack().size());
//Если мы насильно установили ручную обработку кнпки назад!!!
if (customBackBtn) {
if (customBackBtnClicker != null) {
customBackBtnClicker.backClick();
}
return;
}
//Если есть активный таг на который нужно пеерйти
if (mainRouter != null && mainRouter.getBackstackSize() > 1 && needToPopRoot) {
Log.d(LOG, "Главный роутер POP = " + mainRouter.getBackstackSize());
needToPopRoot = false;
mainRouter.popToRoot();
return;
}
//Если главный роутер не может перейти назад
if (mainRouter != null && mainRouter.getBackstackSize() > 1) {
Log.d(LOG, "Главный роутер назад = " + mainRouter.getBackstackSize());
mainRouter.handleBack();
return;
}
//Если дети могут перейти назад
if (currentRouter != null && currentRouter.getBackstackSize() > 0) {
Log.d(LOG, "Текущий роутер назад = " + currentRouter.getBackstackSize());
currentRouter.handleBack();
return;
}
//Если так оказалось что из ПОЛНОЭКРАННОГО РЕЖИМА НИЧЕГО НЕ ВЫТАЛКИВАЕТСЯ,
//то мы проверяем - МБ мы просто сменили вкладку на корневых экранах ???
if (IS_TAB_SWITCHED) {
Log.d(LOG, "Смена вкладки назад");
switchTab(0, true);
} else {
if (rootActivity == null) return;
//Если это корневое активити - то ПРОСТО НАХУЙ ЗАКРЫВАЕМ ПРИЛОЖЕНИЕ
rootActivity.finishAffinity();
}
}
//Получение видимости клавы!
public Boolean getKEYBOARD_VISIBLE() { return KEYBOARD_VISIBLE; }
public ViewGroup getFullScreenContainer() {
return fullScreenContainer;
}
public void setFullScreenContainer(ViewGroup fullScreenContainer) {
this.fullScreenContainer = fullScreenContainer;
}
public ViewGroup getBotNavContainer() {
return botNavContainer;
}
public void setBotNavContainer(ViewGroup botNavContainer) {
this.botNavContainer = botNavContainer;
}
//Все что нужно для боттом навигации
//Примерно тоже самое будет нужна для дровера
public AHBottomNavigation getBottomNavigationView() {
return ahBottomNavigation;
}
//Установка навигации
public void setBottomNavigationView(AHBottomNavigation ahBottomNavigation,
List<RouterTransaction> routerTransactionList,
Router navRouter) {
this.ahBottomNavigation = ahBottomNavigation;
this.navRouter = navRouter;
this.routerTransactionList = routerTransactionList;
//Все транзакции загоняем в роутер
for (RouterTransaction routerTransaction : routerTransactionList) {
this.navRouter.pushController(routerTransaction);
}
//Добавляем элементы!
AHBottomNavigationItem item1 = new AHBottomNavigationItem("Назначенные", R.drawable.calendar_10x);
AHBottomNavigationItem item2 = new AHBottomNavigationItem("В работе", R.drawable.technical_support_10x);
AHBottomNavigationItem item3 = new AHBottomNavigationItem("Осмечивание", R.drawable.list_10x);
AHBottomNavigationItem item4 = new AHBottomNavigationItem("Согласование", R.drawable.group_10x);
this.ahBottomNavigation.addItem(item1);
this.ahBottomNavigation.addItem(item2);
this.ahBottomNavigation.addItem(item3);
this.ahBottomNavigation.addItem(item4);
// this.ahBottomNavigation.addItem(item5);
//Меняем цвет активной иконки !
ahBottomNavigation.setAccentColor(Color.parseColor("#26245C"));
this.ahBottomNavigation.setOnTabSelectedListener(new AHBottomNavigation.OnTabSelectedListener() {
@Override
public boolean onTabSelected(int position, boolean wasSelected) {
CoordinatorMain.getInstance().switchTab(position, true);
return true;
}
});
//Выбираем 0 индекс(Изначально)
switchTab(0, true);
}
public Router getMainRouter() {
return mainRouter;
}
public void setMainRouter(Router mainRouter) {
this.mainRouter = mainRouter;
}
public void setCustomBackBtn(Boolean customBackBtn) {
this.customBackBtn = customBackBtn;
}
public void setCustomBackBtnClicker(CustomBackBtnClicker customBackBtnClicker) {
this.customBackBtnClicker = customBackBtnClicker;
}
public Boolean getNeedToPopRoot() {
return needToPopRoot;
}
public void setNeedToPopRoot(Boolean needToPopRoot) {
this.needToPopRoot = needToPopRoot;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment