package com.reactnativenavigation.views; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.graphics.drawable.Drawable; import android.support.annotation.Nullable; import android.support.v7.widget.ActionMenuView; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.View; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AccelerateInterpolator; import android.widget.TextView; import com.reactnativenavigation.params.BaseScreenParams; import com.reactnativenavigation.params.BaseTitleBarButtonParams; import com.reactnativenavigation.params.StyleParams; import com.reactnativenavigation.params.TitleBarButtonParams; import com.reactnativenavigation.params.TitleBarLeftButtonParams; import com.reactnativenavigation.utils.ViewUtils; import java.util.List; public class TitleBar extends Toolbar { private static final int TITLE_VISIBILITY_ANIMATION_DURATION = 320; private LeftButton leftButton; private ActionMenuView actionMenuView; private List<TitleBarButtonParams> rightButtons; public TitleBar(Context context) { super(context); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); } @Override public void onViewAdded(View child) { super.onViewAdded(child); if (child instanceof ActionMenuView) { actionMenuView = (ActionMenuView) child; } } public void setRightButtons(List<TitleBarButtonParams> rightButtons, String navigatorEventId) { this.rightButtons = rightButtons; Menu menu = getMenu(); menu.clear(); if (rightButtons == null) { return; } addButtonsToTitleBar(navigatorEventId, menu); } public void setLeftButton(TitleBarLeftButtonParams leftButtonParams, LeftButtonOnClickListener leftButtonOnClickListener, String navigatorEventId, boolean overrideBackPressInJs) { if (shouldSetLeftButton(leftButtonParams)) { createAndSetLeftButton(leftButtonParams, leftButtonOnClickListener, navigatorEventId, overrideBackPressInJs); } else if (hasLeftButton()) { if (leftButtonParams.hasDefaultIcon() || leftButtonParams.hasCustomIcon()) { updateLeftButton(leftButtonParams); } else { removeLeftButton(); } } } private void removeLeftButton() { setNavigationIcon(null); leftButton = null; } public void setStyle(StyleParams params) { setVisibility(params.titleBarHidden ? GONE : VISIBLE); setTitleTextColor(params); setTitleTextFont(params); setSubtitleTextColor(params); colorOverflowButton(params); setBackground(params); centerTitle(params); } private void centerTitle(final StyleParams params) { final View titleView = getTitleView(); if (titleView == null) { return; } ViewUtils.runOnPreDraw(titleView, new Runnable() { @Override public void run() { if (params.titleBarTitleTextCentered) { titleView.setX(ViewUtils.getScreenWidth() / 2 - titleView.getWidth() / 2); } } }); } private void colorOverflowButton(StyleParams params) { Drawable overflowIcon = actionMenuView.getOverflowIcon(); if (shouldColorOverflowButton(params, overflowIcon)) { ViewUtils.tintDrawable(overflowIcon, params.titleBarButtonColor.getColor(), true); } } protected void setBackground(StyleParams params) { setTranslucent(params); } protected void setTranslucent(StyleParams params) { if (params.topBarTranslucent) { setBackground(new TranslucentDrawable()); } } private boolean shouldColorOverflowButton(StyleParams params, Drawable overflowIcon) { return overflowIcon != null && params.titleBarButtonColor.hasColor(); } protected void setTitleTextColor(StyleParams params) { if (params.titleBarTitleColor.hasColor()) { setTitleTextColor(params.titleBarTitleColor.getColor()); } } protected void setTitleTextFont(StyleParams params) { if (!params.titleBarTitleFont.hasFont()) { return; } View titleView = getTitleView(); if (titleView instanceof TextView) { ((TextView) titleView).setTypeface(params.titleBarTitleFont.get()); } } protected void setSubtitleTextColor(StyleParams params) { if (params.titleBarSubtitleColor.hasColor()) { setSubtitleTextColor(params.titleBarSubtitleColor.getColor()); } } private void addButtonsToTitleBar(String navigatorEventId, Menu menu) { for (int i = 0; i < rightButtons.size(); i++) { final TitleBarButton button = ButtonFactory.create(menu, this, rightButtons.get(i), navigatorEventId); addButtonInReverseOrder(rightButtons, i, button); } } protected void addButtonInReverseOrder(List<? extends BaseTitleBarButtonParams> buttons, int i, TitleBarButton button) { final int index = buttons.size() - i - 1; button.addToMenu(index); } private boolean hasLeftButton() { return leftButton != null; } private void updateLeftButton(TitleBarLeftButtonParams leftButtonParams) { if (leftButtonParams.hasDefaultIcon()) { leftButton.setIconState(leftButtonParams); setNavigationIcon(leftButton); } else if (leftButtonParams.hasCustomIcon()) { leftButton.setCustomIcon(leftButtonParams); setNavigationIcon(leftButtonParams.icon); } } private boolean shouldSetLeftButton(TitleBarLeftButtonParams leftButtonParams) { return leftButton == null && leftButtonParams != null && (leftButtonParams.hasDefaultIcon() || leftButtonParams.hasCustomIcon()); } private void createAndSetLeftButton(TitleBarLeftButtonParams leftButtonParams, LeftButtonOnClickListener leftButtonOnClickListener, String navigatorEventId, boolean overrideBackPressInJs) { leftButton = new LeftButton(getContext(), leftButtonParams, leftButtonOnClickListener, navigatorEventId, overrideBackPressInJs); setNavigationOnClickListener(leftButton); if (leftButtonParams.hasCustomIcon()) { setNavigationIcon(leftButtonParams.icon); } else { setNavigationIcon(leftButton); } } public void hide() { hide(null); } public void hide(@Nullable final Runnable onHidden) { animate() .alpha(0) .setDuration(200) .setInterpolator(new AccelerateInterpolator()) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (onHidden != null) { onHidden.run(); } } }); } public void show() { this.show(null); } public void show(final @Nullable Runnable onDisplayed) { setAlpha(0); animate() .alpha(1) .setDuration(200) .setInterpolator(new AccelerateDecelerateInterpolator()) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (onDisplayed != null) { onDisplayed.run(); } } }); } public void showTitle() { animateTitle(1); } public void hideTitle() { animateTitle(0); } private void animateTitle(int alpha) { View titleView = getTitleView(); if (titleView != null) { titleView.animate() .alpha(alpha) .setDuration(TITLE_VISIBILITY_ANIMATION_DURATION); } } @Nullable protected View getTitleView() { return ViewUtils.findChildByClass(this, TextView.class, new ViewUtils.Matcher<TextView>() { @Override public boolean match(TextView child) { return child.getText().equals(getTitle()); } }); } public void setButtonColor(StyleParams.Color titleBarButtonColor) { if (!titleBarButtonColor.hasColor()) { return; } updateButtonColor(titleBarButtonColor); setLeftButtonColor(titleBarButtonColor); setButtonsIconColor(); setButtonTextColor(); } private void setLeftButtonColor(StyleParams.Color titleBarButtonColor) { if (leftButton != null) { leftButton.setColor(titleBarButtonColor.getColor()); } } private void updateButtonColor(StyleParams.Color titleBarButtonColor) { if (rightButtons != null) { for (TitleBarButtonParams rightButton : rightButtons) { rightButton.color = titleBarButtonColor; } } } private void setButtonTextColor() { final ActionMenuView buttonsContainer = ViewUtils.findChildByClass(this, ActionMenuView.class); if (buttonsContainer != null) { for (int i = 0; i < buttonsContainer.getChildCount(); i++) { if (buttonsContainer.getChildAt(i) instanceof TextView) { ((TextView) buttonsContainer.getChildAt(i)).setTextColor(getButton(i).getColor().getColor()); } } } } private void setButtonsIconColor() { final Menu menu = getMenu(); for (int i = 0; i < menu.size(); i++) { if (menu.getItem(i).getIcon() != null) { ViewUtils.tintDrawable(menu.getItem(i).getIcon(), getButton(i).getColor().getColor(), getButton(i).enabled); } } } BaseTitleBarButtonParams getButton(int index) { return rightButtons.get(rightButtons.size() - index - 1); } public void onViewPagerScreenChanged(BaseScreenParams screenParams) { if (hasLeftButton()) { leftButton.updateNavigatorEventId(screenParams.getNavigatorEventId()); } } }