Skip to content

Commit

Permalink
RTL Layout (#4575)
Browse files Browse the repository at this point in the history
* Support rtl layout

* ios layout options

* Support rtl layout

* Use View.LAYOUT_DIRECTION_LTR constant instead of 0

* move layout direction logic to RootPresenter

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* fix tests

* Fix tests
  • Loading branch information
hadimostafapour authored and yogevbd committed Feb 14, 2019
1 parent 362606b commit d09d010
Show file tree
Hide file tree
Showing 15 changed files with 132 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
import com.reactnativenavigation.parse.params.NullColor;
import com.reactnativenavigation.parse.params.NullNumber;
import com.reactnativenavigation.parse.params.Number;
import com.reactnativenavigation.parse.params.Text;
import com.reactnativenavigation.parse.params.NullText;
import com.reactnativenavigation.parse.parsers.ColorParser;
import com.reactnativenavigation.parse.parsers.NumberParser;
import com.reactnativenavigation.parse.parsers.TextParser;


import org.json.JSONObject;

Expand All @@ -18,6 +22,7 @@ public static LayoutOptions parse(JSONObject json) {
result.componentBackgroundColor = ColorParser.parse(json, "componentBackgroundColor");
result.topMargin = NumberParser.parse(json, "topMargin");
result.orientation = OrientationOptions.parse(json);
result.direction = TextParser.parse(json, "direction");

return result;
}
Expand All @@ -26,12 +31,14 @@ public static LayoutOptions parse(JSONObject json) {
public Colour componentBackgroundColor = new NullColor();
public Number topMargin = new NullNumber();
public OrientationOptions orientation = new OrientationOptions();
public Text direction = new NullText();

public void mergeWith(LayoutOptions other) {
if (other.backgroundColor.hasValue()) backgroundColor = other.backgroundColor;
if (other.componentBackgroundColor.hasValue()) componentBackgroundColor = other.componentBackgroundColor;
if (other.topMargin.hasValue()) topMargin = other.topMargin;
if (other.orientation.hasValue()) orientation = other.orientation;
if (other.direction.hasValue()) direction = other.direction;

}

Expand All @@ -40,5 +47,6 @@ public void mergeWithDefault(LayoutOptions defaultOptions) {
if (!componentBackgroundColor.hasValue()) componentBackgroundColor = defaultOptions.componentBackgroundColor;
if (!topMargin.hasValue()) topMargin = defaultOptions.topMargin;
if (!orientation.hasValue()) orientation = defaultOptions.orientation;
if (!direction.hasValue()) direction = defaultOptions.direction;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public void setRoot(String commandId, ReadableMap rawLayoutTree, Promise promise
handle(() -> {
navigator().setEventEmitter(eventEmitter);
final ViewController viewController = newLayoutFactory().create(layoutTree);
navigator().setRoot(viewController, new NativeCommandListener(commandId, promise, eventEmitter, now));
navigator().setRoot(viewController, new NativeCommandListener(commandId, promise, eventEmitter, now), reactInstanceManager);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ public boolean onMenuItemClick(MenuItem item) {
}

public void applyNavigationIcon(Toolbar toolbar) {
navigationIconResolver.resolve(button, icon -> {
Integer direction = getActivity().getWindow().getDecorView().getLayoutDirection();
navigationIconResolver.resolve(button, direction, icon -> {
setIconColor(icon);
toolbar.setNavigationOnClickListener(view -> onPressListener.onPress(button.id));
toolbar.setNavigationIcon(icon);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.View;

import com.reactnativenavigation.R;
import com.reactnativenavigation.parse.params.Button;
Expand All @@ -23,7 +24,7 @@ public NavigationIconResolver(Context context, ImageLoader imageLoader) {
this.imageLoader = imageLoader;
}

public void resolve(Button button, Func1<Drawable> onSuccess) {
public void resolve(Button button, Integer direction, Func1<Drawable> onSuccess) {
if (button.icon.hasValue()) {
imageLoader.loadIcon(context, button.icon.get(), new ImageLoadingListenerAdapter() {
@Override
Expand All @@ -37,7 +38,8 @@ public void onError(Throwable error) {
}
});
} else if (Constants.BACK_BUTTON_ID.equals(button.id)) {
onSuccess.run(ContextCompat.getDrawable(context, R.drawable.ic_arrow_back_black_24dp));
Boolean isRTL = direction == View.LAYOUT_DIRECTION_RTL;
onSuccess.run(ContextCompat.getDrawable(context, isRTL ? R.drawable.ic_arrow_back_black_rtl_24dp : R.drawable.ic_arrow_back_black_24dp));
} else {
Log.w("RNN", "Left button needs to have an icon");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import com.reactnativenavigation.viewcontrollers.modal.ModalStack;
import com.reactnativenavigation.viewcontrollers.stack.StackController;

import com.facebook.react.ReactInstanceManager;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -125,7 +127,7 @@ public void sendOnNavigationButtonPressed(String buttonId) {

}

public void setRoot(final ViewController viewController, CommandListener commandListener) {
public void setRoot(final ViewController viewController, CommandListener commandListener, ReactInstanceManager reactInstanceManager) {
destroyRoot();
final boolean removeSplashView = isRootNotCreated();
if (isRootNotCreated()) getView();
Expand All @@ -136,7 +138,7 @@ public void onSuccess(String childId) {
if (removeSplashView) removePreviousContentView();
super.onSuccess(childId);
}
});
}, reactInstanceManager);
}

private void removePreviousContentView() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@

import android.content.Context;
import android.widget.FrameLayout;
import android.view.View;

import com.reactnativenavigation.anim.NavigationAnimator;
import com.reactnativenavigation.parse.Options;
import com.reactnativenavigation.utils.CommandListener;
import com.reactnativenavigation.viewcontrollers.ViewController;
import com.reactnativenavigation.views.element.ElementTransitionManager;

import com.facebook.react.modules.i18nmanager.I18nUtil;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.ReactInstanceManager;

public class RootPresenter {
private NavigationAnimator animator;
private FrameLayout rootLayout;
Expand All @@ -25,7 +30,8 @@ public RootPresenter(Context context) {
this.animator = animator;
}

void setRoot(ViewController root, Options defaultOptions, CommandListener listener) {
void setRoot(ViewController root, Options defaultOptions, CommandListener listener, ReactInstanceManager reactInstanceManager) {
setLayoutDirection(root, defaultOptions, (ReactApplicationContext) reactInstanceManager.getCurrentReactContext());
rootLayout.addView(root.getView());
Options options = root.resolveCurrentOptions(defaultOptions);
root.setWaitForRender(options.animations.setRoot.waitForRender);
Expand All @@ -47,4 +53,15 @@ private void animateSetRootAndReportSuccess(ViewController root, CommandListener
listener.onSuccess(root.getId());
}
}

private void setLayoutDirection(ViewController root, Options defaultOptions, ReactApplicationContext reactContext) {
if (defaultOptions.layout.direction.hasValue()) {
I18nUtil i18nUtil = I18nUtil.getInstance();
Boolean isRtl = defaultOptions.layout.direction.get().equals("rtl");

root.getActivity().getWindow().getDecorView().setLayoutDirection(isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
i18nUtil.allowRTL(reactContext, isRtl);
i18nUtil.forceRTL(reactContext, isRtl);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,18 @@ public void setSubtitleAlignment(Alignment alignment) {
}

private void alignTextView(Alignment alignment, TextView view) {
Integer direction = view.getParent().getLayoutDirection();
Boolean isRTL = direction == View.LAYOUT_DIRECTION_RTL;
int width = view.getResources().getDisplayMetrics().widthPixels;
view.post(() -> {
if (alignment == Alignment.Center) {
view.measure(0, 0);
//noinspection IntegerDivisionInFloatingPointContext
view.setX((width - view.getWidth()) / 2);
} else if (leftButtonController != null) {
view.setX(getContentInsetStartWithNavigation());
view.setX(isRTL ? (getWidth() - view.getWidth()) - getContentInsetStartWithNavigation() : getContentInsetStartWithNavigation());
} else {
view.setX(UiUtils.dpToPx(getContext(), DEFAULT_LEFT_MARGIN));
view.setX(isRTL ? (getWidth() - view.getWidth()) - UiUtils.dpToPx(getContext(), DEFAULT_LEFT_MARGIN) : UiUtils.dpToPx(getContext(), DEFAULT_LEFT_MARGIN));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#000000"
android:pathData="M4,13H16.15l-5.6,5.6L12,20l8-8L12,4,10.6,5.4,16.15,11H4Z" />
</vector>
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.view.View;

import com.reactnativenavigation.BaseTest;
import com.reactnativenavigation.mocks.ImageLoaderMock;
Expand Down Expand Up @@ -42,7 +43,7 @@ public void run(Drawable icon) {

}
});
uut.resolve(iconButton(), onSuccess);
uut.resolve(iconButton(), View.LAYOUT_DIRECTION_LTR, onSuccess);
verify(imageLoader).loadIcon(eq(context), eq(ICON_URI), any());
verify(onSuccess).run(any(Drawable.class));
}
Expand All @@ -55,7 +56,7 @@ public void run(Drawable param) {

}
});
uut.resolve(backButton(), onSuccess);
uut.resolve(backButton(), View.LAYOUT_DIRECTION_LTR, onSuccess);
verifyZeroInteractions(imageLoader);
verify(onSuccess).run(any());
}
Expand Down
Loading

0 comments on commit d09d010

Please sign in to comment.