You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ky...@apache.org on 2018/11/15 09:24:25 UTC
[incubator-weex] branch master updated:
[WEEX-653][android][iOS][core] Android&iOS support rtl direction by CSS
"direction:rtl" (#1664)
This is an automated email from the ASF dual-hosted git repository.
kyork pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-weex.git
The following commit(s) were added to refs/heads/master by this push:
new 3cb8e9e [WEEX-653][android][iOS][core] Android&iOS support rtl direction by CSS "direction:rtl" (#1664)
3cb8e9e is described below
commit 3cb8e9e7744be99408519bc20a7ab818e24d2cbd
Author: Klueze <hz...@gmail.com>
AuthorDate: Thu Nov 15 17:24:20 2018 +0800
[WEEX-653][android][iOS][core] Android&iOS support rtl direction by CSS "direction:rtl" (#1664)
Ref https://developer.mozilla.org/en-US/docs/Web/CSS/text-align
---
.../com/alibaba/weex/extend/component/WXMask.java | 4 +-
android/sdk/libs/armeabi-v7a/libweexcore.so | Bin 1116120 -> 1399344 bytes
android/sdk/libs/armeabi/libweexcore.so | Bin 1128400 -> 1407536 bytes
.../x86/{libweexjss.so => libJavaScriptCore.so} | Bin 11354824 -> 10159504 bytes
android/sdk/libs/x86/libweexcore.so | Bin 2706100 -> 2742964 bytes
android/sdk/libs/x86/libweexjss.so | Bin 11354824 -> 1231736 bytes
android/sdk/libs/x86/libweexjst.so | Bin 0 -> 5548 bytes
.../main/java/com/taobao/weex/WXEnvironment.java | 14 +++
.../main/java/com/taobao/weex/WXSDKInstance.java | 7 ++
.../com/taobao/weex/bridge/WXBridgeManager.java | 1 +
.../main/java/com/taobao/weex/bridge/WXParams.java | 7 ++
.../main/java/com/taobao/weex/common/WXConfig.java | 1 +
.../src/main/java/com/taobao/weex/dom/WXStyle.java | 8 +-
.../measurefunc/TextContentBoxMeasurement.java | 2 +-
.../weex/ui/action/ActionGetLayoutDirection.java | 117 +++++++++++++++++++++
.../com/taobao/weex/ui/component/WXComponent.java | 66 ++++++++++--
.../com/taobao/weex/ui/component/WXIndicator.java | 2 +-
.../com/taobao/weex/ui/component/WXScroller.java | 89 +++++++++++++++-
.../com/taobao/weex/ui/component/WXSlider.java | 29 ++++-
.../com/taobao/weex/ui/component/WXVContainer.java | 5 +-
.../weex/ui/component/list/BasicListComponent.java | 42 +++++++-
.../weex/ui/component/list/GapItemDecoration.java | 13 ++-
.../list/template/WXRecyclerTemplateList.java | 3 +-
.../template/jni/NativeRenderLayoutDirection.java} | 28 ++---
.../list/template/jni/NativeRenderObjectUtils.java | 1 +
.../com/taobao/weex/ui/module/WXDomModule.java | 12 ++-
.../taobao/weex/ui/view/WXCirclePageAdapter.java | 28 ++++-
.../com/taobao/weex/ui/view/WXCircleViewPager.java | 23 ++--
.../com/taobao/weex/utils/StaticLayoutProxy.java | 22 ++--
android/sdk/src/main/res/values-ldltr/isrtl.xml | 24 +++++
android/sdk/src/main/res/values-ldrtl/istrtl.xml | 24 +++++
ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m | 16 +--
.../Sources/Component/WXComponent_internal.h | 3 +
.../Sources/Component/WXCycleSliderComponent.mm | 33 ++++++
.../Sources/Component/WXScrollerComponent.mm | 37 ++++++-
.../WeexSDK/Sources/Component/WXTextComponent.mm | 6 +-
.../WeexSDK/Sources/Layout/WXComponent+Layout.h | 10 ++
.../WeexSDK/Sources/Layout/WXComponent+Layout.mm | 75 ++++++++++++-
ios/sdk/WeexSDK/Sources/Model/WXComponent.mm | 5 +-
ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 3 +
ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m | 1 +
ios/sdk/WeexSDK/Sources/Module/WXDomModule.m | 26 +++++
.../WeexSDK/Sources/Protocol/WXScrollerProtocol.h | 6 ++
ios/sdk/WeexSDK/Sources/Utility/WXType.h | 6 ++
ios/sdk/WeexSDK/Sources/Utility/WXUtility.h | 6 ++
ios/sdk/WeexSDK/Sources/Utility/WXUtility.m | 27 ++++-
.../Sources/View/WXComponent+ViewManagement.mm | 6 ++
.../jniheader/NativeRenderObjectUtils_jni.h | 8 ++
weex_core/Source/android/utils/params_utils.cpp | 16 +++
.../native_render_object_utils_impl_android.cpp | 7 +-
weex_core/Source/core/css/constants_name.h | 1 +
weex_core/Source/core/css/constants_value.h | 4 +
weex_core/Source/core/css/css_value_getter.cpp | 11 ++
weex_core/Source/core/css/css_value_getter.h | 1 +
weex_core/Source/core/layout/flex_enum.h | 12 ++-
weex_core/Source/core/layout/layout.cpp | 76 ++++++++++---
weex_core/Source/core/layout/layout.h | 94 ++++++++++++++---
weex_core/Source/core/layout/style.h | 6 +-
.../Source/core/render/node/render_object.cpp | 7 ++
weex_core/Source/core/render/node/render_object.h | 3 +-
.../Source/core/render/node/render_scroller.cpp | 7 ++
.../Source/core/render/node/render_scroller.h | 18 ++++
weex_core/Source/core/render/page/render_page.cpp | 8 +-
weex_core/release.sh | 0
64 files changed, 1000 insertions(+), 117 deletions(-)
diff --git a/android/playground/app/src/main/java/com/alibaba/weex/extend/component/WXMask.java b/android/playground/app/src/main/java/com/alibaba/weex/extend/component/WXMask.java
index 778404c..252de1c 100644
--- a/android/playground/app/src/main/java/com/alibaba/weex/extend/component/WXMask.java
+++ b/android/playground/app/src/main/java/com/alibaba/weex/extend/component/WXMask.java
@@ -124,7 +124,9 @@ public class WXMask extends WXVContainer {
top = get(TOP);
bottom = get(BOTTOM);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height);
- params.setMargins(left, top, right, bottom);
+
+ this.setMarginsSupportRTL(params, left, top, right, bottom);
+
getHostView().setLayoutParams(params);
}
diff --git a/android/sdk/libs/armeabi-v7a/libweexcore.so b/android/sdk/libs/armeabi-v7a/libweexcore.so
old mode 100755
new mode 100644
index 08a3751..4b1cac4
Binary files a/android/sdk/libs/armeabi-v7a/libweexcore.so and b/android/sdk/libs/armeabi-v7a/libweexcore.so differ
diff --git a/android/sdk/libs/armeabi/libweexcore.so b/android/sdk/libs/armeabi/libweexcore.so
old mode 100755
new mode 100644
index a88a0ff..1be8d2b
Binary files a/android/sdk/libs/armeabi/libweexcore.so and b/android/sdk/libs/armeabi/libweexcore.so differ
diff --git a/android/sdk/libs/x86/libweexjss.so b/android/sdk/libs/x86/libJavaScriptCore.so
old mode 100755
new mode 100644
similarity index 53%
copy from android/sdk/libs/x86/libweexjss.so
copy to android/sdk/libs/x86/libJavaScriptCore.so
index ac0dd7f..0e0f9f5
Binary files a/android/sdk/libs/x86/libweexjss.so and b/android/sdk/libs/x86/libJavaScriptCore.so differ
diff --git a/android/sdk/libs/x86/libweexcore.so b/android/sdk/libs/x86/libweexcore.so
old mode 100755
new mode 100644
index 9955dc3..e4c3a3b
Binary files a/android/sdk/libs/x86/libweexcore.so and b/android/sdk/libs/x86/libweexcore.so differ
diff --git a/android/sdk/libs/x86/libweexjss.so b/android/sdk/libs/x86/libweexjss.so
old mode 100755
new mode 100644
index ac0dd7f..3733a2a
Binary files a/android/sdk/libs/x86/libweexjss.so and b/android/sdk/libs/x86/libweexjss.so differ
diff --git a/android/sdk/libs/x86/libweexjst.so b/android/sdk/libs/x86/libweexjst.so
new file mode 100644
index 0000000..84add1e
Binary files /dev/null and b/android/sdk/libs/x86/libweexjst.so differ
diff --git a/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java b/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java
index 13564ff..cf4c7b2 100644
--- a/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java
+++ b/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java
@@ -157,6 +157,13 @@ public class WXEnvironment {
configs.put(WXConfig.sysModel, SYS_MODEL);
configs.put(WXConfig.weexVersion, String.valueOf(WXSDK_VERSION));
configs.put(WXConfig.logLevel,sLogLevel.getName());
+
+ try {
+ configs.put(WXConfig.layoutDirection, isLayoutDirectionRTL() ? "rtl" : "ltr");
+ } catch (Exception e) {
+ configs.put(WXConfig.layoutDirection, "ltr");
+ }
+
try {
if (isApkDebugable()) {
options.put(WXConfig.debugMode, "true");
@@ -225,6 +232,13 @@ public class WXEnvironment {
return isHardwareSupport() && isInitialized;
}
+ public static boolean isLayoutDirectionRTL() {
+ // support RTL
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ return sApplication.getApplicationContext().getResources().getBoolean(R.bool.weex_is_right_to_left);
+ }
+ return false;
+ }
/**
* Tell whether Weex can run on current hardware.
* @return true if weex can run on current hardware, otherwise false.
diff --git a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
index cfa87b7..0962db5 100644
--- a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
+++ b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
@@ -1664,6 +1664,13 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
return 0;
}
+ public int getRenderContainerPaddingRight() {
+ if(mRenderContainer != null) {
+ return mRenderContainer.getPaddingRight();
+ }
+ return 0;
+ }
+
public int getRenderContainerPaddingTop() {
if(mRenderContainer != null) {
return mRenderContainer.getPaddingTop();
diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
index 531b601..cbe68ae 100644
--- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
@@ -1975,6 +1975,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
wxParams.setDeviceModel(config.get(WXConfig.sysModel));
wxParams.setShouldInfoCollect(config.get("infoCollect"));
wxParams.setLogLevel(config.get(WXConfig.logLevel));
+ wxParams.setLayoutDirection(config.get(WXConfig.layoutDirection));
wxParams.setUseSingleProcess(isUseSingleProcess ? "true" : "false");
wxParams.setCrashFilePath(WXEnvironment.getCrashFilePath(WXEnvironment.getApplication().getApplicationContext()));
wxParams.setLibJssPath(WXEnvironment.getLibJssRealPath());
diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXParams.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXParams.java
index 8b41a8f..657b21a 100644
--- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXParams.java
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXParams.java
@@ -42,6 +42,7 @@ public class WXParams implements Serializable {
private String useSingleProcess;
private String crashFilePath;
private String libJssPath;
+ private String layoutDirection;
private String libJscPath;
private String libIcuPath;
@@ -121,6 +122,11 @@ public class WXParams implements Serializable {
}
@CalledByNative
+ public String getLayoutDirection() {return layoutDirection;}
+
+ public void setLayoutDirection(String direction) { this.layoutDirection = direction; }
+
+ @CalledByNative
public String getAppName() {
return appName;
}
@@ -246,6 +252,7 @@ public class WXParams implements Serializable {
map.put("deviceHeight", deviceHeight);
map.put("deviceModel", deviceModel);
map.put("deviceWidth", deviceWidth);
+ map.put("layoutDirection", layoutDirection);
map.put("libJssPath", libJssPath);
map.put("logLevel", logLevel);
map.put("needInitV8", needInitV8);
diff --git a/android/sdk/src/main/java/com/taobao/weex/common/WXConfig.java b/android/sdk/src/main/java/com/taobao/weex/common/WXConfig.java
index 11dc820..7bf525c 100644
--- a/android/sdk/src/main/java/com/taobao/weex/common/WXConfig.java
+++ b/android/sdk/src/main/java/com/taobao/weex/common/WXConfig.java
@@ -33,5 +33,6 @@ public interface WXConfig {
String externalUserAgent="externalUserAgent";
String logLevel="logLevel";
String scale = "scale";
+ String layoutDirection = "layoutDirection";
String debugMode = "debugMode";
}
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXStyle.java b/android/sdk/src/main/java/com/taobao/weex/dom/WXStyle.java
index a401090..17f549e 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/WXStyle.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXStyle.java
@@ -178,13 +178,17 @@ public class WXStyle implements Map<String, Object>,Cloneable {
}
public static Layout.Alignment getTextAlignment(Map<String, Object> style){
- Layout.Alignment alignment= Layout.Alignment.ALIGN_NORMAL;
+ return getTextAlignment(style, false);
+ }
+
+ public static Layout.Alignment getTextAlignment(Map<String, Object> style, boolean isRTL){
+ Layout.Alignment alignment= isRTL ? Layout.Alignment.ALIGN_OPPOSITE : Layout.Alignment.ALIGN_NORMAL;
String textAlign= (String) style.get(Constants.Name.TEXT_ALIGN);
if(TextUtils.equals(Constants.Value.LEFT,textAlign)){
alignment= Layout.Alignment.ALIGN_NORMAL;
}
else if(TextUtils.equals(Constants.Value.CENTER,textAlign)){
- alignment=Layout.Alignment.ALIGN_CENTER;
+ alignment= Layout.Alignment.ALIGN_CENTER;
}
else if(TextUtils.equals(Constants.Value.RIGHT,textAlign)){
alignment= Layout.Alignment.ALIGN_OPPOSITE;
diff --git a/android/sdk/src/main/java/com/taobao/weex/layout/measurefunc/TextContentBoxMeasurement.java b/android/sdk/src/main/java/com/taobao/weex/layout/measurefunc/TextContentBoxMeasurement.java
index 66d0fae..ef0ccb0 100644
--- a/android/sdk/src/main/java/com/taobao/weex/layout/measurefunc/TextContentBoxMeasurement.java
+++ b/android/sdk/src/main/java/com/taobao/weex/layout/measurefunc/TextContentBoxMeasurement.java
@@ -232,7 +232,7 @@ public class TextContentBoxMeasurement extends ContentBoxMeasurement {
if (style.containsKey(Constants.Name.FONT_FAMILY)) {
mFontFamily = WXStyle.getFontFamily(style);
}
- mAlignment = WXStyle.getTextAlignment(style);
+ mAlignment = WXStyle.getTextAlignment(style, mComponent.isNativeLayoutRTL());
textOverflow = WXStyle.getTextOverflow(style);
int lineHeight = WXStyle.getLineHeight(style, mComponent.getViewPortWidth());
if (lineHeight != UNSET) {
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/action/ActionGetLayoutDirection.java b/android/sdk/src/main/java/com/taobao/weex/ui/action/ActionGetLayoutDirection.java
new file mode 100644
index 0000000..039bdfc
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/action/ActionGetLayoutDirection.java
@@ -0,0 +1,117 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.taobao.weex.ui.action;
+
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
+import android.view.View;
+
+import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.bridge.JSCallback;
+import com.taobao.weex.bridge.SimpleJSCallback;
+import com.taobao.weex.ui.component.WXComponent;
+import com.taobao.weex.ui.component.list.template.jni.NativeRenderObjectUtils;
+import com.taobao.weex.utils.WXViewUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Created by listen on 18/09/12.
+ */
+public class ActionGetLayoutDirection extends BasicGraphicAction {
+
+ private final String mCallback;
+
+ public ActionGetLayoutDirection(WXSDKInstance instance, String ref, String callback) {
+ super(instance, ref);
+ this.mCallback = callback;
+ }
+
+ @Override
+ public void executeAction() {
+ WXSDKInstance instance = getWXSDKIntance();
+ if (instance == null || instance.isDestroy()) {
+ return;
+ }
+
+ JSCallback jsCallback = new SimpleJSCallback(instance.getInstanceId(), mCallback);
+
+ if (TextUtils.isEmpty(getRef())) {
+ Map<String, Object> options = new HashMap<>();
+ options.put("result", false);
+ options.put("errMsg", "Illegal parameter");
+ jsCallback.invoke(options);
+ } else if ("viewport".equalsIgnoreCase(getRef())) {
+ callbackViewport(instance, jsCallback);
+ } else {
+ WXComponent component = WXSDKManager.getInstance().getWXRenderManager().getWXComponent(getPageId(), getRef());
+ if (component == null) {
+ return;
+ }
+
+ String directionRet = "ltr";
+ if (component != null) {
+ int direction = NativeRenderObjectUtils.nativeRenderObjectGetLayoutDirectionFromPathNode(component.getRenderObjectPtr());
+ switch (direction) {
+ case 0: {
+ directionRet = "inherit";
+ break;
+ }
+ case 1: {
+ directionRet = "ltr";
+ break;
+ }
+ case 2: {
+ directionRet = "rtl";
+ break;
+ }
+ default: {
+ directionRet = "ltr";
+ break;
+ }
+
+ }
+ }
+ jsCallback.invoke(directionRet);
+ }
+ }
+
+ private void callbackViewport(WXSDKInstance instance, JSCallback jsCallback) {
+ View container;
+ if ((container = instance.getContainerView()) != null) {
+ Map<String, Object> options = new HashMap<>();
+ options.put("direction", "ltr");
+ options.put("result", true);
+ jsCallback.invoke(options);
+ } else {
+ Map<String, Object> options = new HashMap<>();
+ options.put("result", false);
+ options.put("errMsg", "Component does not exist");
+ jsCallback.invoke(options);
+ }
+ }
+
+ @NonNull
+ private float getWebPxValue(int value,int viewport) {
+ return WXViewUtils.getWebPxByWidth(value, viewport);
+ }
+
+}
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java
index 7840b9a..fbf8bc3 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java
@@ -46,6 +46,7 @@ import android.support.v4.view.ViewCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.text.TextUtils;
import android.util.Pair;
+import android.view.Gravity;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
@@ -87,6 +88,7 @@ import com.taobao.weex.ui.animation.WXAnimationModule;
import com.taobao.weex.ui.component.basic.WXBasicComponent;
import com.taobao.weex.ui.component.binding.Statements;
import com.taobao.weex.ui.component.list.WXCell;
+import com.taobao.weex.ui.component.list.template.jni.NativeRenderLayoutDirection;
import com.taobao.weex.ui.component.list.template.jni.NativeRenderObjectUtils;
import com.taobao.weex.ui.component.pesudo.OnActivePseudoListner;
import com.taobao.weex.ui.component.pesudo.PesudoStatus;
@@ -153,6 +155,7 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
private int mPreRealWidth = 0;
private int mPreRealHeight = 0;
private int mPreRealLeft = 0;
+ private int mPreRealRight = 0;
private int mPreRealTop = 0;
private int mStickyOffset = 0;
protected WXGesture mGesture;
@@ -233,6 +236,44 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
WXBridgeManager.getInstance().bindMeasurementToRenderObject(getRenderObjectPtr());
}
+
+ public void setMarginsSupportRTL(ViewGroup.MarginLayoutParams lp, int left, int top, int right, int bottom) {
+ lp.setMargins(left, top, right, bottom);
+ if (lp instanceof FrameLayout.LayoutParams) {
+ FrameLayout.LayoutParams lp_frameLayout = (FrameLayout.LayoutParams) lp;
+ lp_frameLayout.gravity = Gravity.LEFT | Gravity.TOP;
+ }
+ }
+
+ public boolean isNativeLayoutRTL() {
+ return NativeRenderObjectUtils.nativeRenderObjectGetLayoutDirectionFromPathNode(this.getRenderObjectPtr()) == NativeRenderLayoutDirection.rtl;
+ }
+
+ public static boolean isLayoutRTL(WXComponent cmp) {
+ if (cmp == null) return false;
+
+ View view = cmp.getHostView();
+ if (ViewCompat.isLayoutDirectionResolved(view)) {
+ return ViewCompat.getLayoutDirection(view) == View.LAYOUT_DIRECTION_RTL;
+ } else if (cmp.getParent() != null){
+ return isLayoutRTL(cmp.getParent());
+ } else {
+ return isLayoutRTL((ViewGroup) view.getParent());
+ }
+ }
+
+ public static boolean isLayoutRTL(ViewGroup viewGroup) {
+ if (viewGroup == null) return false;
+
+ if (ViewCompat.isLayoutDirectionResolved(viewGroup)) {
+ return ViewCompat.getLayoutDirection(viewGroup) == View.LAYOUT_DIRECTION_RTL;
+ } else if (viewGroup.getParent() instanceof ViewGroup) {
+ return isLayoutRTL((ViewGroup) viewGroup.getParent());
+ } else {
+ return false;
+ }
+ }
+
public void updateStyles(WXComponent component) {
if (component != null) {
updateProperties(component.getStyles());
@@ -881,8 +922,7 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
/**
* layout view
*/
- public final void setLayout(WXComponent component) {
-
+ public void setLayout(WXComponent component) {
if (TextUtils.isEmpty(component.getComponentType())
|| TextUtils.isEmpty(component.getRef()) || component.getLayoutPosition() == null
|| component.getLayoutSize() == null) {
@@ -910,6 +950,7 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
int realLeft = 0;
int realTop = 0;
+ int realRight = 0;
if (isFixed()) {
realLeft = (int) (getLayoutPosition().getLeft() - getInstance().getRenderContainerPaddingLeft());
@@ -921,14 +962,14 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
parentPadding.get(CSSShorthand.EDGE.TOP) - parentBorder.get(CSSShorthand.EDGE.TOP)) + siblingOffset;
}
- int realRight = (int) getMargin().get(CSSShorthand.EDGE.RIGHT);
+ realRight = (int) getMargin().get(CSSShorthand.EDGE.RIGHT);
int realBottom = (int) getMargin().get(CSSShorthand.EDGE.BOTTOM);
Point rawOffset = new Point(
(int) getLayoutPosition().getLeft(),
(int) getLayoutPosition().getTop());
- if (mPreRealWidth == realWidth && mPreRealHeight == realHeight && mPreRealLeft == realLeft && mPreRealTop == realTop) {
+ if (mPreRealWidth == realWidth && mPreRealHeight == realHeight && mPreRealLeft == realLeft && mPreRealRight == realRight && mPreRealTop == realTop) {
return;
}
@@ -994,6 +1035,7 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
mPreRealWidth = realWidth;
mPreRealHeight = realHeight;
mPreRealLeft = realLeft;
+ mPreRealRight = realRight;
mPreRealTop = realTop;
onFinishLayout();
// restore box shadow
@@ -1047,14 +1089,14 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
protected void setHostLayoutParams(T host, int width, int height, int left, int right, int top, int bottom) {
ViewGroup.LayoutParams lp;
if (mParent == null) {
- FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height);
- params.setMargins(left, top, right, bottom);
- lp = params;
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height);
+ this.setMarginsSupportRTL(params, left, top, right, bottom);
+ lp = params;
} else {
- lp = mParent.getChildLayoutParams(this, host, width, height, left, right, top, bottom);
+ lp = mParent.getChildLayoutParams(this, host, width, height, left, right, top, bottom);
}
if (lp != null) {
- host.setLayoutParams(lp);
+ host.setLayoutParams(lp);
}
}
@@ -1063,7 +1105,9 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
params.width = width;
params.height = height;
- params.setMargins(left, top, right, bottom);
+
+ this.setMarginsSupportRTL(params, left, top, right, bottom);
+
host.setLayoutParams(params);
mInstance.moveFixedView(host);
@@ -1844,6 +1888,7 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
public View detachViewAndClearPreInfo() {
View original = mHost;
mPreRealLeft = 0;
+ mPreRealRight = 0;
mPreRealWidth = 0;
mPreRealHeight = 0;
mPreRealTop = 0;
@@ -1853,6 +1898,7 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
public void clearPreLayout() {
mPreRealLeft = 0;
+ mPreRealRight = 0;
mPreRealWidth = 0;
mPreRealHeight = 0;
mPreRealTop = 0;
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXIndicator.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXIndicator.java
index e8422ca..449c12e 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXIndicator.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXIndicator.java
@@ -54,7 +54,7 @@ public class WXIndicator extends WXComponent<WXCircleIndicator> {
@Override
protected void setHostLayoutParams(WXCircleIndicator host, int width, int height, int left, int right, int top, int bottom) {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height);
- params.setMargins(left, top, right, bottom);
+ this.setMarginsSupportRTL(params, left, top, right, bottom);
host.setLayoutParams(params);
}
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXScroller.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXScroller.java
index 81c0e17..bfef86f 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXScroller.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXScroller.java
@@ -33,7 +33,11 @@ import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
+import android.support.annotation.RequiresApi;
+import android.support.v4.view.ViewCompat;
import android.text.TextUtils;
+import android.view.Gravity;
+import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
@@ -378,6 +382,42 @@ public class WXScroller extends WXVContainer<ViewGroup> implements WXScrollViewL
}
@Override
+ public void setMarginsSupportRTL(ViewGroup.MarginLayoutParams lp, int left, int top, int right, int bottom) {
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ lp.setMargins(left, top, right, bottom);
+ lp.setMarginStart(left);
+ lp.setMarginEnd(right);
+ } else {
+ if (lp instanceof FrameLayout.LayoutParams) {
+ FrameLayout.LayoutParams lp_frameLayout = (FrameLayout.LayoutParams) lp;
+ if (this.isNativeLayoutRTL()) {
+ lp_frameLayout.gravity = Gravity.RIGHT | Gravity.TOP;
+ lp.setMargins(right, top, left, bottom);
+ } else {
+ lp_frameLayout.gravity = Gravity.LEFT | Gravity.TOP;
+ lp.setMargins(left, top, right, bottom);
+ }
+ } else {
+ lp.setMargins(left, top, right, bottom);
+ }
+ }
+ }
+
+ @Override
+ public void setLayout(WXComponent component) {
+ if (TextUtils.isEmpty(component.getComponentType())
+ || TextUtils.isEmpty(component.getRef()) || component.getLayoutPosition() == null
+ || component.getLayoutSize() == null) {
+ return;
+ }
+ if (component.getHostView() != null) {
+ int layoutDirection = component.isNativeLayoutRTL() ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
+ ViewCompat.setLayoutDirection(component.getHostView(), layoutDirection);
+ }
+ super.setLayout(component);
+ }
+
+ @Override
protected MeasureOutput measure(int width, int height) {
MeasureOutput measureOutput = new MeasureOutput();
if (this.mOrientation == Constants.Orientation.HORIZONTAL) {
@@ -437,6 +477,37 @@ public class WXScroller extends WXVContainer<ViewGroup> implements WXScrollViewL
scrollView.addView(mRealView, layoutParams);
scrollView.setHorizontalScrollBarEnabled(false);
+ final WXScroller component = this;
+ final View.OnLayoutChangeListener listener = new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ final View frameLayout = view;
+ scrollView.post(new Runnable() {
+ @Override
+ public void run() {
+ if (isNativeLayoutRTL()) {
+ int mw = frameLayout.getMeasuredWidth();
+ scrollView.scrollTo(mw, component.getScrollY());
+ } else {
+ scrollView.scrollTo(0, component.getScrollY());
+ }
+ }
+ });
+ }
+ };
+ mRealView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View view) {
+ view.addOnLayoutChangeListener(listener);
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View view) {
+ view.removeOnLayoutChangeListener(listener);
+ }
+ });
+
+
if(pageEnable) {
mGestureDetector = new GestureDetector(new MyGestureDetector(scrollView));
scrollView.setOnTouchListener(new View.OnTouchListener() {
@@ -706,9 +777,21 @@ public class WXScroller extends WXVContainer<ViewGroup> implements WXScrollViewL
mActiveFeature = mChildren.indexOf(component);
}
-
- int viewYInScroller=component.getAbsoluteY() - getAbsoluteY();
- int viewXInScroller=component.getAbsoluteX() - getAbsoluteX();
+ int viewYInScroller = component.getAbsoluteY() - getAbsoluteY();
+ int viewXInScroller = 0;
+ if (this.isNativeLayoutRTL()) {
+ // if layout direction is rtl, we need calculate rtl scroll x;
+ if (getInnerView().getChildCount() > 0) {
+ int totalWidth = getInnerView().getChildAt(0).getWidth();
+ int displayWidth = getInnerView().getMeasuredWidth();
+ viewXInScroller = totalWidth - (component.getAbsoluteX() - getAbsoluteX()) - displayWidth;
+ } else {
+ viewXInScroller = component.getAbsoluteX() - getAbsoluteX();
+ }
+ offsetFloat = - offsetFloat;
+ } else {
+ viewXInScroller = component.getAbsoluteX() - getAbsoluteX();
+ }
scrollBy(viewXInScroller - getScrollX() + (int) offsetFloat, viewYInScroller - getScrollY() + (int) offsetFloat, smooth);
}
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXSlider.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXSlider.java
index 196c839..8e94740 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXSlider.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXSlider.java
@@ -145,9 +145,9 @@ public class WXSlider extends WXVContainer<FrameLayout> {
if (lp instanceof ViewGroup.MarginLayoutParams) {
//expect indicator .
if (child instanceof WXIndicator) {
- ((ViewGroup.MarginLayoutParams) lp).setMargins(left, top, right, bottom);
+ this.setMarginsSupportRTL((ViewGroup.MarginLayoutParams) lp, left, top, right, bottom);
} else {
- ((ViewGroup.MarginLayoutParams) lp).setMargins(0, 0, 0, 0);
+ this.setMarginsSupportRTL((ViewGroup.MarginLayoutParams) lp, 0, 0, 0, 0);
}
}
return lp;
@@ -193,7 +193,7 @@ public class WXSlider extends WXVContainer<FrameLayout> {
@Override
public void run() {
initIndex = getInitIndex();
- mViewPager.setCurrentItem(initIndex);
+ mViewPager.setCurrentItem(getRealIndex(initIndex));
initIndex = -1;
initRunnable = null;
}
@@ -203,7 +203,7 @@ public class WXSlider extends WXVContainer<FrameLayout> {
mViewPager.postDelayed(initRunnable, 50);
} else {
if (!keepIndex) {
- mViewPager.setCurrentItem(0);
+ mViewPager.setCurrentItem(getRealIndex(0));
}
}
if (mIndicator != null) {
@@ -213,6 +213,12 @@ public class WXSlider extends WXVContainer<FrameLayout> {
}
@Override
+ public void setLayout(WXComponent component) {
+ mAdapter.setLayoutDirectionRTL(this.isNativeLayoutRTL());
+ super.setLayout(component);
+ }
+
+ @Override
public void remove(WXComponent child, boolean destroy) {
if (child == null || child.getHostView() == null || mAdapter == null) {
return;
@@ -274,9 +280,22 @@ public class WXSlider extends WXVContainer<FrameLayout> {
if(select >= mAdapter.getRealCount()){
select = select%mAdapter.getRealCount();
}
+
return select;
}
+ private int getRealIndex(int idx) {
+ int retIdx = idx;
+
+ if (mAdapter.getRealCount() > 0) {
+ if(idx >= mAdapter.getRealCount()) retIdx = mAdapter.getRealCount() - 1;
+ if (isNativeLayoutRTL()) {
+ retIdx = mAdapter.getRealCount() - 1 - retIdx;
+ }
+ }
+ retIdx = retIdx + 0;
+ return retIdx;
+ }
@Override
protected boolean setProperty(String key, Object param) {
@@ -383,6 +402,8 @@ public class WXSlider extends WXVContainer<FrameLayout> {
initIndex = index;
return;
}
+
+ index = getRealIndex(index);
mViewPager.setCurrentItem(index);
if (mIndicator != null && mIndicator.getHostView() != null
&& mIndicator.getHostView().getRealCurrentItem() != index) {
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java
index c9880b5..3d797ed 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java
@@ -131,7 +131,7 @@ public abstract class WXVContainer<T extends ViewGroup> extends WXComponent<T> {
lp.width = width;
lp.height = height;
if(lp instanceof ViewGroup.MarginLayoutParams){
- ((ViewGroup.MarginLayoutParams) lp).setMargins(left,top,right,bottom);
+ this.setMarginsSupportRTL((ViewGroup.MarginLayoutParams) lp, left, top, right, bottom);
}
}
return lp;
@@ -588,8 +588,7 @@ public abstract class WXVContainer<T extends ViewGroup> extends WXComponent<T> {
int bottom = (int) (padding.get(CSSShorthand.EDGE.BOTTOM) + border.get(CSSShorthand.EDGE.BOTTOM));
ViewGroup.MarginLayoutParams layoutParams = new ViewGroup.MarginLayoutParams(hostView.getLayoutParams()) ;
- layoutParams.setMargins(-left, -top, -right, -bottom);
-
+ this.setMarginsSupportRTL(layoutParams, -left, -top, -right, -bottom);
mBoxShadowHost.setLayoutParams(layoutParams);
hostView.addView(mBoxShadowHost);
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java
index e377ad9..a9a2c67 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java
@@ -35,6 +35,7 @@ import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.text.TextUtils;
import android.util.SparseArray;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -174,6 +175,42 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
}
@Override
+ public void setMarginsSupportRTL(ViewGroup.MarginLayoutParams lp, int left, int top, int right, int bottom) {
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ lp.setMargins(left, top, right, bottom);
+ lp.setMarginStart(left);
+ lp.setMarginEnd(right);
+ } else {
+ if (lp instanceof FrameLayout.LayoutParams) {
+ FrameLayout.LayoutParams lp_frameLayout = (FrameLayout.LayoutParams) lp;
+ if (this.isNativeLayoutRTL()) {
+ lp_frameLayout.gravity = Gravity.RIGHT | Gravity.TOP;
+ lp.setMargins(right, top, left, bottom);
+ } else {
+ lp_frameLayout.gravity = Gravity.LEFT | Gravity.TOP;
+ lp.setMargins(left, top, right, bottom);
+ }
+ } else {
+ lp.setMargins(left, top, right, bottom);
+ }
+ }
+ }
+
+ @Override
+ public void setLayout(WXComponent component) {
+ if (TextUtils.isEmpty(component.getComponentType())
+ || TextUtils.isEmpty(component.getRef()) || component.getLayoutPosition() == null
+ || component.getLayoutSize() == null) {
+ return;
+ }
+ if (component.getHostView() != null) {
+ int layoutDirection = component.isNativeLayoutRTL() ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
+ ViewCompat.setLayoutDirection(component.getHostView(), layoutDirection);
+ }
+ super.setLayout(component);
+ }
+
+ @Override
protected void onHostViewInitialized(T host) {
super.onHostViewInitialized(host);
@@ -248,7 +285,8 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
} else {
params.width = width;
params.height = height;
- params.setMargins(left, 0, right, 0);
+
+ this.setMarginsSupportRTL(params, left, 0, right, 0);
}
return params;
}
@@ -331,8 +369,6 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
}
});
-
-
bounceRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/GapItemDecoration.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/GapItemDecoration.java
index 821d7ce..aebb6c3 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/GapItemDecoration.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/GapItemDecoration.java
@@ -64,10 +64,17 @@ public class GapItemDecoration extends RecyclerView.ItemDecoration {
if (params.getSpanIndex() >= spanOffsets.length) {
return;
}
- float spanOffset = listComponent.getSpanOffsets()[params.getSpanIndex()];
+
+ int index = listComponent.isNativeLayoutRTL() ? spanOffsets.length - params.getSpanIndex() - 1 : params.getSpanIndex();
+ float spanOffset = listComponent.getSpanOffsets()[index];
int spanOffsetPx = Math.round(WXViewUtils.getRealPxByWidth(spanOffset, listComponent.getViewPortWidth()));
- outRect.left = spanOffsetPx;
- outRect.right = -spanOffsetPx;
+ if (listComponent.isNativeLayoutRTL()) {
+ outRect.left = -spanOffsetPx;
+ outRect.right = spanOffsetPx;
+ } else {
+ outRect.left = spanOffsetPx;
+ outRect.right = -spanOffsetPx;
+ }
}
}
}
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java
index 916d895..8efcc2f 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java
@@ -1283,7 +1283,8 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
} else {
params.width = width;
params.height = height;
- params.setMargins(left, 0, right, 0);
+
+ this.setMarginsSupportRTL(params, left, 0, right, 0);
}
return params;
}
diff --git a/android/sdk/src/main/java/com/taobao/weex/common/WXConfig.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/jni/NativeRenderLayoutDirection.java
similarity index 61%
copy from android/sdk/src/main/java/com/taobao/weex/common/WXConfig.java
copy to android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/jni/NativeRenderLayoutDirection.java
index 11dc820..443dcf6 100644
--- a/android/sdk/src/main/java/com/taobao/weex/common/WXConfig.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/jni/NativeRenderLayoutDirection.java
@@ -1,4 +1,4 @@
-/*
+/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -16,22 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package com.taobao.weex.common;
+package com.taobao.weex.ui.component.list.template.jni;
-public interface WXConfig {
-
- String os = "os";
- String osName = "osName";
- String appVersion="appVersion";
- String cacheDir = "cacheDir";
- String devId="devId";
- String sysVersion="sysVersion";
- String sysModel="sysModel";
- String weexVersion="weexVersion";
- String appName="appName";
- String appGroup="appGroup";
- String externalUserAgent="externalUserAgent";
- String logLevel="logLevel";
- String scale = "scale";
- String debugMode = "debugMode";
+public class NativeRenderLayoutDirection {
+ public static final int inherit = 0;
+ public static final int ltr = 1;
+ public static final int rtl = 2;
}
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/jni/NativeRenderObjectUtils.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/jni/NativeRenderObjectUtils.java
index c477413..f665e8b 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/jni/NativeRenderObjectUtils.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/jni/NativeRenderObjectUtils.java
@@ -51,6 +51,7 @@ public class NativeRenderObjectUtils {
* */
public static native int nativeLayoutRenderObject(long ptr, float width, float height);
+ public static native int nativeRenderObjectGetLayoutDirectionFromPathNode(long ptr);
/**
* get child length
* */
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/module/WXDomModule.java b/android/sdk/src/main/java/com/taobao/weex/ui/module/WXDomModule.java
index 787ae53..8f8c957 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/module/WXDomModule.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/module/WXDomModule.java
@@ -26,6 +26,7 @@ import com.taobao.weex.common.WXModule;
import com.taobao.weex.dom.binding.JSONUtils;
import com.taobao.weex.ui.action.ActionAddRule;
import com.taobao.weex.ui.action.ActionGetComponentRect;
+import com.taobao.weex.ui.action.ActionGetLayoutDirection;
import com.taobao.weex.ui.action.ActionInvokeMethod;
import com.taobao.weex.ui.action.GraphicActionBatchBegin;
import com.taobao.weex.ui.action.GraphicActionBatchEnd;
@@ -47,6 +48,7 @@ public final class WXDomModule extends WXModule {
public static final String SCROLL_TO_ELEMENT = "scrollToElement";
public static final String ADD_RULE = "addRule";
public static final String GET_COMPONENT_RECT = "getComponentRect";
+ public static final String GET_COMPONENT_DIRECTION = "getLayoutDirection";
public static final String WXDOM = "dom";
public static final String INVOKE_METHOD = "invokeMethod";
@@ -59,7 +61,7 @@ public final class WXDomModule extends WXModule {
* Methods expose to js. Every method which will be called in js should add to this array.
*/
public static final String[] METHODS = {SCROLL_TO_ELEMENT, ADD_RULE, GET_COMPONENT_RECT,
- INVOKE_METHOD, BATCH_BEGIN, BATCH_END};
+ INVOKE_METHOD, GET_COMPONENT_DIRECTION, BATCH_BEGIN, BATCH_END};
public WXDomModule(WXSDKInstance instance){
mWXSDKInstance = instance;
@@ -82,6 +84,14 @@ public final class WXDomModule extends WXModule {
try {
switch (method) {
+ case GET_COMPONENT_DIRECTION: {
+ if(args == null){
+ return null;
+ }
+ new ActionGetLayoutDirection(mWXSDKInstance, args.getString(0), args.getString(1))
+ .executeActionOnRender();
+ break;
+ }
case SCROLL_TO_ELEMENT:{
if (args == null) {
return null;
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/view/WXCirclePageAdapter.java b/android/sdk/src/main/java/com/taobao/weex/ui/view/WXCirclePageAdapter.java
index 281c4e2..1b5b219 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/view/WXCirclePageAdapter.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/view/WXCirclePageAdapter.java
@@ -26,6 +26,7 @@ import com.taobao.weex.WXEnvironment;
import com.taobao.weex.utils.WXLogUtils;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
public class WXCirclePageAdapter extends PagerAdapter {
@@ -37,12 +38,26 @@ public class WXCirclePageAdapter extends PagerAdapter {
private List<View> shadow = new ArrayList<>();
private boolean needLoop = true;
+ public boolean isRTL = false;
+ private List<View> originalViews = new ArrayList<>();
+
public WXCirclePageAdapter(List<View> views, boolean needLoop) {
super();
this.views = new ArrayList<>(views);
+ this.originalViews = new ArrayList<>(views);
this.needLoop = needLoop;
}
+ public void setLayoutDirectionRTL(boolean isRTL) {
+ if (isRTL == this.isRTL) return;
+ this.isRTL = isRTL;
+ this.views = new ArrayList<>(this.originalViews);
+ if (isRTL) {
+ Collections.reverse(this.views);
+ }
+ ensureShadow();
+ }
+
public WXCirclePageAdapter() {
this(true);
}
@@ -56,7 +71,13 @@ public class WXCirclePageAdapter extends PagerAdapter {
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.d("onPageSelected >>>> addPageView");
}
- views.add(view);
+
+ originalViews.add(view);
+ if (this.isRTL) {
+ views.add(0, view);
+ } else {
+ views.add(view);
+ }
ensureShadow();
}
@@ -65,6 +86,7 @@ public class WXCirclePageAdapter extends PagerAdapter {
WXLogUtils.d("onPageSelected >>>> removePageView");
}
views.remove(view);
+ originalViews.remove(view);
ensureShadow();
}
@@ -77,6 +99,10 @@ public class WXCirclePageAdapter extends PagerAdapter {
views.remove(index);
views.add(index, newView);
ensureShadow();
+
+ index = originalViews.indexOf(oldView);
+ originalViews.remove(index);
+ originalViews.add(index, newView);
}
@Override
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/view/WXCircleViewPager.java b/android/sdk/src/main/java/com/taobao/weex/ui/view/WXCircleViewPager.java
index 5c79e5b..6c19615 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/view/WXCircleViewPager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/view/WXCircleViewPager.java
@@ -317,13 +317,24 @@ public class WXCircleViewPager extends ViewPager implements WXGestureObservable
}
private void showNextItem() {
- if (!needLoop && superGetCurrentItem() == getRealCount() - 1) {
- return;
- }
- if (getRealCount() == 2 && superGetCurrentItem() == 1) {
- superSetCurrentItem(0, true);
+ if (this.getCirclePageAdapter() != null && this.getCirclePageAdapter().isRTL) {
+ if (!needLoop && superGetCurrentItem() == 0) {
+ return;
+ }
+ if (getRealCount() == 2 && superGetCurrentItem() == 0) {
+ superSetCurrentItem(1, true);
+ } else {
+ superSetCurrentItem(superGetCurrentItem() - 1, true);
+ }
} else {
- superSetCurrentItem(superGetCurrentItem() + 1, true);
+ if (!needLoop && superGetCurrentItem() == getRealCount() - 1) {
+ return;
+ }
+ if (getRealCount() == 2 && superGetCurrentItem() == 1) {
+ superSetCurrentItem(0, true);
+ } else {
+ superSetCurrentItem(superGetCurrentItem() + 1, true);
+ }
}
}
}
diff --git a/android/sdk/src/main/java/com/taobao/weex/utils/StaticLayoutProxy.java b/android/sdk/src/main/java/com/taobao/weex/utils/StaticLayoutProxy.java
index a3584ce..ac1d660 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/StaticLayoutProxy.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/StaticLayoutProxy.java
@@ -31,6 +31,7 @@ import java.lang.reflect.Constructor;
*/
public class StaticLayoutProxy {
+ private static Constructor<StaticLayout> layoutConstructor;
public static StaticLayout create(CharSequence source, TextPaint paint,
int width,
Layout.Alignment align, float spacingmult, float spacingadd,
@@ -40,6 +41,8 @@ public class StaticLayoutProxy {
StaticLayout rtlLayout = createInternal(source, paint, width, align, textDir, spacingmult, spacingadd, includepad);
if (rtlLayout != null) {
return rtlLayout;
+ } else {
+ return new StaticLayout(source, paint, width, align, spacingmult, spacingadd, includepad);
}
}
return new StaticLayout(source, paint, width, align, spacingmult, spacingadd, includepad);
@@ -53,16 +56,19 @@ public class StaticLayoutProxy {
return null;
} else {
try {
- Class<StaticLayout> clazz = StaticLayout.class;
- Constructor<StaticLayout> constructor = clazz.getConstructor(CharSequence.class, TextPaint.class,
- int.class, Layout.Alignment.class, TextDirectionHeuristic.class,
- float.class, float.class,
- boolean.class);
-
- if (constructor != null) {
- return constructor.newInstance(source, paint, width,
+ if (layoutConstructor == null) {
+ Class<StaticLayout> clazz = StaticLayout.class;
+ Constructor<StaticLayout> constructor = clazz.getConstructor(CharSequence.class, TextPaint.class,
+ int.class, Layout.Alignment.class, TextDirectionHeuristic.class,
+ float.class, float.class,
+ boolean.class);
+ layoutConstructor = constructor;
+ }
+ if (layoutConstructor != null) {
+ return layoutConstructor.newInstance(source, paint, width,
align, textDir, spacingmult, spacingadd, includepad);
}
+
} catch (Throwable e) {
e.printStackTrace();
}
diff --git a/android/sdk/src/main/res/values-ldltr/isrtl.xml b/android/sdk/src/main/res/values-ldltr/isrtl.xml
new file mode 100644
index 0000000..5008fea
--- /dev/null
+++ b/android/sdk/src/main/res/values-ldltr/isrtl.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<resources>
+ <bool name="weex_is_right_to_left">false</bool>
+</resources>
\ No newline at end of file
diff --git a/android/sdk/src/main/res/values-ldrtl/istrtl.xml b/android/sdk/src/main/res/values-ldrtl/istrtl.xml
new file mode 100644
index 0000000..47d9b1a
--- /dev/null
+++ b/android/sdk/src/main/res/values-ldrtl/istrtl.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<resources>
+ <bool name="weex_is_right_to_left">true</bool>
+</resources>
\ No newline at end of file
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
index dd186de..6d42333 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
@@ -850,13 +850,17 @@ _Pragma("clang diagnostic pop") \
{
if(self.frameworkLoadFinished) {
WXAssert(script, @"param script required!");
- NSDictionary* funcInfo = @{
- @"func":@"executeJsService",
- @"arg":name?:@"unsetScriptName"
- };
- self.jsBridge.javaScriptContext[@"wxExtFuncInfo"] = funcInfo;
+ if ([self.jsBridge respondsToSelector:@selector(javaScriptContext)]) {
+ NSDictionary* funcInfo = @{
+ @"func":@"executeJsService",
+ @"arg":name?:@"unsetScriptName"
+ };
+ self.jsBridge.javaScriptContext[@"wxExtFuncInfo"] = funcInfo;
+ }
[self.jsBridge executeJavascript:script];
- self.jsBridge.javaScriptContext[@"wxExtFuncInfo"] = nil;
+ if ([self.jsBridge respondsToSelector:@selector(javaScriptContext)]) {
+ self.jsBridge.javaScriptContext[@"wxExtFuncInfo"] = nil;
+ }
if ([self.jsBridge exception]) {
NSString *exception = [[self.jsBridge exception] toString];
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
index fc7658d..3aef1dc 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
@@ -283,6 +283,9 @@ typedef id (^WXDataBindingBlock)(NSDictionary *data, BOOL *needUpdate);
- (void)_buildViewHierarchyLazily;
+
+- (void)_adjustForRTL;
+
- (BOOL)_isAffineTypeAs:(NSString *)type;
@end
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.mm b/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.mm
index 402e592..b8a25fa 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.mm
+++ b/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.mm
@@ -458,6 +458,39 @@ typedef NS_ENUM(NSInteger, Direction) {
_recycleSliderView.currentIndex = _index;
}
+- (void)_buildViewHierarchyLazily {
+ [super _buildViewHierarchyLazily];
+}
+
+- (void)adjustForRTL
+{
+ if (![WXUtility enableRTLLayoutDirection]) return;
+
+ // this is scroll rtl solution.
+ // scroll layout not use direction, use self tranform
+ if (self.view && _flexCssNode && _flexCssNode->getLayoutDirectionFromPathNode() == WeexCore::kDirectionRTL
+ ) {
+ WXRecycleSliderView *slider = (WXRecycleSliderView *)self.view;
+ CATransform3D transform = CATransform3DScale(CATransform3DIdentity, -1, 1, 1);
+ slider.scrollView.layer.transform = transform ;
+ } else {
+ WXRecycleSliderView *slider = (WXRecycleSliderView *)self.view;
+ slider.scrollView.layer.transform = CATransform3DIdentity ;
+ }
+
+}
+
+- (void)_adjustForRTL {
+ if (![WXUtility enableRTLLayoutDirection]) return;
+
+ [super _adjustForRTL];
+ [self adjustForRTL];
+}
+
+- (BOOL)shouldTransformSubviewsWhenRTL {
+ return YES;
+}
+
- (void)viewDidUnload
{
[_childrenView removeAllObjects];
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.mm b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.mm
index a278202..50256ab 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.mm
+++ b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.mm
@@ -19,6 +19,7 @@
#import "WXScrollerComponent.h"
#import "WXComponent_internal.h"
+#import "WXSDKInstance_private.h"
#import "WXComponent.h"
#import "WXDefine.h"
#import "WXConvert.h"
@@ -415,6 +416,33 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
}
}
+- (void)adjustForRTL
+{
+ if (![WXUtility enableRTLLayoutDirection]) return;
+
+ // this is scroll rtl solution.
+ // scroll layout not use direction, use self tranform
+ if (self.view && _flexCssNode && _flexCssNode->getLayoutDirectionFromPathNode() == WeexCore::kDirectionRTL
+ ) {
+ if (_transform) {
+ self.view.layer.transform = CATransform3DConcat(self.view.layer.transform, CATransform3DScale(CATransform3DIdentity, -1, 1, 1));
+ } else {
+ self.view.layer.transform = CATransform3DScale(CATransform3DIdentity, -1, 1, 1);
+ }
+ } else {
+ if (!_transform) {
+ self.view.layer.transform = CATransform3DIdentity;
+ }
+ }
+}
+
+- (void)_adjustForRTL {
+ if (![WXUtility enableRTLLayoutDirection]) return;
+
+ [super _adjustForRTL];
+ [self adjustForRTL];
+}
+
- (void)adjustSticky
{
if (![self isViewLoaded]) {
@@ -1044,7 +1072,7 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
float left = _flexCssNode->getLayoutPositionLeft();
float width = _flexCssNode->getLayoutWidth();
float height = _flexCssNode->getLayoutHeight();
-
+
if (_scrollDirection == WXScrollDirectionVertical) {
_flexCssNode->setFlexDirection(WeexCore::kFlexDirectionColumn, NO);
_flexCssNode->setStyleWidth(_flexCssNode->getLayoutWidth(), NO);
@@ -1054,7 +1082,14 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
_flexCssNode->setStyleHeight(_flexCssNode->getLayoutHeight());
_flexCssNode->setStyleWidth(FlexUndefined, NO);
}
+
_flexCssNode->markAllDirty();
+
+ // this is scroll rtl solution.
+ // scroll layout not use direction, use self tranform
+ // but we need inherit direction in CSS, so we set children layout diretion manually
+ _flexCssNode->determineChildLayoutDirection(_flexCssNode->getLayoutDirectionFromPathNode());
+
std::pair<float, float> renderPageSize;
renderPageSize.first = self.weexInstance.frame.size.width;
renderPageSize.second = self.weexInstance.frame.size.height;
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm
index e8683aa..f4c21a9 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm
+++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm
@@ -139,7 +139,6 @@ CGFloat WXTextDefaultLineThroughWidth = 1.2;
WXTextStyle _fontStyle;
NSUInteger _lines;
NSTextAlignment _textAlign;
- NSString *_direction;
WXTextDecoration _textDecoration;
NSString *_textOverflow;
CGFloat _lineHeight;
@@ -273,7 +272,6 @@ do {\
WX_STYLE_FILL_TEXT_PIXEL(lineHeight, lineHeight, YES)
WX_STYLE_FILL_TEXT_PIXEL(letterSpacing, letterSpacing, YES)
WX_STYLE_FILL_TEXT(wordWrap, wordWrap, NSString, YES);
- WX_STYLE_FILL_TEXT(direction, direction, NSString, YES)
if (_fontFamily && !_observerIconfont) {
// notification received when custom icon font file download finish
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(repaintText:) name:WX_ICONFONT_DOWNLOAD_NOTIFICATION object:nil];
@@ -515,7 +513,7 @@ do {\
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
// handle text direction style, default ltr
- BOOL isRtl = [_direction isEqualToString:@"rtl"];
+ BOOL isRtl = [self isDirectionRTL];
if (isRtl) {
if (0 == _textAlign) {
//force text right-align if don't specified any align.
@@ -598,7 +596,7 @@ do {\
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
// handle text direction style, default ltr
- BOOL isRtl = [_direction isEqualToString:@"rtl"];
+ BOOL isRtl = [self isDirectionRTL];
if (isRtl) {
if (0 == _textAlign) {
//force text right-align if don't specified any align.
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.h b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.h
index a338847..518a163 100644
--- a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.h
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.h
@@ -43,6 +43,7 @@ extern "C" {
CGRect _calculatedFrame;
CGPoint _absolutePosition;
WXPositionType _positionType;
+ BOOL _isLastLayoutDirectionRTL;
}
/**
@@ -69,4 +70,13 @@ extern "C" {
*/
- (void)removeSubcomponentCssNode:(WXComponent *)subcomponent;
+#pragma mark - RTL
+
+@property (nonatomic, assign, readonly) BOOL isDirectionRTL;
+
+// Now we scrollView RTL solution is tranform
+// so scrollView need tranform subviews when RTL by default
+// if your component view is not scrollView but also implement RTL layout by tranform,you need return YES
+- (BOOL)shouldTransformSubviewsWhenRTL;
+
@end
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm
index 18cb24d..14246e7 100644
--- a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm
@@ -153,11 +153,26 @@ bool flexIsUndefined(float value) {
[strongSelf->_transform applyTransformForView:strongSelf.view];
}
+ [self _adjustForRTL];
+
if (strongSelf->_backgroundImage) {
[strongSelf setGradientLayer];
}
[strongSelf setNeedsDisplay];
}];
+ } else {
+ // if frame is not change, we still need check was layoutDirection changed
+ if ([self isDirectionRTL] != _isLastLayoutDirectionRTL) {
+ _isLastLayoutDirectionRTL = [self isDirectionRTL];
+ __weak typeof(self) weakSelf = self;
+ [self.weexInstance.componentManager _addUITask:^{
+ __strong typeof(weakSelf) strongSelf = weakSelf;
+ if (strongSelf->_transform) {
+ [strongSelf->_transform applyTransformForView:strongSelf.view];
+ }
+ [strongSelf _adjustForRTL];
+ }];
+ }
}
}
@@ -168,6 +183,7 @@ bool flexIsUndefined(float value) {
if (_positionType == WXPositionTypeSticky) {
[self.ancestorScroller adjustSticky];
}
+
[self layoutDidFinish];
}
@@ -183,9 +199,15 @@ bool flexIsUndefined(float value) {
if (_flexCssNode == nullptr) {
return;
}
-
+
BOOL needLayout = NO;
+ // CSS direction for RTL Layout
+ if (styles[@"direction"]) {
+ _flexCssNode->setDirection([self fxDirection:styles[@"direction"]], isUpdate);
+ needLayout = YES;
+ }
+
// flex
if (styles[@"flex"]) {
_flexCssNode->set_flex([WXConvert CGFloat:styles[@"flex"]]);
@@ -453,7 +475,9 @@ do {\
if (styles.count<=0) {
return;
}
-
+
+ WX_FLEX_STYLE_RESET_CSS_NODE(direction, @(WeexCore::kDirectionInherit))
+
WX_FLEX_STYLE_RESET_CSS_NODE(flex, @0.0)
WX_FLEX_STYLE_RESET_CSS_NODE(flexDirection, @(WeexCore::kFlexDirectionColumn))
WX_FLEX_STYLE_RESET_CSS_NODE(alignItems, @(WeexCore::kAlignItemsStretch))
@@ -563,6 +587,18 @@ static WeexCore::WXCoreSize flexCssNodeMeasure(WeexCore::WXCoreLayoutNode *node,
return WeexCore::kRelative;
}
+- (WeexCore::WXCoreDirection)fxDirection:(id)value
+{
+ if([value isKindOfClass:[NSString class]]){
+ if ([value isEqualToString:@"rtl"]) {
+ return WeexCore::kDirectionRTL;
+ } else if ([value isEqualToString:@"ltr"]) {
+ return WeexCore::kDirectionLTR;
+ }
+ }
+ return WeexCore::kDirectionInherit;
+}
+
- (WeexCore::WXCoreFlexDirection)fxFlexDirection:(id)value
{
if([value isKindOfClass:[NSString class]]){
@@ -677,4 +713,39 @@ static WeexCore::WXCoreSize flexCssNodeMeasure(WeexCore::WXCoreLayoutNode *node,
}
}
+#pragma mark - RTL
+
+- (BOOL)isDirectionRTL {
+ if (![WXUtility enableRTLLayoutDirection]) return NO;
+
+ WeexCore::WXCoreDirection direction = _flexCssNode == nullptr ? WeexCore::WEEXCORE_CSS_DEFAULT_DIRECTION : _flexCssNode->getLayoutDirectionFromPathNode();
+ if (direction != WeexCore::kDirectionInherit) return direction == WeexCore::kDirectionRTL;
+ return NO;
+}
+
+- (void)_adjustForRTL {
+ if (![WXUtility enableRTLLayoutDirection]) return;
+
+ if (self->_positionType == WXPositionTypeFixed) return;
+
+ if (self.supercomponent && self.supercomponent->_flexCssNode && self.supercomponent->_flexCssNode->getLayoutDirectionFromPathNode() == WeexCore::kDirectionRTL && [self.supercomponent shouldTransformSubviewsWhenRTL]) {
+ if (_transform) {
+ self.view.layer.transform = CATransform3DConcat(self.view.layer.transform, CATransform3DScale(CATransform3DIdentity, -1, 1, 1));
+ } else {
+ self.view.layer.transform = CATransform3DScale(CATransform3DIdentity, -1, 1, 1);
+ }
+ } else {
+ if (!_transform) {
+ self.view.layer.transform = CATransform3DIdentity;
+ }
+ }
+}
+
+// Now we scrollView RTL solution is tranform
+// so scrollView need tranform subviews when RTL by default
+// if your component view is not scrollView but also implement RTL layout by tranform,you need return YES
+- (BOOL)shouldTransformSubviewsWhenRTL {
+ return [self.view isKindOfClass:[UIScrollView class]];
+}
+
@end
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm b/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm
index 43fda8b..f69f506 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.mm
@@ -383,11 +383,13 @@ static BOOL bNeedRemoveEvents = YES;
if (_backgroundImage) {
[self setGradientLayer];
}
-
+
if (_transform) {
[_transform applyTransformForView:_view];
}
+ [self _adjustForRTL];
+
if (_boxShadow) {
[self configBoxShadow:_boxShadow];
}
@@ -801,6 +803,7 @@ static BOOL bNeedRemoveEvents = YES;
self.transform = [[WXTransform alloc] initWithNativeTransform:CATransform3DMakeAffineTransform(transform) instance:self.weexInstance];
if (!CGRectEqualToRect(self.calculatedFrame, CGRectZero)) {
[_transform applyTransformForView:_view];
+ [self _adjustForRTL];
[_layer setNeedsDisplay];
}
}
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
index e0cc3b8..4a04c14 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
@@ -447,6 +447,9 @@ typedef enum : NSUInteger {
BOOL useJSCApiForCreateInstance = [[configCenter configForKey:@"iOS_weex_ext_config.useJSCApiForCreateInstance" defaultValue:@(YES) isDefault:NULL] boolValue];
[WXUtility setUseJSCApiForCreateInstance:useJSCApiForCreateInstance];
+
+ BOOL enableRTLLayoutDirection = [[configCenter configForKey:@"iOS_weex_ext_config.enableRTLLayoutDirection" defaultValue:@(YES) isDefault:NULL] boolValue];
+ [WXUtility setEnableRTLLayoutDirection:enableRTLLayoutDirection];
BOOL shoudMultiContext = NO;
shoudMultiContext = [[configCenter configForKey:@"iOS_weex_ext_config.createInstanceUsingMutliContext" defaultValue:@(YES) isDefault:NULL] boolValue];
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m
index 75b09d8..3b52110 100644
--- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m
+++ b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m
@@ -93,6 +93,7 @@
if ([_animationInfo.propertyName hasPrefix:@"transform"]) {
WXTransform *transform = _animationInfo.target->_transform;
[transform applyTransformForView:_animationInfo.target.view];
+ [_animationInfo.target _adjustForRTL];
} else if ([_animationInfo.propertyName isEqualToString:@"backgroundColor"]) {
_animationInfo.target.view.layer.backgroundColor = (__bridge CGColorRef _Nullable)(_animationInfo.toValue);
} else if ([_animationInfo.propertyName isEqualToString:@"opacity"]) {
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m b/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m
index 312d6f8..a3de95b 100644
--- a/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m
+++ b/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m
@@ -18,6 +18,7 @@
*/
#import "WXDomModule.h"
+#import "WXComponent+Layout.h"
#import "WXDefine.h"
#import "WXSDKManager.h"
#import "WXComponentManager.h"
@@ -54,6 +55,7 @@ WX_EXPORT_METHOD(@selector(updateStyle:styles:))
WX_EXPORT_METHOD(@selector(updateAttrs:attrs:))
WX_EXPORT_METHOD(@selector(addRule:rule:))
WX_EXPORT_METHOD(@selector(getComponentRect:callback:))
+WX_EXPORT_METHOD(@selector(getLayoutDirection:callback:))
WX_EXPORT_METHOD(@selector(updateComponentData:componentData:callback:))
WX_EXPORT_METHOD(@selector(beginBatchMark))
WX_EXPORT_METHOD(@selector(endBatchMark))
@@ -261,6 +263,30 @@ WX_EXPORT_METHOD(@selector(endBatchMark))
}];
}
+- (void)getLayoutDirection:(NSString*)ref callback:(WXModuleKeepAliveCallback)callback {
+ [self performBlockOnComponentManager:^(WXComponentManager * manager) {
+ if ([ref isEqualToString:@"viewport"]) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSString *direction = [WXUtility getEnvLayoutDirection] == WXLayoutDirectionRTL ? @"rtl" : @"ltr";
+ if (callback) {
+ callback(direction, false);
+ }
+ });
+ } else {
+ WXComponent *component = [manager componentForRef:ref];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSString *direction = @"unknow";
+ if (component) {
+ direction = [component isDirectionRTL] ? @"rtl" : @"ltr";
+ }
+ if (callback) {
+ callback(direction, false);
+ }
+ });
+ }
+ }];
+}
+
- (void)updateComponentData:(NSString*)componentDataId componentData:(NSDictionary*)componentData callback:(NSString*)callbackId
{
NSString *recycleListComponentRef = [[componentDataId componentsSeparatedByString:@"@"] objectAtIndex:0];
diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXScrollerProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXScrollerProtocol.h
index 6cbb245..9b72ba3 100644
--- a/ios/sdk/WeexSDK/Sources/Protocol/WXScrollerProtocol.h
+++ b/ios/sdk/WeexSDK/Sources/Protocol/WXScrollerProtocol.h
@@ -73,7 +73,13 @@
- (WXScrollDirection)scrollDirection;
@optional
+
- (NSString*)refreshType;
- (BOOL)requestGestureShouldStopPropagation:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
+/**
+ * @abstract adjust for RTL
+ */
+- (void)adjustForRTL;
+
@end
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXType.h b/ios/sdk/WeexSDK/Sources/Utility/WXType.h
index a33b9cc..2ef5c84 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXType.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXType.h
@@ -20,6 +20,12 @@
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
+typedef NS_ENUM(NSUInteger, WXLayoutDirection) {
+ WXLayoutDirectionLTR,
+ WXLayoutDirectionRTL,
+ WXLayoutDirectionAuto,
+};
+
typedef NS_ENUM(NSUInteger, WXComponentType) {
WXComponentTypeCommon = 0,
WXComponentTypeVirtual
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
index 601727a..730c560 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
@@ -131,6 +131,8 @@ _Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector);
+ (NSDictionary *_Nonnull)getDebugEnvironment;
++ (WXLayoutDirection)getEnvLayoutDirection;
+
/**
* @abstract UserAgent Generation
*
@@ -489,6 +491,10 @@ BOOL WXFloatGreaterThanWithPrecision(CGFloat a,CGFloat b,double precision);
+ (BOOL)useJSCApiForCreateInstance;
++ (void)setEnableRTLLayoutDirection:(BOOL)value;
+
++ (BOOL)enableRTLLayoutDirection;
+
+ (long) getUnixFixTimeMillis;
+ (NSArray<NSString *> *_Nullable)extractPropertyNamesOfJSValueObject:(JSValue *_Nullable)jsvalue;
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m
index 121a73c..b070a87 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m
@@ -44,6 +44,7 @@
static BOOL unregisterFontWhenCollision = NO;
static BOOL useJSCApiForCreateInstance = YES;
+static BOOL enableRTLLayoutDirection = YES;
void WXPerformBlockOnMainThread(void (^ _Nonnull block)(void))
{
@@ -173,6 +174,18 @@ CGFloat WXFloorPixelValue(CGFloat value)
block();
}
++ (WXLayoutDirection)getEnvLayoutDirection {
+ // We not use the below technique, because your app maybe not support the first preferredLanguages
+ // _sysLayoutDirection = [NSLocale characterDirectionForLanguage:[[NSLocale preferredLanguages] objectAtIndex:0]] == NSLocaleLanguageDirectionRightToLeft ? WXLayoutDirectionRTL : WXLayoutDirectionLTR;
+ if (@available(iOS 9.0, *)) {
+ // The view is shown in right-to-left mode right now.
+ return [UIView userInterfaceLayoutDirectionForSemanticContentAttribute:UISemanticContentAttributeUnspecified] == UIUserInterfaceLayoutDirectionRightToLeft ? WXLayoutDirectionRTL : WXLayoutDirectionLTR;
+ } else {
+ // Use the previous technique
+ return [[UIApplication sharedApplication] userInterfaceLayoutDirection] == UIUserInterfaceLayoutDirectionRightToLeft ? WXLayoutDirectionRTL : WXLayoutDirectionLTR;
+ }
+}
+
+ (NSDictionary *)getEnvironment
{
NSString *platform = @"iOS";
@@ -197,7 +210,8 @@ CGFloat WXFloorPixelValue(CGFloat value)
@"deviceWidth":@(deviceWidth * scale),
@"deviceHeight":@(deviceHeight * scale),
@"scale":@(scale),
- @"logLevel":[WXLog logLevelString] ?: @"error"
+ @"logLevel":[WXLog logLevelString] ?: @"error",
+ @"layoutDirection": [self getEnvLayoutDirection] == WXLayoutDirectionRTL ? @"rtl" : @"ltr"
}];
if ([[[UIDevice currentDevice] systemVersion] integerValue] >= 11) {
@@ -736,6 +750,17 @@ CGFloat WXFloorPixelValue(CGFloat value)
return defaultScaleFactor;
}
+#pragma mark - RTL
+
++ (void)setEnableRTLLayoutDirection:(BOOL)value
+{
+ enableRTLLayoutDirection = value;
+}
+
++ (BOOL)enableRTLLayoutDirection
+{
+ return enableRTLLayoutDirection;
+}
#pragma mark - get deviceID
+ (NSString *)getDeviceID {
diff --git a/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.mm b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.mm
index ad17890..98cf737 100644
--- a/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.mm
+++ b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.mm
@@ -263,6 +263,7 @@ do {\
WXTransform* transform = [[WXTransform alloc] initWithCSSValue:[WXConvert NSString:styles[@"transform"]] origin:[WXConvert NSString:transformOrigin] instance:self.weexInstance];
if (!CGRectEqualToRect(self.calculatedFrame, CGRectZero)) {
[transform applyTransformForView:_view];
+ [self _adjustForRTL];
[_layer setNeedsDisplay];
}
self.transform = transform;
@@ -270,9 +271,14 @@ do {\
[_transform setTransformOrigin:[WXConvert NSString:styles[@"transformOrigin"]]];
if (!CGRectEqualToRect(self.calculatedFrame, CGRectZero)) {
[_transform applyTransformForView:_view];
+ [self _adjustForRTL];
[_layer setNeedsDisplay];
}
}
+ // for RTL
+ if (styles[@"direction"]) {
+ [self _adjustForRTL];
+ }
}
- (void)resetBorder:(NSArray *)styles
diff --git a/weex_core/Source/android/jniprebuild/jniheader/NativeRenderObjectUtils_jni.h b/weex_core/Source/android/jniprebuild/jniheader/NativeRenderObjectUtils_jni.h
index 55eefa2..78c51c7 100644
--- a/weex_core/Source/android/jniprebuild/jniheader/NativeRenderObjectUtils_jni.h
+++ b/weex_core/Source/android/jniprebuild/jniheader/NativeRenderObjectUtils_jni.h
@@ -50,6 +50,9 @@ static void AddChildRenderObject(JNIEnv* env, jclass jcaller,
jlong parent,
jlong child);
+static jint RenderObjectGetLayoutDirectionFromPathNode(JNIEnv* env, jclass jcaller,
+ jlong ptr);
+
static jboolean RenderObjectHasNewLayout(JNIEnv* env, jclass jcaller,
jlong ptr);
@@ -147,6 +150,11 @@ static const JNINativeMethod kMethodsNativeRenderObjectUtils[] = {
"J"
")"
"V", reinterpret_cast<void*>(AddChildRenderObject) },
+ { "nativeRenderObjectGetLayoutDirectionFromPathNode",
+"("
+"J"
+")"
+"I", reinterpret_cast<void*>(RenderObjectGetLayoutDirectionFromPathNode) },
{ "nativeRenderObjectHasNewLayout",
"("
"J"
diff --git a/weex_core/Source/android/utils/params_utils.cpp b/weex_core/Source/android/utils/params_utils.cpp
index be663ee..47651ef 100644
--- a/weex_core/Source/android/utils/params_utils.cpp
+++ b/weex_core/Source/android/utils/params_utils.cpp
@@ -293,6 +293,22 @@ std::vector<INIT_FRAMEWORK_PARAMS*> initFromParam(
ADDSTRING(appVersion);
env->DeleteLocalRef(appVersion);
+ jmethodID m_layoutDirection =
+ env->GetMethodID(c_params, "getLayoutDirection", "()Ljava/lang/String;");
+ if (m_layoutDirection == nullptr) {
+ ADDSTRING(nullptr);
+ ReportNativeInitStatus("-1012", "get m_layoutDirection failed");
+ return initFrameworkParams;
+ }
+ jobject layoutDirection = env->CallObjectMethod(params, m_layoutDirection);
+ if (layoutDirection == nullptr) {
+ ADDSTRING(nullptr);
+ ReportNativeInitStatus("-1012", "get layoutDirection failed");
+ return initFrameworkParams;
+ }
+ ADDSTRING(layoutDirection);
+ env->DeleteLocalRef(layoutDirection);
+
jmethodID m_weexVersion =
env->GetMethodID(c_params, "getWeexVersion", "()Ljava/lang/String;");
if (m_weexVersion == nullptr) {
diff --git a/weex_core/Source/android/wrap/native_render_object_utils_impl_android.cpp b/weex_core/Source/android/wrap/native_render_object_utils_impl_android.cpp
index 5565075..8b6d9f1 100644
--- a/weex_core/Source/android/wrap/native_render_object_utils_impl_android.cpp
+++ b/weex_core/Source/android/wrap/native_render_object_utils_impl_android.cpp
@@ -128,8 +128,11 @@ static jint LayoutRenderObject(JNIEnv* env, jclass jcaller,
return (jint)render->getLayoutHeight();
}
-
-
+static jint RenderObjectGetLayoutDirectionFromPathNode(JNIEnv* env, jclass jcaller,
+ jlong ptr){
+ RenderObject* renderObject = convert_long_to_render_object(ptr);
+ return renderObject->getLayoutDirectionFromPathNode();
+}
static jboolean RenderObjectHasNewLayout(JNIEnv* env, jclass jcaller,
jlong ptr){
diff --git a/weex_core/Source/core/css/constants_name.h b/weex_core/Source/core/css/constants_name.h
index 48b8a59..fe282cc 100644
--- a/weex_core/Source/core/css/constants_name.h
+++ b/weex_core/Source/core/css/constants_name.h
@@ -23,6 +23,7 @@
#include <string>
namespace WeexCore {
+ constexpr char DIRECTION[] = "direction";
constexpr char FLEX[] = "flex";
constexpr char HORIZONTAL[] = "horizontal";
diff --git a/weex_core/Source/core/css/constants_value.h b/weex_core/Source/core/css/constants_value.h
index d51ebb5..b2a1862 100644
--- a/weex_core/Source/core/css/constants_value.h
+++ b/weex_core/Source/core/css/constants_value.h
@@ -23,6 +23,10 @@
#include <string>
namespace WeexCore {
+ // direction
+ constexpr char RTL[] = "rtl";
+ constexpr char LTR[] = "ltr";
+ constexpr char INHERIT[] = "inherit";
// flex-direction
constexpr char ROW[] = "row";
diff --git a/weex_core/Source/core/css/css_value_getter.cpp b/weex_core/Source/core/css/css_value_getter.cpp
index f576245..a60529f 100644
--- a/weex_core/Source/core/css/css_value_getter.cpp
+++ b/weex_core/Source/core/css/css_value_getter.cpp
@@ -24,6 +24,17 @@
#include "core/layout/style.h"
namespace WeexCore {
+ const WXCoreDirection GetWXCoreDirection(const std::string &value) {
+ const char *c_value = value.c_str();
+ if(strcmp(c_value, INHERIT) == 0) {
+ return WeexCore::kDirectionInherit;
+ } else if (strcmp(c_value, LTR) == 0) {
+ return WeexCore::kDirectionLTR;
+ } else if (strcmp(c_value, RTL) == 0) {
+ return WeexCore::kDirectionRTL;
+ }
+ return WeexCore::kDirectionLTR;
+ }
const WXCoreFlexDirection GetWXCoreFlexDirection(const std::string &value) {
const char *c_value = value.c_str();
diff --git a/weex_core/Source/core/css/css_value_getter.h b/weex_core/Source/core/css/css_value_getter.h
index f47abc1..ec630ca 100644
--- a/weex_core/Source/core/css/css_value_getter.h
+++ b/weex_core/Source/core/css/css_value_getter.h
@@ -23,6 +23,7 @@
#include <string>
namespace WeexCore {
+ const WXCoreDirection GetWXCoreDirection(const std::string &value);
const WXCoreFlexDirection GetWXCoreFlexDirection(const std::string &value);
diff --git a/weex_core/Source/core/layout/flex_enum.h b/weex_core/Source/core/layout/flex_enum.h
index 9eb3676..6f63e99 100644
--- a/weex_core/Source/core/layout/flex_enum.h
+++ b/weex_core/Source/core/layout/flex_enum.h
@@ -16,13 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
+
#ifdef __cplusplus
#ifndef WEEXCORE_FLEXLAYOUT_WXCOREFLEXENUM_H
#define WEEXCORE_FLEXLAYOUT_WXCOREFLEXENUM_H
-namespace WeexCore {
+#define WEEXCORE_CSS_DEFAULT_DIRECTION kDirectionLTR
+namespace WeexCore {
+ /**
+ * MainAxis direction
+ */
+ enum WXCoreDirection {
+ kDirectionInherit,
+ kDirectionLTR,
+ kDirectionRTL
+ };
/**
* MainAxis direction
*/
diff --git a/weex_core/Source/core/layout/layout.cpp b/weex_core/Source/core/layout/layout.cpp
index 6b7a290..8ffdf48 100644
--- a/weex_core/Source/core/layout/layout.cpp
+++ b/weex_core/Source/core/layout/layout.cpp
@@ -645,21 +645,39 @@ namespace WeexCore {
void WXCoreLayoutNode::onLayout(const float left, const float top, const float right, const float bottom,
WXCoreLayoutNode *const absoulteItem, WXCoreFlexLine *const flexLine) {
- switch (mCssStyle->mFlexDirection) {
- case kFlexDirectionRow:
- layoutHorizontal(false, left, top, right, bottom, absoulteItem, flexLine);
- break;
- case kFlexDirectionRowReverse:
- layoutHorizontal(true, left, top, right, bottom, absoulteItem, flexLine);
- break;
- case kFlexDirectionColumnReverse:
- layoutVertical(mCssStyle->mFlexWrap == kWrapReverse, true, left, top, right, bottom, absoulteItem, flexLine);
- break;
- case kFlexDirectionColumn:
- default:
- layoutVertical(mCssStyle->mFlexWrap == kWrapReverse, false, left, top, right, bottom, absoulteItem, flexLine);
- break;
- }
+ // determin direction
+ if (mLayoutResult->mLayoutDirection == kDirectionInherit) {
+ if(mCssStyle->mDirection == kDirectionInherit) {
+ // default direction in css is inherit, inherit direction from parent node
+ mLayoutResult->mLayoutDirection = NULL == mParent ? WEEXCORE_CSS_DEFAULT_DIRECTION : mParent->getLayoutDirection();
+ } else {
+ // specific direction in current Node's style
+ mLayoutResult->mLayoutDirection = mCssStyle->mDirection;
+ }
+ }
+
+ bool verticalRTL = false;
+ if (mCssStyle->mFlexWrap != kNoWrap && mLayoutResult->mLayoutDirection == kDirectionRTL) {
+ verticalRTL = mCssStyle->mFlexWrap != kWrapReverse;
+ } else {
+ verticalRTL = mCssStyle->mFlexWrap == kWrapReverse;
+ }
+
+ switch (mCssStyle->mFlexDirection) {
+ case kFlexDirectionRow:
+ layoutHorizontal(mLayoutResult->mLayoutDirection == kDirectionRTL, left, top, right, bottom, absoulteItem, flexLine);
+ break;
+ case kFlexDirectionRowReverse:
+ layoutHorizontal(mLayoutResult->mLayoutDirection != kDirectionRTL, left, top, right, bottom, absoulteItem, flexLine);
+ break;
+ case kFlexDirectionColumnReverse:
+ layoutVertical(verticalRTL, true, left, top, right, bottom, absoulteItem, flexLine);
+ break;
+ case kFlexDirectionColumn:
+ default:
+ layoutVertical(verticalRTL, false, left, top, right, bottom, absoulteItem, flexLine);
+ break;
+ }
}
/**
@@ -1083,6 +1101,34 @@ namespace WeexCore {
break;
}
}
+ void WXCoreLayoutNode::determineChildLayoutDirection(const WXCoreDirection direction) {
+ for (Index i = 0; i < getChildCount(kBFC); ++i) {
+ WXCoreLayoutNode *child = getChildAt(kBFC, i);
+ // determin direction
+ if (child->mLayoutResult->mLayoutDirection == kDirectionInherit) {
+ if(child->mCssStyle->mDirection == kDirectionInherit) {
+ // default direction in css is inherit, inherit direction from parent node
+ child->mLayoutResult->mLayoutDirection = direction;
+ } else {
+ // specific direction in current Node's style
+ child->mLayoutResult->mLayoutDirection = child->mCssStyle->mDirection;
+ }
+ }
+ }
+ }
+
+ WXCoreDirection WXCoreLayoutNode::getLayoutDirectionFromPathNode() {
+ WXCoreLayoutNode *node = this;
+ if (node->getLayoutDirection() != kDirectionInherit) return node->getLayoutDirection();
+ if (node->getDirection() != kDirectionInherit) {
+ node->mLayoutResult->mLayoutDirection = node->getDirection();
+ return node->getLayoutDirection();
+ } else if (nullptr != node->mParent) {
+ node->mLayoutResult->mLayoutDirection = node->mParent->getLayoutDirectionFromPathNode();
+ return node->getLayoutDirection();
+ }
+ return WEEXCORE_CSS_DEFAULT_DIRECTION;
+ }
}
diff --git a/weex_core/Source/core/layout/layout.h b/weex_core/Source/core/layout/layout.h
index 9434932..bd748e4 100644
--- a/weex_core/Source/core/layout/layout.h
+++ b/weex_core/Source/core/layout/layout.h
@@ -72,9 +72,10 @@ namespace WeexCore {
};
/**
- * layout-result:layout-height、layout-width、position(left、right、top、bottom)
+ * layout-result:layout-height、layout-width、position(left、right、top、bottom)、direction
*/
struct WXCorelayoutResult {
+ WXCoreDirection mLayoutDirection;
WXCoreSize mLayoutSize;
WXCorePosition mLayoutPosition;
@@ -83,8 +84,9 @@ namespace WeexCore {
}
inline void reset() {
- mLayoutSize.reset();
- mLayoutPosition.reset();
+ mLayoutSize.reset();
+ mLayoutPosition.reset();
+ mLayoutDirection = kDirectionInherit;
}
};
@@ -151,7 +153,6 @@ namespace WeexCore {
mLayoutResult = new WXCorelayoutResult();
}
-
virtual ~WXCoreLayoutNode() {
mIsDestroy = true;
mHasNewLayout = true;
@@ -257,20 +258,22 @@ namespace WeexCore {
inline void setContext(void * const context) {
this->context = context;
}
-
+
inline void copyStyle(WXCoreLayoutNode *srcNode) {
- if (memcmp(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle)) != 0) {
+ if (srcNode != nullptr && memcmp(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle)) != 0) {
memcpy(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle));
markDirty();
}
}
-
+
void copyFrom(WXCoreLayoutNode* srcNode){
- memcpy(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle));
+ if (srcNode == nullptr) return;
+
+ memcpy(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle));
}
inline void copyMeasureFunc(WXCoreLayoutNode *srcNode) {
- if (memcmp(&measureFunc, &srcNode->measureFunc, sizeof(WXCoreMeasureFunc)) != 0) {
+ if (srcNode != nullptr && memcmp(&measureFunc, &srcNode->measureFunc, sizeof(WXCoreMeasureFunc)) != 0) {
memcpy(&measureFunc, &srcNode->measureFunc, sizeof(WXCoreMeasureFunc));
markDirty();
}
@@ -607,8 +610,6 @@ namespace WeexCore {
void positionAbsoluteFlexItem(float &left, float &top, float &right, float &bottom);
- void onLayout(float left, float top, float right, float bottom, WXCoreLayoutNode* = nullptr, WXCoreFlexLine *const flexLine = nullptr);
-
void layoutHorizontal(bool isRtl, float left, float top, float right, float bottom,
WXCoreLayoutNode*, WXCoreFlexLine *const flexLine);
@@ -668,7 +669,7 @@ namespace WeexCore {
public:
-
+ virtual void onLayout(float left, float top, float right, float bottom, WXCoreLayoutNode* = nullptr, WXCoreFlexLine *const flexLine = nullptr);
/** ================================ tree =================================== **/
inline Index getChildCount(FormattingContext formattingContext) const {
@@ -972,7 +973,33 @@ namespace WeexCore {
return mCssStyle->mMaxHeight;
}
+ inline void setDirection(const WXCoreDirection direction, const bool updating) {
+ if (nullptr == mCssStyle) return;
+
+ if (mCssStyle->mDirection != direction) {
+ mCssStyle->mDirection = direction;
+ markDirty();
+ if (updating) {
+ for (auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) {
+ (*it)->markInheritableDirty();
+ }
+ }
+ }
+ }
+ inline WXCoreDirection getDirection() const {
+ if (mCssStyle == nullptr) {
+ return WEEXCORE_CSS_DEFAULT_DIRECTION;
+ }
+ return mCssStyle->mDirection;
+ }
+
+ /** ================================ CSS direction For RTL =================================== **/
+
+ void determineChildLayoutDirection(const WXCoreDirection direction);
+
+ WXCoreDirection getLayoutDirectionFromPathNode();
+
/** ================================ flex-style =================================== **/
inline void setFlexDirection(const WXCoreFlexDirection flexDirection, const bool updating) {
@@ -1070,7 +1097,18 @@ namespace WeexCore {
inline float getLayoutPositionRight() const {
return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeRight);
}
+
+ virtual inline WXCoreDirection getLayoutDirection() const {
+ if (nullptr == mLayoutResult) {
+ return WEEXCORE_CSS_DEFAULT_DIRECTION;
+ }
+ return mLayoutResult->mLayoutDirection;
+ }
+ inline void setLayoutDirection(WXCoreDirection direction) {
+ if (nullptr == mLayoutResult) return;
+ mLayoutResult->mLayoutDirection = direction;
+ }
inline bool hasNewLayout() const {
return mHasNewLayout;
}
@@ -1114,6 +1152,38 @@ namespace WeexCore {
return ret;
}
+ void markInheritableDirty() {
+ if (resetInheritableSet()) {
+ // if some style was inherited from parent, reset those styles
+ // then mark self dirty
+ markDirty(false);
+
+ // traverse children to mark dirty
+ if(getChildCount() == 0){
+ return;
+ }
+ else {
+ for (auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) {
+ (*it)->markInheritableDirty();
+ }
+ }
+ }
+ }
+
+ /**
+ * if some style was inherited from parent, reset those styles, then return true, eles return false
+ */
+ bool resetInheritableSet() {
+ if (mCssStyle == nullptr || mLayoutResult == nullptr) return false;
+
+ bool hasInheritedStyle = false;
+ if (mCssStyle->mDirection == kDirectionInherit) {
+ mLayoutResult->mLayoutDirection = kDirectionInherit;
+ hasInheritedStyle = true;
+ }
+ return hasInheritedStyle;
+ }
+
inline void setHasNewLayout(const bool hasNewLayout) {
this->mHasNewLayout = hasNewLayout;
}
diff --git a/weex_core/Source/core/layout/style.h b/weex_core/Source/core/layout/style.h
index a5c5f7e..5c9ca89 100644
--- a/weex_core/Source/core/layout/style.h
+++ b/weex_core/Source/core/layout/style.h
@@ -201,6 +201,8 @@ namespace WeexCore {
WXCoreAlignSelf mAlignSelf;
WXCorePositionType mPositionType;
+
+ WXCoreDirection mDirection;
float mFlexGrow;
@@ -242,7 +244,8 @@ namespace WeexCore {
constexpr static WXCorePositionType kWXCorePositionTypeDefault = kRelative;
- WXCoreCSSStyle() : mFlexDirection(kFlexDirectionDefault),
+ WXCoreCSSStyle() : mDirection(kDirectionInherit),
+ mFlexDirection(kFlexDirectionDefault),
mFlexWrap(kFlexWrapDefault),
mJustifyContent(kFlexJustifyContentDefault),
mAlignItems(kFlexAlignItemsDefault),
@@ -257,6 +260,7 @@ namespace WeexCore {
}
~WXCoreCSSStyle() {
+ mDirection = kDirectionInherit;
mFlexDirection = kFlexDirectionDefault;
mFlexWrap = kFlexWrapDefault;
mJustifyContent = kFlexJustifyContentDefault;
diff --git a/weex_core/Source/core/render/node/render_object.cpp b/weex_core/Source/core/render/node/render_object.cpp
index ffc8388..ba547a7 100644
--- a/weex_core/Source/core/render/node/render_object.cpp
+++ b/weex_core/Source/core/render/node/render_object.cpp
@@ -160,6 +160,13 @@ StyleType RenderObject::ApplyStyle(const std::string &key,
}
}
return kTypeLayout;
+ } else if (key == DIRECTION) {
+ WeexCore::WXCoreDirection direction = GetWXCoreDirection(value);
+ if (direction == WeexCore::kDirectionInherit && this->is_root_render_ ) {
+ direction = WeexCore::kDirectionLTR;
+ }
+ setDirection(direction, updating);
+ return kTypeInheritableLayout;
} else if (key == FLEX_DIRECTION) {
setFlexDirection(GetWXCoreFlexDirection(value), updating);
return kTypeLayout;
diff --git a/weex_core/Source/core/render/node/render_object.h b/weex_core/Source/core/render/node/render_object.h
index 5242a64..9522d9d 100644
--- a/weex_core/Source/core/render/node/render_object.h
+++ b/weex_core/Source/core/render/node/render_object.h
@@ -44,7 +44,8 @@ typedef enum StyleType {
kTypeLayout,
kTypeMargin,
kTypePadding,
- kTypeBorder
+ kTypeBorder,
+ kTypeInheritableLayout
} StyleType;
class RenderObject : public IRenderObject {
diff --git a/weex_core/Source/core/render/node/render_scroller.cpp b/weex_core/Source/core/render/node/render_scroller.cpp
index 05e67e2..03d0b8d 100644
--- a/weex_core/Source/core/render/node/render_scroller.cpp
+++ b/weex_core/Source/core/render/node/render_scroller.cpp
@@ -52,4 +52,11 @@ void RenderScroller::set_flex(const float flex) {
this->is_set_flex_ = true;
WXCoreLayoutNode::set_flex(flex);
}
+
+ void RenderScroller::onLayout(const float left, const float top, const float right, const float bottom,
+ WXCoreLayoutNode *const absoulteItem, WXCoreFlexLine *const flexLine) {
+ // In scroller only use left to right direction to caculate children frame
+ this->setLayoutDirection(kDirectionLTR);
+ RenderObject::onLayout(left, top, right, bottom, absoulteItem, flexLine);
+ }
} // namespace WeexCore
diff --git a/weex_core/Source/core/render/node/render_scroller.h b/weex_core/Source/core/render/node/render_scroller.h
index 59a35df..1cf6fc6 100644
--- a/weex_core/Source/core/render/node/render_scroller.h
+++ b/weex_core/Source/core/render/node/render_scroller.h
@@ -37,6 +37,24 @@ class RenderScroller : public RenderObject {
const float ¤t_length) const override {
return NAN;
}
+
+protected:
+ void onLayout(const float left, const float top, const float right, const float bottom,
+ WXCoreLayoutNode *const absoulteItem, WXCoreFlexLine *const flexLine) override;
+
+ // Since scroll only use ltr to layout children actually,
+ // so we need override this method to return calculated inherit direction as normal render_object do
+ inline WXCoreDirection getLayoutDirection() const override {
+ WXCoreDirection styleDirection = this->getDirection();
+ if (styleDirection != kDirectionInherit) {
+ return styleDirection;
+ } else if (this->getParent() != nullptr) {
+ WXCoreLayoutNode *parent = this->getParent();
+ return parent->getLayoutDirection();
+ }
+ return WEEXCORE_CSS_DEFAULT_DIRECTION;
+ }
+
};
} // namespace WeexCore
#endif // CORE_RENDER_NODE_RENDER_SCROLLER_H_
diff --git a/weex_core/Source/core/render/page/render_page.cpp b/weex_core/Source/core/render/page/render_page.cpp
index d54fade..875cd3d 100644
--- a/weex_core/Source/core/render/page/render_page.cpp
+++ b/weex_core/Source/core/render/page/render_page.cpp
@@ -221,7 +221,8 @@ bool RenderPage::UpdateStyle(
std::vector<std::pair<std::string, std::string>> *margin = nullptr;
std::vector<std::pair<std::string, std::string>> *padding = nullptr;
std::vector<std::pair<std::string, std::string>> *border = nullptr;
-
+ bool inheriableLayout = false;
+
bool flag = false;
int result =
WeexCoreManager::Instance()
@@ -277,13 +278,16 @@ bool RenderPage::UpdateStyle(
flag = true;
});
break;
+ case kTypeInheritableLayout:
+ inheriableLayout = true;
+ break;
default: break;
}
}
}
if (style != nullptr || margin != nullptr || padding != nullptr ||
- border != nullptr)
+ border != nullptr || inheriableLayout)
SendUpdateStyleAction(render, style, margin, padding, border);
Batch();
diff --git a/weex_core/release.sh b/weex_core/release.sh
old mode 100644
new mode 100755