Conversation
| if (options.hidden == False) { | ||
| showTopBar(options.animateHide); | ||
| } | ||
| if (options.collapse == True) { |
There was a problem hiding this comment.
This logic isn't a concern of OptionsPresenter. TopBar should have a dedicated class for managing collapse
There was a problem hiding this comment.
Sure, I'll move it out as soon it's ready
| @Override | ||
| public void addView(View child, int index, ViewGroup.LayoutParams params) { | ||
| super.addView(child, index, params); | ||
| if (child instanceof ScrollView) { |
There was a problem hiding this comment.
This means ScrollView must be the root component.
There was a problem hiding this comment.
We can look for it recursively, but I'm not sure you need to have collapsing Toolbar if ScrollView is not root
| if (scrollView != null) { | ||
| if (scrollListener != null) { | ||
| scrollChangedListener = () -> scrollListener.onScroll(scrollView.getScrollY()); | ||
| scrollView.getViewTreeObserver().addOnScrollChangedListener(scrollChangedListener); |
There was a problem hiding this comment.
Last time I checked, this method "skips" scroll events. The events reported are kind of batched or posted, meaning the callback isn't invoked immediately after a scroll. This means that if we need to track finger, this method yields subpar results.
There was a problem hiding this comment.
From what I've tested, it produces enough events to track finger. I mean we don't need that much precision.
| ViewGroup.LayoutParams layoutParams = container.getLayoutParams(); | ||
| layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT; | ||
| container.setLayoutParams(layoutParams); | ||
| //TODO: needs refactoring |
There was a problem hiding this comment.
Either refactor now, or remove the comment, open an issue detailing what needs to be refactored and assign your self.
| @SuppressWarnings("ResourceType") | ||
| public class NavigationAnimator { | ||
|
|
||
| public interface StackAnimationListener { |
There was a problem hiding this comment.
Rename this interface as well
| } | ||
|
|
||
| @Override | ||
| public void onAnimationCancel(Animator animation) { |
There was a problem hiding this comment.
Switch to adapter and remove unused methods
| AnimatorSet set = new AnimatorSet(); | ||
| set.addListener(new Animator.AnimatorListener() { | ||
| @Override | ||
| public void onAnimationStart(Animator animation) { |
| set.start(); | ||
| } | ||
|
|
||
| private float getWindowHeight(Context context) { |
There was a problem hiding this comment.
This method doesn't belong here. It should be pulled into some utils class (ViewUtils?)
| return metrics.heightPixels; | ||
| } | ||
|
|
||
| public void animateShowTopBar(final TopBar topBar, final View container) { |
There was a problem hiding this comment.
Seems like NavigationAnimator has two concerns and should be split into two classes.
- Animating screens
- Animating TopBar
There was a problem hiding this comment.
I really dislike the word container... we abused it a lot and would love phasing it out.
Please rename to contentView which is also the naming used in NavigationOptions
| } | ||
|
|
||
| @Override | ||
| public void onAnimationCancel(Animator animation) { |
| } | ||
|
|
||
| @Override | ||
| public void onAnimationCancel(Animator animation) { |
| options.textFontFamily = typefaceManager.getTypeFace(json.optString("textFontFamily", NO_VALUE)); | ||
| options.hidden = NavigationOptions.BooleanOptions.parse(json.optString("hidden")); | ||
| options.animateHide = NavigationOptions.BooleanOptions.parse(json.optString("animateHide")); | ||
| options.collapse = NavigationOptions.BooleanOptions.parse(json.optString("hideOnScroll")); |
There was a problem hiding this comment.
Consider renaming collapse to hideOnScroll? Having the same names across Js and native helps a lot
| if (options.hidden == NavigationOptions.BooleanOptions.False) { | ||
| showTopBar(options.animateHide); | ||
| } | ||
| if (options.drawUnder == True) { |
There was a problem hiding this comment.
OptionsPresenter is bound to become messy real quick. One way of keeping it clean and readable is to avoid having any kind of logic in it. Ideally, it should act as a delegate and invoke the appropriate style methods of the views.
So contentView won't be a simple view, instead it will be a concrete class or an interface declaring drawBehindTopBar() and drawBelowTopBar(). This change will make the code readable and easier to understand since the user won't need see how the two methods are implemented, to understand what they are doing.
Now, the user needs to read both methods to understand what are these rules that we are adding and removing. It also means that OptionsPresenter makes assumptions on the view and knows it's a direct child of a RelativeLayout.
| } | ||
| } | ||
|
|
||
| private void showTopBar(NavigationOptions.BooleanOptions animated) { |
There was a problem hiding this comment.
showTopBar is a detail of TopBar.
OptionsPresenter should only call topBar.showAnimated or topBar.show
|
|
||
| @SuppressLint("ViewConstructor") | ||
| public class ContainerLayout extends LinearLayout implements ReactContainer { | ||
| public class ContainerLayout extends RelativeLayout implements ReactContainer { |
| this.reactView = reactView; | ||
| public ContainerLayout(Context context, IReactView reactView, EventDispatcher eventDispatcher) { | ||
| super(context); | ||
|
|
There was a problem hiding this comment.
What's the purpose of this empty line?
There was a problem hiding this comment.
Easier to read. I mean, they belong to different views. And you can distinguish what relates to what
|
|
||
| this.topBar = new TopBar(context, this, eventDispatcher); | ||
| topBar.setId(View.generateViewId()); | ||
|
|
There was a problem hiding this comment.
What's the purpose of this empty line?
| addView(reactView.asView()); | ||
| } | ||
| private void initViews() { | ||
| LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); |
There was a problem hiding this comment.
import MATCH_PARENT statically
| addView(topTabs); | ||
| } | ||
|
|
||
| public void enableCollapse() { |
There was a problem hiding this comment.
Can we pull this logic into TopBarCollapser, then invoke topBarCollapser.enable()?
| super(context); | ||
| topBar = new TopBar(context, this); | ||
| this.tabs = tabs; | ||
| topBar = new TopBar(context, this, null); |
There was a problem hiding this comment.
Avoid passing null, better to overload and pass null internally.
There was a problem hiding this comment.
We should open an issue to implement collapse in topTabs screen
| accelerateInterpolator = new AccelerateInterpolator(); | ||
| } | ||
|
|
||
| public void animateShowTopBar(final TopBar topBar, final View contentView) { |
There was a problem hiding this comment.
Both TopBar and contentView should be params of TopBarAnimator. This way you're end up with a class which exposes public commands that only accept variables that describe the command, like start translation and duration. This makes the code much easier to understand.
| topbarAnim.start(); | ||
| } | ||
|
|
||
| public void animateHideTopBar(final TopBar topBar, final View contentView) { |
There was a problem hiding this comment.
Both params should be class members, and the function can be named to hide as we currently only animate the topBar.
topBarAnimator.animateHideTopBar -> topBarAnimator.hide() 👍
| animateHideTopBar(topBar, contentView, 0, accelerateInterpolator, DURATION_TOPBAR); | ||
| } | ||
|
|
||
| public void animateHideTopBar(final TopBar topBar, final View container, float startTranslation, TimeInterpolator interpolator, int duration) { |
| import com.reactnativenavigation.utils.UiThread; | ||
| import com.reactnativenavigation.views.TopBar; | ||
|
|
||
| public class TopbarCollapsingBehavior { |
There was a problem hiding this comment.
Change tense to present.
TopBarCollapsingBehavior -> TopBarCollapseBehavior
| this.animator = new TopBarAnimator(); | ||
| } | ||
|
|
||
| public void enableCollapsing() { |
There was a problem hiding this comment.
enableCollapsing -> enableCollapse
| showTopBar(options.animateHide); | ||
| } | ||
| if (options.drawUnder == True) { | ||
| reactContainer.drawUnderTopBar(); |
There was a problem hiding this comment.
We need to rename under to behind. Apparently under can mean two things (depending on how you look at things) and behind means exactly what we mean - a view behind a view
| } | ||
| } | ||
| private void showTopBar(NavigationOptions.BooleanOptions animated) { | ||
| topBar.show(animated, contentView); |
|
|
||
| @Override | ||
| public void drawUnderTopBar() { | ||
| //TODO: implement later |
There was a problem hiding this comment.
Please avoid leaving TODO comments. Open an issue instead 👍
| } | ||
|
|
||
| @Override | ||
| public void drawUnderTopBar() { |
| private static final String TOP_BAR_FONT_FAMILY = "HelveticaNeue-CondensedBold"; | ||
| private static final Typeface TOP_BAR_TYPEFACE = Typeface.create("HelveticaNeue-CondensedBold", Typeface.BOLD); | ||
| private static final NavigationOptions.BooleanOptions TOP_BAR_HIDDEN = True; | ||
| private static final NavigationOptions.BooleanOptions TOP_BAR_DRAW_UNDER = True; |
No description provided.