react-native-navigation的迁移库

TitleBar.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. package com.reactnativenavigation.views;
  2. import android.animation.Animator;
  3. import android.animation.AnimatorListenerAdapter;
  4. import android.app.Activity;
  5. import android.content.Context;
  6. import android.graphics.drawable.Drawable;
  7. import android.graphics.Typeface;
  8. import android.support.annotation.Nullable;
  9. import android.support.v7.widget.ActionMenuView;
  10. import android.support.v7.widget.Toolbar;
  11. import android.text.TextUtils;
  12. import android.view.Menu;
  13. import android.view.View;
  14. import android.view.animation.AccelerateDecelerateInterpolator;
  15. import android.view.animation.AccelerateInterpolator;
  16. import android.widget.TextView;
  17. import com.reactnativenavigation.params.BaseScreenParams;
  18. import com.reactnativenavigation.params.BaseTitleBarButtonParams;
  19. import com.reactnativenavigation.params.StyleParams;
  20. import com.reactnativenavigation.params.TitleBarButtonParams;
  21. import com.reactnativenavigation.params.TitleBarLeftButtonParams;
  22. import com.reactnativenavigation.utils.ViewUtils;
  23. import java.util.List;
  24. public class TitleBar extends Toolbar {
  25. private static final int TITLE_VISIBILITY_ANIMATION_DURATION = 320;
  26. private LeftButton leftButton;
  27. private ActionMenuView actionMenuView;
  28. private List<TitleBarButtonParams> rightButtons;
  29. public TitleBar(Context context) {
  30. super(context);
  31. }
  32. @Override
  33. public void onViewAdded(View child) {
  34. super.onViewAdded(child);
  35. if (child instanceof ActionMenuView) {
  36. actionMenuView = (ActionMenuView) child;
  37. }
  38. }
  39. public void setRightButtons(List<TitleBarButtonParams> rightButtons, String navigatorEventId) {
  40. this.rightButtons = rightButtons;
  41. Menu menu = getMenu();
  42. menu.clear();
  43. if (rightButtons == null) {
  44. return;
  45. }
  46. addButtonsToTitleBar(navigatorEventId, menu);
  47. }
  48. public void setLeftButton(TitleBarLeftButtonParams leftButtonParams,
  49. LeftButtonOnClickListener leftButtonOnClickListener,
  50. String navigatorEventId,
  51. boolean overrideBackPressInJs) {
  52. if (shouldSetLeftButton(leftButtonParams)) {
  53. createAndSetLeftButton(leftButtonParams, leftButtonOnClickListener, navigatorEventId, overrideBackPressInJs);
  54. } else if (hasLeftButton()) {
  55. if (leftButtonParams.hasDefaultIcon() || leftButtonParams.hasCustomIcon()) {
  56. updateLeftButton(leftButtonParams);
  57. } else {
  58. removeLeftButton();
  59. }
  60. }
  61. }
  62. private void removeLeftButton() {
  63. setNavigationIcon(null);
  64. leftButton = null;
  65. }
  66. public void setStyle(StyleParams params) {
  67. setVisibility(params.titleBarHidden);
  68. setTitleTextColor(params);
  69. setTitleTextFont(params);
  70. setTitleTextFontSize(params);
  71. setTitleTextFontWeight(params);
  72. setSubtitleTextColor(params);
  73. setSubtitleFontSize(params);
  74. setSubtitleFont(params);
  75. colorOverflowButton(params);
  76. setBackground(params);
  77. centerTopBarContent(params);
  78. setTopPadding(params);
  79. }
  80. public void setVisibility(boolean titleBarHidden) {
  81. setVisibility(titleBarHidden ? GONE : VISIBLE);
  82. }
  83. public void setTitle(String title, StyleParams styleParams) {
  84. setTitle(title);
  85. setTitleTextFont(styleParams);
  86. centerTitle(styleParams);
  87. }
  88. public void setSubtitle(CharSequence subtitle, StyleParams styleParams) {
  89. super.setSubtitle(subtitle);
  90. setSubtitleFontSize(styleParams);
  91. setSubtitleFont(styleParams);
  92. centerSubTitle(styleParams);
  93. }
  94. private void setSubtitleFontSize(StyleParams params) {
  95. TextView subtitleView = getSubtitleView();
  96. if (subtitleView != null && params.titleBarSubtitleFontSize > 0) {
  97. subtitleView.setTextSize(params.titleBarSubtitleFontSize);
  98. }
  99. }
  100. private void setSubtitleFont(StyleParams params) {
  101. if (params.titleBarSubtitleFontFamily.hasFont()) {
  102. TextView subtitleView = getSubtitleView();
  103. if (subtitleView != null) {
  104. subtitleView.setTypeface(params.titleBarSubtitleFontFamily.get());
  105. }
  106. }
  107. }
  108. private void centerTopBarContent(final StyleParams params) {
  109. centerTitle(params);
  110. centerSubTitle(params);
  111. }
  112. private void centerTitle(final StyleParams params) {
  113. final View titleView = getTitleView();
  114. if (titleView == null) {
  115. return;
  116. }
  117. ViewUtils.runOnPreDraw(titleView, new Runnable() {
  118. @Override
  119. public void run() {
  120. if (params.titleBarTitleTextCentered) {
  121. titleView.setX(ViewUtils.getWindowWidth((Activity) getContext()) / 2 - titleView.getWidth() / 2);
  122. }
  123. }
  124. });
  125. }
  126. private void centerSubTitle(final StyleParams params) {
  127. final TextView subTitleView = getSubtitleView();
  128. if (subTitleView == null) {
  129. return;
  130. }
  131. ViewUtils.runOnPreDraw(subTitleView, new Runnable() {
  132. @Override
  133. public void run() {
  134. if (params.titleBarSubTitleTextCentered) {
  135. subTitleView.setX(ViewUtils.getWindowWidth((Activity) getContext()) / 2 - subTitleView.getWidth() / 2);
  136. }
  137. }
  138. });
  139. }
  140. private void setTopPadding(final StyleParams params) {
  141. setPadding(0, (int) ViewUtils.convertDpToPixel(params.titleBarTopPadding), 0,0);
  142. }
  143. private void colorOverflowButton(StyleParams params) {
  144. Drawable overflowIcon = actionMenuView.getOverflowIcon();
  145. if (shouldColorOverflowButton(params, overflowIcon)) {
  146. ViewUtils.tintDrawable(overflowIcon, params.titleBarButtonColor.getColor(), true);
  147. }
  148. }
  149. protected void setBackground(StyleParams params) {
  150. setTranslucent(params);
  151. }
  152. protected void setTranslucent(StyleParams params) {
  153. if (params.topBarTranslucent) {
  154. setBackground(new TranslucentDrawable());
  155. }
  156. }
  157. private boolean shouldColorOverflowButton(StyleParams params, Drawable overflowIcon) {
  158. return overflowIcon != null && params.titleBarButtonColor.hasColor();
  159. }
  160. protected void setTitleTextColor(StyleParams params) {
  161. if (params.titleBarTitleColor.hasColor()) {
  162. setTitleTextColor(params.titleBarTitleColor.getColor());
  163. }
  164. }
  165. protected void setTitleTextFont(StyleParams params) {
  166. if (!params.titleBarTitleFont.hasFont()) {
  167. return;
  168. }
  169. View titleView = getTitleView();
  170. if (titleView instanceof TextView) {
  171. ((TextView) titleView).setTypeface(params.titleBarTitleFont.get());
  172. }
  173. }
  174. protected void setTitleTextFontSize(StyleParams params) {
  175. if (params.titleBarTitleFontSize > 0) {
  176. View titleView = getTitleView();
  177. if (titleView instanceof TextView) {
  178. ((TextView) titleView).setTextSize(((float) params.titleBarTitleFontSize));
  179. }
  180. }
  181. }
  182. protected void setTitleTextFontWeight(StyleParams params) {
  183. if (params.titleBarTitleFontBold) {
  184. View titleView = getTitleView();
  185. if (titleView instanceof TextView) {
  186. ((TextView) titleView).setTypeface(((TextView) titleView).getTypeface(), Typeface.BOLD);
  187. }
  188. }
  189. }
  190. protected void setSubtitleTextColor(StyleParams params) {
  191. if (params.titleBarSubtitleColor.hasColor()) {
  192. setSubtitleTextColor(params.titleBarSubtitleColor.getColor());
  193. }
  194. }
  195. private void addButtonsToTitleBar(String navigatorEventId, Menu menu) {
  196. for (int i = 0; i < rightButtons.size(); i++) {
  197. final TitleBarButton button = new TitleBarButton(menu, this, rightButtons.get(i), navigatorEventId);
  198. addButtonInReverseOrder(rightButtons, i, button);
  199. }
  200. }
  201. protected void addButtonInReverseOrder(List<? extends BaseTitleBarButtonParams> buttons, int i, TitleBarButton button) {
  202. final int index = buttons.size() - i - 1;
  203. button.addToMenu(index);
  204. }
  205. private boolean hasLeftButton() {
  206. return leftButton != null;
  207. }
  208. private void updateLeftButton(TitleBarLeftButtonParams leftButtonParams) {
  209. if (leftButtonParams.hasDefaultIcon()) {
  210. leftButton.setIconState(leftButtonParams);
  211. setNavigationIcon(leftButton);
  212. } else if (leftButtonParams.hasCustomIcon()) {
  213. leftButton.setCustomIcon(leftButtonParams);
  214. setNavigationIcon(leftButtonParams.icon);
  215. }
  216. }
  217. private boolean shouldSetLeftButton(TitleBarLeftButtonParams leftButtonParams) {
  218. return leftButton == null && leftButtonParams != null && (leftButtonParams.hasDefaultIcon() || leftButtonParams.hasCustomIcon());
  219. }
  220. private void createAndSetLeftButton(TitleBarLeftButtonParams leftButtonParams,
  221. LeftButtonOnClickListener leftButtonOnClickListener,
  222. String navigatorEventId,
  223. boolean overrideBackPressInJs) {
  224. leftButton = new LeftButton(getContext(), leftButtonParams, leftButtonOnClickListener, navigatorEventId,
  225. overrideBackPressInJs);
  226. setNavigationOnClickListener(leftButton);
  227. if (leftButtonParams.hasCustomIcon()) {
  228. setNavigationIcon(leftButtonParams.icon);
  229. } else {
  230. setNavigationIcon(leftButton);
  231. }
  232. }
  233. public void hide() {
  234. hide(null);
  235. }
  236. public void hide(@Nullable final Runnable onHidden) {
  237. animate()
  238. .alpha(0)
  239. .setDuration(200)
  240. .setInterpolator(new AccelerateInterpolator())
  241. .setListener(new AnimatorListenerAdapter() {
  242. @Override
  243. public void onAnimationEnd(Animator animation) {
  244. if (onHidden != null) {
  245. onHidden.run();
  246. }
  247. }
  248. });
  249. }
  250. public void show() {
  251. this.show(null);
  252. }
  253. public void show(final @Nullable Runnable onDisplayed) {
  254. setAlpha(0);
  255. animate()
  256. .alpha(1)
  257. .setDuration(200)
  258. .setInterpolator(new AccelerateDecelerateInterpolator())
  259. .setListener(new AnimatorListenerAdapter() {
  260. @Override
  261. public void onAnimationEnd(Animator animation) {
  262. if (onDisplayed != null) {
  263. onDisplayed.run();
  264. }
  265. }
  266. });
  267. }
  268. public void showTitle() {
  269. animateTitle(1);
  270. }
  271. public void hideTitle() {
  272. animateTitle(0);
  273. }
  274. private void animateTitle(int alpha) {
  275. View titleView = getTitleView();
  276. if (titleView != null) {
  277. titleView.animate()
  278. .alpha(alpha)
  279. .setDuration(TITLE_VISIBILITY_ANIMATION_DURATION);
  280. }
  281. }
  282. @Nullable
  283. protected View getTitleView() {
  284. return ViewUtils.findChildByClass(this, TextView.class, new ViewUtils.Matcher<TextView>() {
  285. @Override
  286. public boolean match(TextView child) {
  287. return child.getText().equals(getTitle());
  288. }
  289. });
  290. }
  291. @Nullable
  292. private TextView getSubtitleView() {
  293. if (TextUtils.isEmpty(getSubtitle())) return null;
  294. return ViewUtils.findChildByClass(this, TextView.class, new ViewUtils.Matcher<TextView>() {
  295. @Override
  296. public boolean match(TextView child) {
  297. return child.getText().equals(getSubtitle());
  298. }
  299. });
  300. }
  301. public void setButtonColor(StyleParams.Color titleBarButtonColor) {
  302. if (!titleBarButtonColor.hasColor()) {
  303. return;
  304. }
  305. updateButtonColor(titleBarButtonColor);
  306. setLeftButtonColor(titleBarButtonColor);
  307. setButtonsIconColor();
  308. setButtonTextColor();
  309. }
  310. private void setLeftButtonColor(StyleParams.Color titleBarButtonColor) {
  311. if (leftButton != null) {
  312. leftButton.setColor(titleBarButtonColor.getColor());
  313. }
  314. }
  315. private void updateButtonColor(StyleParams.Color titleBarButtonColor) {
  316. if (rightButtons != null) {
  317. for (TitleBarButtonParams rightButton : rightButtons) {
  318. rightButton.color = titleBarButtonColor;
  319. }
  320. }
  321. }
  322. private void setButtonTextColor() {
  323. final ActionMenuView buttonsContainer = ViewUtils.findChildByClass(this, ActionMenuView.class);
  324. if (buttonsContainer != null) {
  325. for (int i = 0; i < buttonsContainer.getChildCount(); i++) {
  326. if (buttonsContainer.getChildAt(i) instanceof TextView) {
  327. ((TextView) buttonsContainer.getChildAt(i)).setTextColor(getButton(i).getColor().getColor());
  328. }
  329. }
  330. }
  331. }
  332. private void setButtonsIconColor() {
  333. final Menu menu = getMenu();
  334. for (int i = 0; i < menu.size(); i++) {
  335. if (menu.getItem(i).getIcon() != null) {
  336. ViewUtils.tintDrawable(menu.getItem(i).getIcon(),
  337. getButton(i).getColor().getColor(),
  338. getButton(i).enabled);
  339. }
  340. }
  341. }
  342. BaseTitleBarButtonParams getButton(int index) {
  343. return rightButtons.get(rightButtons.size() - index - 1);
  344. }
  345. public void onViewPagerScreenChanged(BaseScreenParams screenParams) {
  346. if (hasLeftButton()) {
  347. leftButton.updateNavigatorEventId(screenParams.getNavigatorEventId());
  348. }
  349. }
  350. public void destroy() {
  351. unmountCustomButtons();
  352. }
  353. private void unmountCustomButtons() {
  354. for (int i = 0; i < actionMenuView.getChildCount(); i++) {
  355. if (actionMenuView.getChildAt(i) instanceof TitleBarButtonComponent) {
  356. ((ContentView) actionMenuView.getChildAt(i)).unmountReactView();
  357. }
  358. }
  359. }
  360. }