react-native-navigation的迁移库

TitleBar.java 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. package com.reactnativenavigation.views.titlebar;
  2. import android.annotation.SuppressLint;
  3. import android.content.Context;
  4. import android.graphics.PorterDuff;
  5. import android.graphics.PorterDuffColorFilter;
  6. import android.graphics.Typeface;
  7. import android.graphics.drawable.Drawable;
  8. import android.util.Log;
  9. import android.view.View;
  10. import android.view.ViewGroup;
  11. import android.widget.TextView;
  12. import com.reactnativenavigation.parse.Alignment;
  13. import com.reactnativenavigation.parse.params.Colour;
  14. import com.reactnativenavigation.utils.StringUtils;
  15. import com.reactnativenavigation.utils.UiUtils;
  16. import com.reactnativenavigation.utils.ViewUtils;
  17. import com.reactnativenavigation.viewcontrollers.TitleBarButtonController;
  18. import java.util.List;
  19. import javax.annotation.Nullable;
  20. import androidx.appcompat.widget.ActionMenuView;
  21. import androidx.appcompat.widget.Toolbar;
  22. import static com.reactnativenavigation.utils.ObjectUtils.perform;
  23. import static com.reactnativenavigation.utils.UiUtils.runOnPreDrawOnce;
  24. import static com.reactnativenavigation.utils.ViewUtils.findChildByClass;
  25. import static com.reactnativenavigation.utils.ViewUtils.findChildrenByClass;
  26. @SuppressLint("ViewConstructor")
  27. public class TitleBar extends Toolbar {
  28. public static final int DEFAULT_LEFT_MARGIN = 16;
  29. private TitleBarButtonController leftButtonController;
  30. private View component;
  31. private Alignment titleAlignment;
  32. private Alignment subtitleAlignment;
  33. private Boolean isTitleChanged = false;
  34. private Boolean isSubtitleChanged = false;
  35. public TitleBar(Context context) {
  36. super(context);
  37. getMenu();
  38. }
  39. @Override
  40. public void onViewAdded(View child) {
  41. super.onViewAdded(child);
  42. enableOverflowForReactButtonViews(child);
  43. }
  44. @Override
  45. public void setTitle(CharSequence title) {
  46. clearComponent();
  47. super.setTitle(title);
  48. isTitleChanged = true;
  49. }
  50. @Override
  51. public void setSubtitle(CharSequence title) {
  52. super.setSubtitle(title);
  53. isSubtitleChanged = true;
  54. }
  55. public String getTitle() {
  56. return super.getTitle() == null ? "" : (String) super.getTitle();
  57. }
  58. public void setComponent(View component) {
  59. clearTitle();
  60. clearSubtitle();
  61. this.component = component;
  62. addView(component);
  63. }
  64. public void setBackgroundColor(Colour color) {
  65. if (color.hasValue()) setBackgroundColor(color.get());
  66. }
  67. public void setTitleFontSize(double size) {
  68. TextView titleTextView = findTitleTextView();
  69. if (titleTextView != null) titleTextView.setTextSize((float) size);
  70. }
  71. public void setTitleTypeface(Typeface typeface) {
  72. TextView titleTextView = findTitleTextView();
  73. if (titleTextView != null) titleTextView.setTypeface(typeface);
  74. }
  75. public void setTitleAlignment(Alignment alignment) {
  76. titleAlignment = alignment;
  77. }
  78. public void setSubtitleTypeface(Typeface typeface) {
  79. TextView subtitleTextView = findSubtitleTextView();
  80. if (subtitleTextView != null) subtitleTextView.setTypeface(typeface);
  81. }
  82. public void setSubtitleFontSize(double size) {
  83. TextView subtitleTextView = findSubtitleTextView();
  84. if (subtitleTextView != null) subtitleTextView.setTextSize((float) size);
  85. }
  86. public void setSubtitleAlignment(Alignment alignment) {
  87. subtitleAlignment = alignment;
  88. }
  89. public void alignTextView(Alignment alignment, TextView view) {
  90. if (StringUtils.isEmpty(view.getText())) return;
  91. int direction = view.getParent().getLayoutDirection();
  92. boolean isRTL = direction == View.LAYOUT_DIRECTION_RTL;
  93. if (alignment == Alignment.Center) {
  94. view.setX((getWidth() - view.getWidth()) / 2);
  95. } else if (leftButtonController != null) {
  96. view.setX(isRTL ? (getWidth() - view.getWidth()) - getContentInsetStartWithNavigation() : getContentInsetStartWithNavigation());
  97. } else {
  98. view.setX(isRTL ? (getWidth() - view.getWidth()) - UiUtils.dpToPx(getContext(), DEFAULT_LEFT_MARGIN) : UiUtils.dpToPx(getContext(), DEFAULT_LEFT_MARGIN));
  99. }
  100. }
  101. @Override
  102. protected void onLayout(boolean changed, int l, int t, int r, int b) {
  103. super.onLayout(changed, l, t, r, b);
  104. if(changed || isTitleChanged) {
  105. TextView title = findTitleTextView();
  106. if (title != null) this.alignTextView(titleAlignment, title);
  107. isTitleChanged = false;
  108. }
  109. if(changed || isSubtitleChanged) {
  110. TextView subtitle = findSubtitleTextView();
  111. if (subtitle != null) this.alignTextView(subtitleAlignment, subtitle);
  112. isSubtitleChanged = false;
  113. }
  114. }
  115. @Override
  116. public void setLayoutDirection(int layoutDirection) {
  117. super.setLayoutDirection(layoutDirection);
  118. perform(findChildByClass(this, ActionMenuView.class), buttonsContainer -> buttonsContainer.setLayoutDirection(layoutDirection));
  119. }
  120. @Nullable
  121. public TextView findTitleTextView() {
  122. List<TextView> children = findChildrenByClass(this, TextView.class, textView -> textView.getText().equals(getTitle()));
  123. return children.isEmpty() ? null : children.get(0);
  124. }
  125. @Nullable
  126. public TextView findSubtitleTextView() {
  127. List<TextView> children = findChildrenByClass(this, TextView.class, textView -> textView.getText().equals(getSubtitle()));
  128. return children.isEmpty() ? null : children.get(0);
  129. }
  130. public void clear() {
  131. clearTitle();
  132. clearSubtitle();
  133. clearRightButtons();
  134. clearLeftButton();
  135. clearComponent();
  136. }
  137. private void clearTitle() {
  138. setTitle(null);
  139. }
  140. private void clearSubtitle() {
  141. setSubtitle(null);
  142. }
  143. private void clearComponent() {
  144. if (component != null) {
  145. removeView(component);
  146. component = null;
  147. }
  148. }
  149. private void clearLeftButton() {
  150. setNavigationIcon(null);
  151. if (leftButtonController != null) {
  152. leftButtonController.destroy();
  153. leftButtonController = null;
  154. }
  155. }
  156. private void clearRightButtons() {
  157. if (getMenu().size() > 0) getMenu().clear();
  158. }
  159. public void setBackButton(TitleBarButtonController button) {
  160. setLeftButton(button);
  161. }
  162. public void setLeftButtons(List<TitleBarButtonController> leftButtons) {
  163. if (leftButtons == null) return;
  164. if (leftButtons.isEmpty()) {
  165. clearLeftButton();
  166. return;
  167. }
  168. if (leftButtons.size() > 1) {
  169. Log.w("RNN", "Use a custom TopBar to have more than one left button");
  170. }
  171. setLeftButton(leftButtons.get(0));
  172. }
  173. private void setLeftButton(TitleBarButtonController button) {
  174. leftButtonController = button;
  175. runOnPreDrawOnce(findTitleTextView(), title -> alignTextView(titleAlignment, title));
  176. button.applyNavigationIcon(this);
  177. }
  178. public void setRightButtons(List<TitleBarButtonController> rightButtons) {
  179. if (rightButtons == null) return;
  180. clearRightButtons();
  181. for (int i = 0; i < rightButtons.size(); i++) {
  182. rightButtons.get(i).addToMenu(this, rightButtons.size() - i - 1);
  183. }
  184. }
  185. public void setHeight(int height) {
  186. int pixelHeight = UiUtils.dpToPx(getContext(), height);
  187. if (pixelHeight == getLayoutParams().height) return;
  188. ViewGroup.LayoutParams lp = getLayoutParams();
  189. lp.height = pixelHeight;
  190. setLayoutParams(lp);
  191. }
  192. public void setTopMargin(int topMargin) {
  193. int pixelTopMargin = UiUtils.dpToPx(getContext(), topMargin);
  194. if (getLayoutParams() instanceof MarginLayoutParams) {
  195. MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
  196. if (lp.topMargin == pixelTopMargin) return;
  197. lp.topMargin = pixelTopMargin;
  198. setLayoutParams(lp);
  199. }
  200. }
  201. public void setOverflowButtonColor(int color) {
  202. ActionMenuView actionMenuView = ViewUtils.findChildByClass(this, ActionMenuView.class);
  203. if (actionMenuView != null) {
  204. Drawable overflowIcon = actionMenuView.getOverflowIcon();
  205. if (overflowIcon != null) {
  206. overflowIcon.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
  207. }
  208. }
  209. }
  210. private void enableOverflowForReactButtonViews(View child) {
  211. if (child instanceof ActionMenuView) {
  212. ((ViewGroup) child).setClipChildren(false);
  213. }
  214. }
  215. }