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/12/07 02:58:01 UTC

[incubator-weex] branch master updated: [WEEX-673][weex_core][iOS][Android] fix crash && advance RTL performance (#1860)

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 5a52f04  [WEEX-673][weex_core][iOS][Android] fix crash && advance RTL performance (#1860)
5a52f04 is described below

commit 5a52f042acd357d763d76c88a5a993e9c33e43ad
Author: Klueze <hz...@gmail.com>
AuthorDate: Fri Dec 7 10:57:55 2018 +0800

    [WEEX-673][weex_core][iOS][Android] fix crash && advance RTL performance (#1860)
    
    * [iOS][android][weex_core] don't read layoutDirection manually,only receive param.
---
 .../main/java/com/taobao/weex/bridge/WXBridge.java |  4 +-
 .../com/taobao/weex/bridge/WXBridgeManager.java    |  5 ++-
 .../java/com/taobao/weex/common/IWXBridge.java     |  2 +-
 .../measurefunc/TextContentBoxMeasurement.java     | 24 ++++++++++-
 .../weex/ui/action/GraphicActionAddElement.java    |  8 ++++
 .../taobao/weex/ui/action/GraphicActionLayout.java |  5 ++-
 .../weex/ui/component/AbstractEditComponent.java   | 16 ++++++-
 .../com/taobao/weex/ui/component/WXComponent.java  | 49 +++++++++-------------
 .../com/taobao/weex/ui/component/WXScroller.java   |  8 ++--
 .../com/taobao/weex/ui/component/WXSlider.java     |  4 +-
 .../java/com/taobao/weex/ui/component/WXText.java  | 17 ++++++++
 .../weex/ui/component/basic/WXBasicComponent.java  |  9 ++++
 .../weex/ui/component/list/BasicListComponent.java |  4 +-
 .../weex/ui/component/list/GapItemDecoration.java  |  4 +-
 ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h      |  2 +-
 ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm     |  8 ++--
 .../Sources/Component/WXComponent_internal.h       |  1 +
 .../Sources/Component/WXCycleSliderComponent.mm    |  3 +-
 .../WeexSDK/Sources/Component/WXEditComponent.mm   | 15 ++++++-
 .../WeexSDK/Sources/Component/WXTextComponent.mm   | 25 +++++++----
 .../WeexSDK/Sources/Layout/WXComponent+Layout.h    |  3 ++
 .../WeexSDK/Sources/Layout/WXComponent+Layout.mm   | 40 +++++++++++++-----
 .../WeexSDK/Sources/Manager/WXComponentManager.h   |  2 +-
 .../WeexSDK/Sources/Manager/WXComponentManager.mm  |  3 +-
 .../android/bridge/platform/android_side.cpp       |  4 +-
 .../Source/android/bridge/platform/android_side.h  |  2 +-
 .../android/jniprebuild/jniheader/WXBridge_jni.h   |  4 +-
 weex_core/Source/android/wrap/wx_bridge.cpp        |  4 +-
 weex_core/Source/android/wrap/wx_bridge.h          |  2 +-
 weex_core/Source/core/bridge/platform_bridge.h     |  2 +-
 weex_core/Source/core/layout/layout.cpp            | 19 ++++-----
 .../core/render/action/render_action_layout.cpp    |  3 +-
 .../core/render/action/render_action_layout.h      |  1 +
 33 files changed, 204 insertions(+), 98 deletions(-)

diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
index 28ffa3b..de3db66 100644
--- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
@@ -519,10 +519,10 @@ public class WXBridge implements IWXBridge {
 
   @Override
   @CalledByNative
-  public int callLayout(String instanceId, String ref, int top, int bottom, int left, int right, int height, int width, int index) {
+  public int callLayout(String instanceId, String ref, int top, int bottom, int left, int right, int height, int width, boolean isRTL, int index) {
     int errorCode = IWXBridge.INSTANCE_RENDERING;
     try {
-      errorCode = WXBridgeManager.getInstance().callLayout(instanceId, ref, top, bottom, left, right, height, width, index);
+      errorCode = WXBridgeManager.getInstance().callLayout(instanceId, ref, top, bottom, left, right, height, width, isRTL, index);
     } catch (Throwable e) {
       //catch everything during call native.
       if (WXEnvironment.isApkDebugable()) {
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 8842bc3..71f5a99 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
@@ -2750,7 +2750,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
     return IWXBridge.INSTANCE_RENDERING;
   }
 
-  public int callLayout(String pageId, String ref, int top, int bottom, int left, int right, int height, int width, int index) {
+  public int callLayout(String pageId, String ref, int top, int bottom, int left, int right, int height, int width, boolean isRTL, int index) {
 
     if (TextUtils.isEmpty(pageId) || TextUtils.isEmpty(ref)) {
         if (WXEnvironment.isApkDebugable()){
@@ -2785,6 +2785,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
         GraphicPosition position = new GraphicPosition(left, top, right, bottom);
         GraphicActionAddElement addAction = instance.getInActiveAddElementAction(ref);
         if(addAction!=null) {
+          addAction.setRTL(isRTL);
           addAction.setSize(size);
           addAction.setPosition(position);
           if(!TextUtils.equals(ref, WXComponent.ROOT)) {
@@ -2794,7 +2795,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
           instance.removeInActiveAddElmentAction(ref);
         }
         else {
-          final BasicGraphicAction action = new GraphicActionLayout(instance, ref, position, size);
+          final BasicGraphicAction action = new GraphicActionLayout(instance, ref, position, size, isRTL);
           WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
         }
       }
diff --git a/android/sdk/src/main/java/com/taobao/weex/common/IWXBridge.java b/android/sdk/src/main/java/com/taobao/weex/common/IWXBridge.java
index c998fe5..40c484f 100644
--- a/android/sdk/src/main/java/com/taobao/weex/common/IWXBridge.java
+++ b/android/sdk/src/main/java/com/taobao/weex/common/IWXBridge.java
@@ -148,7 +148,7 @@ public interface IWXBridge extends IWXObject {
   int callUpdateAttrs(String instanceId, String ref,
                       HashMap<String, String> attrs);
 
-  int callLayout(String instanceId, String ref, int top, int bottom, int left, int right, int height, int width, int index);
+  int callLayout(String instanceId, String ref, int top, int bottom, int left, int right, int height, int width, boolean isRTL, int index);
 
   int callCreateFinish(String instanceId);
 
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 ef0ccb0..8fdf501 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
@@ -36,6 +36,9 @@ import android.text.TextUtils;
 import android.text.style.AbsoluteSizeSpan;
 import android.text.style.AlignmentSpan;
 import android.text.style.ForegroundColorSpan;
+import android.support.annotation.RestrictTo;
+import android.support.annotation.RestrictTo.Scope;
+import android.support.annotation.WorkerThread;
 
 import com.taobao.weex.WXSDKManager;
 import com.taobao.weex.common.Constants;
@@ -203,6 +206,25 @@ public class TextContentBoxMeasurement extends ContentBoxMeasurement {
   }
 
   /**
+   * Force relayout the text, the text must layout before invoke this method.
+   *
+   * Internal method, do not invoke unless you what what you are doing
+   * @param isRTL
+   */
+  @RestrictTo(Scope.LIBRARY)
+  @WorkerThread
+  public void forceRelayout(){
+    //Generate Spans
+    layoutBefore();
+
+    //Measure
+    measure(previousWidth, Float.NaN, MeasureMode.EXACTLY, MeasureMode.UNSPECIFIED);
+
+    //Swap text layout to UI Thread
+    layoutAfter(previousWidth, Float.NaN);
+  }
+
+  /**
    * Record the property according to the given style
    *
    * @param style the give style.
@@ -232,7 +254,7 @@ public class TextContentBoxMeasurement extends ContentBoxMeasurement {
       if (style.containsKey(Constants.Name.FONT_FAMILY)) {
         mFontFamily = WXStyle.getFontFamily(style);
       }
-      mAlignment = WXStyle.getTextAlignment(style, mComponent.isNativeLayoutRTL());
+      mAlignment = WXStyle.getTextAlignment(style, mComponent.isLayoutRTL());
       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/GraphicActionAddElement.java b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionAddElement.java
index c20a1ac..2a3b5da 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionAddElement.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionAddElement.java
@@ -46,6 +46,7 @@ public class GraphicActionAddElement extends GraphicActionAbstractAddElement {
   private WXComponent child;
   private GraphicPosition layoutPosition;
   private GraphicSize layoutSize;
+  private boolean isLayoutRTL;
 
   public GraphicActionAddElement(@NonNull WXSDKInstance instance, String ref,
                                  String componentType, String parentRef,
@@ -147,6 +148,12 @@ public class GraphicActionAddElement extends GraphicActionAbstractAddElement {
 
   @RestrictTo(Scope.LIBRARY)
   @WorkerThread
+  public void setRTL(boolean isRTL){
+    this.isLayoutRTL = isRTL;
+  }
+
+  @RestrictTo(Scope.LIBRARY)
+  @WorkerThread
   public void setSize(GraphicSize graphicSize){
     this.layoutSize = graphicSize;
   }
@@ -173,6 +180,7 @@ public class GraphicActionAddElement extends GraphicActionAbstractAddElement {
       parent.addChild(child, mIndex);
       parent.createChildViewAt(mIndex);
 
+      child.setIsLayoutRTL(isLayoutRTL);
       if(layoutPosition !=null && layoutSize != null) {
         child.setDemission(layoutSize, layoutPosition);
       }
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionLayout.java b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionLayout.java
index 24946fe..cffef17 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionLayout.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionLayout.java
@@ -26,11 +26,13 @@ public class GraphicActionLayout extends BasicGraphicAction {
 
   private final GraphicPosition mLayoutPosition;
   private final GraphicSize mLayoutSize;
+  private final boolean mIsLayoutRTL;
 
-  public GraphicActionLayout(WXSDKInstance instance, String ref, GraphicPosition layoutPosition, GraphicSize layoutSize) {
+  public GraphicActionLayout(WXSDKInstance instance, String ref, GraphicPosition layoutPosition, GraphicSize layoutSize, boolean isRTL) {
     super(instance, ref);
     this.mLayoutPosition = layoutPosition;
     this.mLayoutSize = layoutSize;
+    this.mIsLayoutRTL = isRTL;
   }
 
   @Override
@@ -40,6 +42,7 @@ public class GraphicActionLayout extends BasicGraphicAction {
       return;
     }
 
+    component.setIsLayoutRTL(mIsLayoutRTL);
     component.setDemission(mLayoutSize, mLayoutPosition);
     component.setSafeLayout(component);
     component.setPadding(component.getPadding(), component.getBorder());
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/AbstractEditComponent.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/AbstractEditComponent.java
index ce918e6..7c6134f 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/AbstractEditComponent.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/AbstractEditComponent.java
@@ -127,6 +127,18 @@ public abstract class AbstractEditComponent extends WXComponent<WXEditText> {
     });
   }
 
+  @Override
+  protected void layoutDirectionDidChanged(boolean isRTL) {
+    String alignStr = (String) getStyles().get(Constants.Name.TEXT_ALIGN);
+    int textAlign = getTextAlign(alignStr);
+    if (textAlign <= 0) {
+      textAlign = Gravity.START;
+    }
+    if (getHostView() instanceof WXEditText) {
+      getHostView().setGravity(textAlign | getVerticalGravity());
+    }
+  }
+
   protected final float getMeasuredLineHeight() {
     return mLineHeight != UNSET && mLineHeight > 0 ? mLineHeight : mPaint.getFontMetrics(null);
   }
@@ -749,10 +761,12 @@ public abstract class AbstractEditComponent extends WXComponent<WXEditText> {
   }
 
   private int getTextAlign(String textAlign) {
-    int align = Gravity.START;
+    boolean isRTL = isLayoutRTL();
+    int align = isRTL ? Gravity.END : Gravity.START;
     if (TextUtils.isEmpty(textAlign)) {
       return align;
     }
+
     if (textAlign.equals(Constants.Value.LEFT)) {
       align = Gravity.START;
     } else if (textAlign.equals(Constants.Value.CENTER)) {
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 1e1353e..0336013 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
@@ -147,6 +147,7 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
 
   private int mAbsoluteY = 0;
   private int mAbsoluteX = 0;
+  private boolean isLastLayoutDirectionRTL = false;
   @Nullable
   private Set<String> mGestureType;
 
@@ -184,7 +185,7 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
   private boolean waste = false;
   public boolean isIgnoreInteraction = false;
 
-  private ContentBoxMeasurement contentBoxMeasurement;
+  protected ContentBoxMeasurement contentBoxMeasurement;
   private WXTransition mTransition;
   private GraphicSize mPseudoResetGraphicSize;
   @Nullable
@@ -248,35 +249,6 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
       }
   }
 
-  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());
@@ -944,6 +916,13 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
     setMargins(component.getMargin());
     setBorders(component.getBorder());
 
+    boolean isRTL = component.isLayoutRTL();
+    setIsLayoutRTL(isRTL);
+    if (isRTL != component.isLastLayoutDirectionRTL) {
+      component.isLastLayoutDirectionRTL = isRTL;
+      layoutDirectionDidChanged(isRTL);
+    }
+
     parseAnimation();
 
     boolean nullParent = mParent == null;//parent is nullable
@@ -1050,6 +1029,16 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
     }
   }
 
+  /**
+   * layout direction is changed
+   * basic class is a empty implementation
+   * subclass can override this method do some RTL necessary things
+   * such as WXText
+   */
+  protected void layoutDirectionDidChanged(boolean isRTL) {
+
+  }
+
   private void recordInteraction(int realWidth,int realHeight){
     if (!mIsAddElementToTree){
       return;
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 e89aa07..12c79e6 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
@@ -394,7 +394,7 @@ public class WXScroller extends WXVContainer<ViewGroup> implements WXScrollViewL
     } else {
       if (lp instanceof FrameLayout.LayoutParams) {
         FrameLayout.LayoutParams lp_frameLayout = (FrameLayout.LayoutParams) lp;
-        if (this.isNativeLayoutRTL()) {
+        if (isLayoutRTL()) {
           lp_frameLayout.gravity = Gravity.RIGHT | Gravity.TOP;
           lp.setMargins(right, top, left, bottom);
         } else {
@@ -415,7 +415,7 @@ public class WXScroller extends WXVContainer<ViewGroup> implements WXScrollViewL
       return;
     }
     if (component.getHostView() != null) {
-      int layoutDirection = component.isNativeLayoutRTL() ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
+      int layoutDirection = component.isLayoutRTL() ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
       ViewCompat.setLayoutDirection(component.getHostView(), layoutDirection);
     }
     super.setLayout(component);
@@ -489,7 +489,7 @@ public class WXScroller extends WXVContainer<ViewGroup> implements WXScrollViewL
             scrollView.post(new Runnable() {
               @Override
               public void run() {
-                if (isNativeLayoutRTL()) {
+                if (isLayoutRTL()) {
                   int mw = frameLayout.getMeasuredWidth();
                   scrollView.scrollTo(mw, component.getScrollY());
                 } else {
@@ -784,7 +784,7 @@ public class WXScroller extends WXVContainer<ViewGroup> implements WXScrollViewL
 
     int viewYInScroller = component.getAbsoluteY() - getAbsoluteY();
     int viewXInScroller = 0;
-    if (this.isNativeLayoutRTL()) {
+    if (this.isLayoutRTL()) {
       // if layout direction is rtl, we need calculate rtl scroll x;
       if (getInnerView().getChildCount() > 0) {
         int totalWidth = getInnerView().getChildAt(0).getWidth();
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 d003318..eaacf5a 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
@@ -215,7 +215,7 @@ public class WXSlider extends WXVContainer<FrameLayout> {
   @Override
   public void setLayout(WXComponent component) {
     if (mAdapter != null) {
-      mAdapter.setLayoutDirectionRTL(this.isNativeLayoutRTL());
+      mAdapter.setLayoutDirectionRTL(this.isLayoutRTL());
     }
     super.setLayout(component);
   }
@@ -291,7 +291,7 @@ public class WXSlider extends WXVContainer<FrameLayout> {
 
     if (mAdapter.getRealCount() > 0) {
       if(idx >= mAdapter.getRealCount()) retIdx = mAdapter.getRealCount() - 1;
-      if (isNativeLayoutRTL()) {
+      if (isLayoutRTL()) {
         retIdx = mAdapter.getRealCount() - 1 - retIdx;
       }
     }
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXText.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXText.java
index 93905d4..4e4838b 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXText.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXText.java
@@ -219,4 +219,21 @@ public class WXText extends WXComponent<WXTextView> implements FlatComponent<Tex
 
     LocalBroadcastManager.getInstance(WXEnvironment.getApplication()).registerReceiver(mTypefaceObserver, new IntentFilter(TypefaceUtil.ACTION_TYPE_FACE_AVAILABLE));
   }
+
+
+  @Override
+  protected void layoutDirectionDidChanged(boolean isRTL) {
+    forceRelayout();
+  }
+
+  private void forceRelayout(){
+    WXBridgeManager.getInstance().post(new Runnable() {
+      @Override
+      public void run() {
+        if(contentBoxMeasurement instanceof TextContentBoxMeasurement){
+          ((TextContentBoxMeasurement) contentBoxMeasurement).forceRelayout();
+        }
+      }
+    });
+  }
 }
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/basic/WXBasicComponent.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/basic/WXBasicComponent.java
index 6452559..4164475 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/basic/WXBasicComponent.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/basic/WXBasicComponent.java
@@ -39,6 +39,7 @@ public abstract class WXBasicComponent<T extends View> {
   private String mRef;
   private GraphicPosition mLayoutPosition;
   private GraphicSize mLayoutSize;
+  private boolean mIsLayoutRTL;
   private BasicComponentData mBasicComponentData;
 
   private int mViewPortWidth = 750;
@@ -175,6 +176,14 @@ public abstract class WXBasicComponent<T extends View> {
     return mRef;
   }
 
+  public void setIsLayoutRTL(boolean isRTL) {
+    mIsLayoutRTL = isRTL;
+  }
+
+  public boolean isLayoutRTL() {
+    return mIsLayoutRTL;
+  }
+
   public GraphicPosition getLayoutPosition() {
     if (mLayoutPosition == null) {
       mLayoutPosition = new GraphicPosition(0, 0, 0, 0);
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 c994707..b3546d1 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
@@ -183,7 +183,7 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
     } else {
       if (lp instanceof FrameLayout.LayoutParams) {
         FrameLayout.LayoutParams lp_frameLayout = (FrameLayout.LayoutParams) lp;
-        if (this.isNativeLayoutRTL()) {
+        if (this.isLayoutRTL()) {
           lp_frameLayout.gravity = Gravity.RIGHT | Gravity.TOP;
           lp.setMargins(right, top, left, bottom);
         } else {
@@ -199,7 +199,7 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
   @Override
   public void setLayout(WXComponent component) {
     if (component.getHostView() != null) {
-      int layoutDirection = component.isNativeLayoutRTL() ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
+      int layoutDirection = component.isLayoutRTL() ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
       ViewCompat.setLayoutDirection(component.getHostView(), layoutDirection);
     }
     super.setLayout(component);
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 aebb6c3..96d1770 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
@@ -65,10 +65,10 @@ public class GapItemDecoration extends RecyclerView.ItemDecoration {
                     return;
                 }
 
-                int index = listComponent.isNativeLayoutRTL() ? spanOffsets.length - params.getSpanIndex() - 1 : params.getSpanIndex();
+                int index = listComponent.isLayoutRTL() ? spanOffsets.length - params.getSpanIndex() - 1 : params.getSpanIndex();
                 float spanOffset = listComponent.getSpanOffsets()[index];
                 int   spanOffsetPx =  Math.round(WXViewUtils.getRealPxByWidth(spanOffset, listComponent.getViewPortWidth()));
-                if (listComponent.isNativeLayoutRTL()) {
+                if (listComponent.isLayoutRTL()) {
                     outRect.left = -spanOffsetPx;
                     outRect.right = spanOffsetPx;
                 } else {
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
index 90b7fd1..12c1f07 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
@@ -90,7 +90,7 @@ namespace WeexCore
         
         int Layout(const char* pageId, const char* ref,
                        float top, float bottom, float left, float right,
-                       float height, float width, int index) override;
+                       float height, float width, bool isRTL, int index) override;
         
         int UpdateStyle(const char* pageId, const char* ref,
                             std::vector<std::pair<std::string, std::string>> *style,
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
index a0ad6de..b2ea970 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
@@ -525,7 +525,7 @@ namespace WeexCore
     
     int IOSSide::Layout(const char* pageId, const char* ref,
                        float top, float bottom, float left, float right,
-                       float height, float width, int index)
+                       float height, float width, bool isRTL, int index)
     {
         RenderPage *page = RenderManager::GetInstance()->GetPage(pageId);
         if (page == nullptr) {
@@ -549,7 +549,7 @@ namespace WeexCore
                                   isnan(WXRoundPixelValue(top))?0:WXRoundPixelValue(top),
                                   isnan(WXRoundPixelValue(width))?0:WXRoundPixelValue(width),
                                   isnan(WXRoundPixelValue(height))?0:WXRoundPixelValue(height));
-        [manager layoutComponent:component frame:frame innerMainSize:renderObject->getLargestMainSize()];
+        [manager layoutComponent:component frame:frame isRTL:isRTL innerMainSize:renderObject->getLargestMainSize()];
 
         page->CallBridgeTime(getCurrentTime() - startTime);
         return 0;
@@ -987,13 +987,13 @@ static WeexCore::ScriptBridge* jsBridge = nullptr;
             float left = render->getLayoutPositionLeft();
             float height = render->getLayoutHeight();
             float width = render->getLayoutWidth();
-            
+            BOOL isRTL = render->getLayoutDirectionFromPathNode() == WeexCore::kDirectionRTL;
             WXComponentManager* manager = [WXSDKManager instanceForID:ns_instanceId].componentManager;
             CGRect frame = CGRectMake(isnan(WXRoundPixelValue(left))?0:WXRoundPixelValue(left),
                                       isnan(WXRoundPixelValue(top))?0:WXRoundPixelValue(top),
                                       isnan(WXRoundPixelValue(width))?0:WXRoundPixelValue(width),
                                       isnan(WXRoundPixelValue(height))?0:WXRoundPixelValue(height));
-            [manager layoutComponent:component frame:frame innerMainSize:render->getLargestMainSize()];
+            [manager layoutComponent:component frame:frame isRTL:isRTL innerMainSize:render->getLargestMainSize()];
         }
         render->setHasNewLayout(false);
     }
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
index 3aef1dc..00f9450 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
@@ -283,6 +283,7 @@ typedef id (^WXDataBindingBlock)(NSDictionary *data, BOOL *needUpdate);
 
 - (void)_buildViewHierarchyLazily;
 
+- (void)_setIsLayoutRTL:(BOOL)isRTL;
 
 - (void)_adjustForRTL;
 
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.mm b/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.mm
index 0bd71bc..1848f96 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.mm
+++ b/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.mm
@@ -477,8 +477,7 @@ typedef NS_ENUM(NSInteger, Direction) {
     
     // this is scroll rtl solution.
     // scroll layout not use direction, use self tranform
-    if (self.view && _flexCssNode && _flexCssNode->getLayoutDirectionFromPathNode() == WeexCore::kDirectionRTL
-        ) {
+    if (self.view && self.isDirectionRTL) {
         WXRecycleSliderView *slider = (WXRecycleSliderView *)self.view;
         CATransform3D transform = CATransform3DScale(CATransform3DIdentity, -1, 1, 1);
         slider.scrollView.layer.transform = transform ;
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXEditComponent.mm b/ios/sdk/WeexSDK/Sources/Component/WXEditComponent.mm
index ec45bba..01866b7 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXEditComponent.mm
+++ b/ios/sdk/WeexSDK/Sources/Component/WXEditComponent.mm
@@ -102,6 +102,7 @@ WX_EXPORT_METHOD(@selector(setTextFormatter:))
         _clickEvent = NO;
         _keyboardEvent = NO;
         _keyboardHidden = YES;
+        _textAlignForStyle = NSTextAlignmentNatural;
         // handle attributes
         _autofocus = [attributes[@"autofocus"] boolValue];
         _disabled = [attributes[@"disabled"] boolValue];
@@ -176,7 +177,7 @@ WX_EXPORT_METHOD(@selector(setTextFormatter:))
     [self setAutofocus:_autofocus];
     [self setTextFont];
     [self setPlaceholderAttributedString];
-    [self setTextAlignment:_textAlignForStyle];
+    [self setTextAlignment];
     [self setTextColor:_colorForStyle];
     [self setText:_value];
     [self setEnabled:!_disabled];
@@ -214,6 +215,10 @@ WX_EXPORT_METHOD(@selector(setTextFormatter:))
     [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
 
+- (void)layoutDirectionDidChanged:(BOOL)isRTL {
+    [self setTextAlignment];
+}
+
 -(void)focus
 {
     if(self.view) {
@@ -289,6 +294,14 @@ WX_EXPORT_METHOD(@selector(setTextFormatter:))
 {
 }
 
+- (void)setTextAlignment {
+    if ([self isDirectionRTL] && _textAlignForStyle == NSTextAlignmentNatural) {
+        [self setTextAlignment:NSTextAlignmentRight];
+    } else {
+        [self setTextAlignment:_textAlignForStyle];
+    }
+}
+
 -(void)setTextAlignment:(NSTextAlignment)textAlignForStyle
 {
 }
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm
index f4c21a9..7d779f8 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm
+++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.mm
@@ -29,7 +29,6 @@
 #import "WXComponent+Layout.h"
 #import <pthread/pthread.h>
 #import <CoreText/CoreText.h>
-#import "WXComponent+Layout.h"
 
 // WXText is a non-public is not permitted
 @interface WXTextView : WXView
@@ -180,6 +179,8 @@ CGFloat WXTextDefaultLineThroughWidth = 1.2;
         pthread_mutexattr_settype(&(_propertMutexAttr), PTHREAD_MUTEX_RECURSIVE);
         pthread_mutex_init(&(_ctAttributedStringMutex), &(_propertMutexAttr));
         
+        _textAlign = NSTextAlignmentNatural;
+        
         if ([attributes objectForKey:@"coretext"]) {
             _useCoreTextAttr = [WXConvert NSString:attributes[@"coretext"]];
         } else {
@@ -359,6 +360,10 @@ do {\
     return [[WXTextView alloc] init];
 }
 
+- (void)layoutDirectionDidChanged:(BOOL)isRTL {
+    [self setNeedsRepaint];
+}
+
 - (BOOL)needsDrawRect
 {
     return YES;
@@ -513,11 +518,12 @@ do {\
     NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
     
     // handle text direction style, default ltr
+    NSTextAlignment retAlign = _textAlign;
     BOOL isRtl = [self isDirectionRTL];
     if (isRtl) {
-        if (0 == _textAlign) {
+        if (0 == retAlign) {
             //force text right-align if don't specified any align.
-            _textAlign = NSTextAlignmentRight;
+            retAlign = NSTextAlignmentRight;
         }
         paragraphStyle.baseWritingDirection = NSWritingDirectionRightToLeft;
     } else {
@@ -527,8 +533,8 @@ do {\
         paragraphStyle.baseWritingDirection =  NSWritingDirectionNatural;
     }
     
-    if (_textAlign) {
-        paragraphStyle.alignment = _textAlign;
+    if (retAlign) {
+        paragraphStyle.alignment = retAlign;
     }
     
     if ([[_wordWrap lowercaseString] isEqualToString:@"break-word"]) {
@@ -596,11 +602,12 @@ do {\
     NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
 
     // handle text direction style, default ltr
+    NSTextAlignment retAlign = _textAlign;
     BOOL isRtl = [self isDirectionRTL];
     if (isRtl) {
-        if (0 == _textAlign) {
+        if (0 == retAlign) {
             //force text right-align if don't specified any align.
-            _textAlign = NSTextAlignmentRight;
+            retAlign = NSTextAlignmentRight;
         }
         paragraphStyle.baseWritingDirection = NSWritingDirectionRightToLeft;
     } else {
@@ -610,8 +617,8 @@ do {\
         paragraphStyle.baseWritingDirection =  NSWritingDirectionNatural;
     }
     
-    if (_textAlign) {
-        paragraphStyle.alignment = _textAlign;
+    if (retAlign) {
+        paragraphStyle.alignment = retAlign;
     }
     
     if (_lineHeight) {
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.h b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.h
index 518a163..e2440c7 100644
--- a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.h
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.h
@@ -44,6 +44,7 @@ extern "C" {
     CGPoint _absolutePosition;
     WXPositionType _positionType;
     BOOL _isLastLayoutDirectionRTL;
+    BOOL _isLayoutDirectionRTL;
 }
 
 /**
@@ -79,4 +80,6 @@ extern "C" {
 // if your component view is not scrollView but also implement RTL layout by tranform,you need return YES
 - (BOOL)shouldTransformSubviewsWhenRTL;
 
+- (void)layoutDirectionDidChanged:(BOOL)isRTL;
+
 @end
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm
index 14246e7..eaf778c 100644
--- a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm
@@ -33,8 +33,6 @@ bool flexIsUndefined(float value) {
     return isnan(value);
 }
 
-
-
 @implementation WXComponent (Layout)
 
 #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
@@ -147,26 +145,35 @@ bool flexIsUndefined(float value) {
                 }
             }
             
-            [self _resetNativeBorderRadius];
+            [strongSelf _resetNativeBorderRadius];
+            
+            if ([WXUtility enableRTLLayoutDirection]) {
+                if ([strongSelf isDirectionRTL] != strongSelf -> _isLastLayoutDirectionRTL) {
+                    strongSelf -> _isLastLayoutDirectionRTL = [strongSelf isDirectionRTL];
+                    [strongSelf _layoutDirectionDidChanged:[strongSelf isDirectionRTL]];
+                }
+            }
             
             if (strongSelf->_transform) {
                 [strongSelf->_transform applyTransformForView:strongSelf.view];
             }
             
-            [self _adjustForRTL];
+            [strongSelf _adjustForRTL];
             
             if (strongSelf->_backgroundImage) {
                 [strongSelf setGradientLayer];
             }
+            
             [strongSelf setNeedsDisplay];
         }];
-    } else {
+    } else if ([WXUtility enableRTLLayoutDirection]) {
         // if frame is not change, we still need check was layoutDirection changed
         if ([self isDirectionRTL] != _isLastLayoutDirectionRTL) {
-            _isLastLayoutDirectionRTL = [self isDirectionRTL];
+            self -> _isLastLayoutDirectionRTL = [self isDirectionRTL];
             __weak typeof(self) weakSelf = self;
             [self.weexInstance.componentManager _addUITask:^{
                 __strong typeof(weakSelf) strongSelf = weakSelf;
+                [strongSelf _layoutDirectionDidChanged:[strongSelf isDirectionRTL]];
                 if (strongSelf->_transform) {
                     [strongSelf->_transform applyTransformForView:strongSelf.view];
                 }
@@ -176,6 +183,15 @@ bool flexIsUndefined(float value) {
     }
 }
 
+- (void)_layoutDirectionDidChanged:(BOOL)isRTL {
+    WXAssertMainThread();
+    [self layoutDirectionDidChanged:isRTL];
+}
+
+- (void)layoutDirectionDidChanged:(BOOL)isRTL {
+    
+}
+
 - (void)_layoutDidFinish
 {
     WXAssertMainThread();
@@ -717,10 +733,8 @@ static WeexCore::WXCoreSize flexCssNodeMeasure(WeexCore::WXCoreLayoutNode *node,
 
 - (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;
+
+    return _isLayoutDirectionRTL;
 }
 
 - (void)_adjustForRTL {
@@ -728,7 +742,7 @@ static WeexCore::WXCoreSize flexCssNodeMeasure(WeexCore::WXCoreLayoutNode *node,
     
     if (self->_positionType == WXPositionTypeFixed) return;
     
-    if (self.supercomponent && self.supercomponent->_flexCssNode && self.supercomponent->_flexCssNode->getLayoutDirectionFromPathNode() == WeexCore::kDirectionRTL && [self.supercomponent shouldTransformSubviewsWhenRTL]) {
+    if (self.supercomponent && self.supercomponent.isDirectionRTL && [self.supercomponent shouldTransformSubviewsWhenRTL]) {
         if (_transform) {
             self.view.layer.transform = CATransform3DConcat(self.view.layer.transform, CATransform3DScale(CATransform3DIdentity, -1, 1, 1));
         } else {
@@ -748,4 +762,8 @@ static WeexCore::WXCoreSize flexCssNodeMeasure(WeexCore::WXCoreLayoutNode *node,
     return [self.view isKindOfClass:[UIScrollView class]];
 }
 
+- (void)_setIsLayoutRTL:(BOOL)isRTL {
+    _isLayoutDirectionRTL = isRTL;
+}
+
 @end
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
index d1a36ed..2fa258e 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
@@ -155,7 +155,7 @@ void WXPerformBlockSyncOnComponentThread(void (^block)(void));
 /**
  * @abstract layout a component with frame output by weex core layout engine
  **/
-- (void)layoutComponent:(WXComponent*)component frame:(CGRect)frame innerMainSize:(CGFloat)innerMainSize;
+- (void)layoutComponent:(WXComponent*)component frame:(CGRect)frame isRTL:(BOOL)isRTL innerMainSize:(CGFloat)innerMainSize;
 
 /**
  * @abstract layout a component on platform side
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm
index 53f2157..504ee66 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm
@@ -719,11 +719,12 @@ static NSThread *WXComponentThread;
     return [component _hasTransitionPropertyInStyles:styles];
 }
 
-- (void)layoutComponent:(WXComponent*)component frame:(CGRect)frame innerMainSize:(CGFloat)innerMainSize
+- (void)layoutComponent:(WXComponent*)component frame:(CGRect)frame isRTL:(BOOL)isRTL innerMainSize:(CGFloat)innerMainSize
 {
     WXAssertComponentThread();
     WXAssertParam(component);
     
+    [component _setIsLayoutRTL:isRTL];
     if (component == _rootComponent) {
         if (!CGSizeEqualToSize(frame.size, self.weexInstance.frame.size)) {
             // Synchronize view frame with root component, especially for content wrap mode.
diff --git a/weex_core/Source/android/bridge/platform/android_side.cpp b/weex_core/Source/android/bridge/platform/android_side.cpp
index 6553273..8d55dbe 100644
--- a/weex_core/Source/android/bridge/platform/android_side.cpp
+++ b/weex_core/Source/android/bridge/platform/android_side.cpp
@@ -299,13 +299,13 @@ int AndroidSide::AddElement(const char *page_id, const char *component_type,
 
 int AndroidSide::Layout(const char *page_id, const char *ref, float top,
                         float bottom, float left, float right, float height,
-                        float width, int index) {
+                        float width, bool isRTL, int index) {
   JNIEnv *env = base::android::AttachCurrentThread();
   if(env == nullptr) {
     return -1;
   }
   int flag = 0;
-  wx_bridge_->Layout(env, page_id, ref, top, bottom, left, right, height, width,
+  wx_bridge_->Layout(env, page_id, ref, top, bottom, left, right, height, width, isRTL,
                      index);
 
   if (flag == -1) {
diff --git a/weex_core/Source/android/bridge/platform/android_side.h b/weex_core/Source/android/bridge/platform/android_side.h
index 566bd42..f912992 100644
--- a/weex_core/Source/android/bridge/platform/android_side.h
+++ b/weex_core/Source/android/bridge/platform/android_side.h
@@ -80,7 +80,7 @@ class AndroidSide : public PlatformBridge::PlatformSide {
                  const WXCorePadding& paddings,
                  const WXCoreBorderWidth& borders, bool willLayout) override;
   int Layout(const char* page_id, const char* ref, float top, float bottom,
-             float left, float right, float height, float width, int index) override;
+             float left, float right, float height, float width, bool isRTL, int index) override;
 
   int UpdateStyle(
       const char* pageId, const char* ref,
diff --git a/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h b/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
index 46da177..0b746fd 100644
--- a/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
+++ b/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
@@ -723,6 +723,7 @@ static jint Java_WXBridge_callLayout(JNIEnv* env, jobject obj, jstring
     int right,
     int height,
     int width,
+    bool isRTL,
     int index) {
   /* Must call RegisterNativesImpl()  */
   //CHECK_CLAZZ(env, obj,
@@ -742,6 +743,7 @@ static jint Java_WXBridge_callLayout(JNIEnv* env, jobject obj, jstring
 "I"
 "I"
 "I"
+"Z"
 "I"
 ")"
 "I",
@@ -750,7 +752,7 @@ static jint Java_WXBridge_callLayout(JNIEnv* env, jobject obj, jstring
   jint ret =
       env->CallIntMethod(obj,
           method_id, instanceId, ref, int(top), int(bottom), int(left),
-              int(right), int(height), int(width), int(index));
+              int(right), int(height), int(width), isRTL, int(index));
   base::android::CheckException(env);
   return ret;
 }
diff --git a/weex_core/Source/android/wrap/wx_bridge.cpp b/weex_core/Source/android/wrap/wx_bridge.cpp
index e783eee..a699324 100644
--- a/weex_core/Source/android/wrap/wx_bridge.cpp
+++ b/weex_core/Source/android/wrap/wx_bridge.cpp
@@ -749,13 +749,13 @@ int WXBridge::UpdateStyle(
 }
 
 int WXBridge::Layout(JNIEnv* env, const char* page_id, const char* ref, int top,
-                     int bottom, int left, int right, int height, int width,
+                     int bottom, int left, int right, int height, int width, bool isRTL,
                      int index) {
   auto jPageId = base::android::ScopedLocalJavaRef<jstring>(env, env->NewStringUTF(page_id));
   auto jRef = base::android::ScopedLocalJavaRef<jstring>(env, env->NewStringUTF(ref));
 
   return Java_WXBridge_callLayout(env, jni_object(), jPageId.Get(), jRef.Get(), top, bottom,
-                                  left, right, height, width, index);
+                                  left, right, height, width, isRTL, index);
 }
 
 int WXBridge::AddElement(JNIEnv* env, const char* page_id,
diff --git a/weex_core/Source/android/wrap/wx_bridge.h b/weex_core/Source/android/wrap/wx_bridge.h
index c7dfcc8..dba7cce 100644
--- a/weex_core/Source/android/wrap/wx_bridge.h
+++ b/weex_core/Source/android/wrap/wx_bridge.h
@@ -63,7 +63,7 @@ class WXBridge : public JNIObjectWrap {
                   std::vector<std::pair<std::string, std::string>> *padding,
                   std::vector<std::pair<std::string, std::string>> *border);
   int Layout(JNIEnv *env, const char *page_id, const char *ref, int top,
-             int bottom, int left, int right, int height, int width, int index);
+             int bottom, int left, int right, int height, int width, bool isRTL, int index);
   int AddElement(JNIEnv *env, const char *page_id, const char *component_type,
                  const char *ref, int &index, const char *parentRef,
                  std::map<std::string, std::string> *styles,
diff --git a/weex_core/Source/core/bridge/platform_bridge.h b/weex_core/Source/core/bridge/platform_bridge.h
index 680563f..6b014ae 100644
--- a/weex_core/Source/core/bridge/platform_bridge.h
+++ b/weex_core/Source/core/bridge/platform_bridge.h
@@ -199,7 +199,7 @@ class PlatformBridge {
                            bool willLayout = true) = 0;
     virtual int Layout(const char* page_id, const char* ref, float top,
                        float bottom, float left, float right, float height,
-                       float width, int index) = 0;
+                       float width, bool isRTL, int index) = 0;
 
     virtual int UpdateStyle(
         const char* pageId, const char* ref,
diff --git a/weex_core/Source/core/layout/layout.cpp b/weex_core/Source/core/layout/layout.cpp
index 83e7745..86d671d 100644
--- a/weex_core/Source/core/layout/layout.cpp
+++ b/weex_core/Source/core/layout/layout.cpp
@@ -1119,17 +1119,14 @@ namespace WeexCore {
     }
     
     WXCoreDirection WXCoreLayoutNode::getLayoutDirectionFromPathNode() {
-        WXCoreLayoutNode *node = this;
-        if (nullptr != node) {
-            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();
-            }
+        if (getLayoutDirection() != kDirectionInherit)
+            return getLayoutDirection();
+        if (getDirection() != kDirectionInherit) {
+            mLayoutResult->mLayoutDirection = getDirection();
+            return getLayoutDirection();
+        } else if (nullptr != mParent) {
+            mLayoutResult->mLayoutDirection = mParent->getLayoutDirectionFromPathNode();
+            return getLayoutDirection();
         }
         return WEEXCORE_CSS_DEFAULT_DIRECTION;
     }
diff --git a/weex_core/Source/core/render/action/render_action_layout.cpp b/weex_core/Source/core/render/action/render_action_layout.cpp
index 0c6beac..2b98cb5 100644
--- a/weex_core/Source/core/render/action/render_action_layout.cpp
+++ b/weex_core/Source/core/render/action/render_action_layout.cpp
@@ -34,7 +34,7 @@ RenderActionLayout::RenderActionLayout(const std::string &page_id,
 void RenderActionLayout::ExecuteAction() {
   WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->Layout(
       this->page_id_.c_str(), this->ref_.c_str(), this->top_, this->bottom_,
-      this->left_, this->right_, this->height_, this->width_, this->index_);
+      this->left_, this->right_, this->height_, this->width_, this->isRTL_, this->index_);
 }
 
 void RenderActionLayout::GetLayoutInfo(const WXCoreLayoutNode *node) {
@@ -44,5 +44,6 @@ void RenderActionLayout::GetLayoutInfo(const WXCoreLayoutNode *node) {
   this->left_ = node->getLayoutPositionLeft();
   this->height_ = node->getLayoutHeight();
   this->width_ = node->getLayoutWidth();
+  this->isRTL_ = node->getLayoutDirection() == WeexCore::kDirectionRTL;
 }
 }  // namespace WeexCore
diff --git a/weex_core/Source/core/render/action/render_action_layout.h b/weex_core/Source/core/render/action/render_action_layout.h
index ef36700..fc7e9b4 100644
--- a/weex_core/Source/core/render/action/render_action_layout.h
+++ b/weex_core/Source/core/render/action/render_action_layout.h
@@ -48,6 +48,7 @@ class RenderActionLayout : public RenderAction {
   float left_;
   float bottom_;
   float right_;
+  bool isRTL_;
   int index_;
 };
 }  // namespace WeexCore