mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-02-09 22:51:57 +08:00
When some of config props change or new header items are added we need to perform a header update. This diff adds logic to trigger updating header props when that happens.
293 lines
7.7 KiB
Java
293 lines
7.7 KiB
Java
package com.swmansion.rnscreens;
|
|
|
|
import android.content.Context;
|
|
import android.graphics.PorterDuff;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.util.TypedValue;
|
|
import android.view.Gravity;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.view.ViewParent;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.appcompat.app.ActionBar;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
import androidx.appcompat.widget.Toolbar;
|
|
import androidx.fragment.app.Fragment;
|
|
|
|
import com.facebook.react.views.text.ReactFontManager;
|
|
|
|
public class ScreenStackHeaderConfig extends ViewGroup {
|
|
|
|
private final ScreenStackHeaderSubview mConfigSubviews[] = new ScreenStackHeaderSubview[3];
|
|
private int mSubviewsCount = 0;
|
|
private String mTitle;
|
|
private int mTitleColor;
|
|
private String mTitleFontFamily;
|
|
private int mTitleFontSize;
|
|
private int mBackgroundColor;
|
|
private boolean mIsHidden;
|
|
private boolean mGestureEnabled = true;
|
|
private boolean mIsBackButtonHidden;
|
|
private boolean mIsShadowHidden;
|
|
private int mTintColor;
|
|
private final Toolbar mToolbar;
|
|
|
|
private boolean mIsAttachedToWindow = false;
|
|
|
|
private OnClickListener mBackClickListener = new OnClickListener() {
|
|
@Override
|
|
public void onClick(View view) {
|
|
getScreenStack().dismiss(getScreenFragment());
|
|
}
|
|
};
|
|
|
|
public ScreenStackHeaderConfig(Context context) {
|
|
super(context);
|
|
setVisibility(View.GONE);
|
|
|
|
mToolbar = new Toolbar(context);
|
|
|
|
// set primary color as background by default
|
|
TypedValue tv = new TypedValue();
|
|
if (context.getTheme().resolveAttribute(android.R.attr.colorPrimary, tv, true)) {
|
|
mToolbar.setBackgroundColor(tv.data);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
|
// no-op
|
|
}
|
|
|
|
@Override
|
|
protected void onAttachedToWindow() {
|
|
super.onAttachedToWindow();
|
|
mIsAttachedToWindow = true;
|
|
onUpdate();
|
|
}
|
|
|
|
@Override
|
|
protected void onDetachedFromWindow() {
|
|
super.onDetachedFromWindow();
|
|
mIsAttachedToWindow = false;
|
|
}
|
|
|
|
private Screen getScreen() {
|
|
ViewParent screen = getParent();
|
|
if (screen instanceof Screen) {
|
|
return (Screen) screen;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private ScreenStack getScreenStack() {
|
|
Screen screen = getScreen();
|
|
if (screen != null) {
|
|
ScreenContainer container = screen.getContainer();
|
|
if (container instanceof ScreenStack) {
|
|
return (ScreenStack) container;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private ScreenStackFragment getScreenFragment() {
|
|
ViewParent screen = getParent();
|
|
if (screen instanceof Screen) {
|
|
Fragment fragment = ((Screen) screen).getFragment();
|
|
if (fragment instanceof ScreenStackFragment) {
|
|
return (ScreenStackFragment) fragment;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public boolean isDismissable() {
|
|
return mGestureEnabled;
|
|
}
|
|
|
|
public void onUpdate() {
|
|
Screen parent = (Screen) getParent();
|
|
final ScreenStack stack = getScreenStack();
|
|
boolean isRoot = stack == null ? true : stack.getRootScreen() == parent;
|
|
boolean isTop = stack == null ? true : stack.getTopScreen() == parent;
|
|
|
|
if (!mIsAttachedToWindow || !isTop) {
|
|
return;
|
|
}
|
|
|
|
if (mIsHidden) {
|
|
if (mToolbar.getParent() != null) {
|
|
getScreenFragment().removeToolbar();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (mToolbar.getParent() == null) {
|
|
getScreenFragment().setToolbar(mToolbar);
|
|
}
|
|
|
|
AppCompatActivity activity = (AppCompatActivity) getScreenFragment().getActivity();
|
|
activity.setSupportActionBar(mToolbar);
|
|
ActionBar actionBar = activity.getSupportActionBar();
|
|
|
|
// hide back button
|
|
actionBar.setDisplayHomeAsUpEnabled(isRoot ? false : !mIsBackButtonHidden);
|
|
|
|
// when setSupportActionBar is called a toolbar wrapper gets initialized that overwrites
|
|
// navigation click listener. The default behavior set in the wrapper is to call into
|
|
// menu options handlers, but we prefer the back handling logic to stay here instead.
|
|
mToolbar.setNavigationOnClickListener(mBackClickListener);
|
|
|
|
|
|
// shadow
|
|
getScreenFragment().setToolbarShadowHidden(mIsShadowHidden);
|
|
|
|
// title
|
|
actionBar.setTitle(mTitle);
|
|
TextView titleTextView = getTitleTextView();
|
|
if (mTitleColor != 0) {
|
|
mToolbar.setTitleTextColor(mTitleColor);
|
|
}
|
|
if (titleTextView != null) {
|
|
if (mTitleFontFamily != null) {
|
|
titleTextView.setTypeface(ReactFontManager.getInstance().getTypeface(
|
|
mTitleFontFamily, 0, getContext().getAssets()));
|
|
}
|
|
if (mTitleFontSize > 0) {
|
|
titleTextView.setTextSize(mTitleFontSize);
|
|
}
|
|
}
|
|
|
|
// background
|
|
if (mBackgroundColor != 0) {
|
|
mToolbar.setBackgroundColor(mBackgroundColor);
|
|
}
|
|
|
|
// color
|
|
if (mTintColor != 0) {
|
|
Drawable navigationIcon = mToolbar.getNavigationIcon();
|
|
if (navigationIcon != null) {
|
|
navigationIcon.setColorFilter(mTintColor, PorterDuff.Mode.SRC_ATOP);
|
|
}
|
|
}
|
|
|
|
// subviews
|
|
for (int i = 0; i < mSubviewsCount; i++) {
|
|
ScreenStackHeaderSubview view = mConfigSubviews[i];
|
|
ScreenStackHeaderSubview.Type type = view.getType();
|
|
|
|
Toolbar.LayoutParams params =
|
|
new Toolbar.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
|
|
|
|
switch (type) {
|
|
case LEFT:
|
|
// when there is a left item we need to disable navigation icon
|
|
// we also hide title as there is no other way to display left side items
|
|
mToolbar.setNavigationIcon(null);
|
|
mToolbar.setTitle(null);
|
|
params.gravity = Gravity.LEFT;
|
|
break;
|
|
case RIGHT:
|
|
params.gravity = Gravity.RIGHT;
|
|
break;
|
|
case TITLE:
|
|
params.width = LayoutParams.MATCH_PARENT;
|
|
mToolbar.setTitle(null);
|
|
case CENTER:
|
|
params.gravity = Gravity.CENTER_HORIZONTAL;
|
|
break;
|
|
}
|
|
|
|
view.setLayoutParams(params);
|
|
if (view.getParent() == null) {
|
|
mToolbar.addView(view);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void maybeUpdate() {
|
|
if (getParent() != null) {
|
|
onUpdate();
|
|
}
|
|
}
|
|
|
|
public ScreenStackHeaderSubview getConfigSubview(int index) {
|
|
return mConfigSubviews[index];
|
|
}
|
|
|
|
public int getConfigSubviewsCount() {
|
|
return mSubviewsCount;
|
|
}
|
|
|
|
public void removeConfigSubview(int index) {
|
|
if (mConfigSubviews[index] != null) {
|
|
mSubviewsCount--;
|
|
}
|
|
mConfigSubviews[index] = null;
|
|
maybeUpdate();
|
|
}
|
|
|
|
public void addConfigSubview(ScreenStackHeaderSubview child, int index) {
|
|
if (mConfigSubviews[index] == null) {
|
|
mSubviewsCount++;
|
|
}
|
|
mConfigSubviews[index] = child;
|
|
maybeUpdate();
|
|
}
|
|
|
|
private TextView getTitleTextView() {
|
|
for (int i = 0, size = mToolbar.getChildCount(); i < size; i++) {
|
|
View view = mToolbar.getChildAt(i);
|
|
if (view instanceof TextView) {
|
|
TextView tv = (TextView) view;
|
|
if (tv.getText().equals(mToolbar.getTitle())) {
|
|
return tv;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void setTitle(String title) {
|
|
mTitle = title;
|
|
}
|
|
|
|
public void setTitleFontFamily(String titleFontFamily) {
|
|
mTitleFontFamily = titleFontFamily;
|
|
}
|
|
|
|
public void setTitleFontSize(int titleFontSize) {
|
|
mTitleFontSize = titleFontSize;
|
|
}
|
|
|
|
public void setTitleColor(int color) {
|
|
mTitleColor = color;
|
|
}
|
|
|
|
public void setTintColor(int color) {
|
|
mTintColor = color;
|
|
}
|
|
|
|
public void setBackgroundColor(int color) {
|
|
mBackgroundColor = color;
|
|
}
|
|
|
|
public void setHideShadow(boolean hideShadow) {
|
|
mIsShadowHidden = hideShadow;
|
|
}
|
|
|
|
public void setGestureEnabled(boolean gestureEnabled) {
|
|
mGestureEnabled = gestureEnabled;
|
|
}
|
|
|
|
public void setHideBackButton(boolean hideBackButton) {
|
|
mIsBackButtonHidden = hideBackButton;
|
|
}
|
|
|
|
public void setHidden(boolean hidden) {
|
|
mIsHidden = hidden;
|
|
}
|
|
}
|