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 2017/06/08 09:42:17 UTC

incubator-weex git commit: * [Android] Support rotateX and rotateY, optimize animation as well.

Repository: incubator-weex
Updated Branches:
  refs/heads/0.14-dev bd00ba86b -> cd911636d


* [Android] Support rotateX and rotateY, optimize animation as well.

@notdanger

* [Use LayoutParamsProperty instead of DimensionUpdateListener to achieve height/width animation.](http://dotwe.org/vue/c7a70462a136b61e11ab37f384862003)
* [Support rotateX and rotateY.](http://dotwe.org/vue/e712dd2ad4df470bab940d8e0e6d052d).
* Stop remove transform and transform-origin from WXStyle in UpdateStyleAction.
* Stop execute animation callback if corresponding WXInstance is destroyed when animation finished.

Corresponding [JIRA issue](https://issues.apache.org/jira/browse/WEEX-38).


Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/cd911636
Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/cd911636
Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/cd911636

Branch: refs/heads/0.14-dev
Commit: cd911636d6ca25d12470a9c492bdfb5beb7e169d
Parents: bd00ba8
Author: YorkShen <sh...@gmail.com>
Authored: Mon Jun 5 14:59:31 2017 +0800
Committer: YorkShen <sh...@gmail.com>
Committed: Thu Jun 8 17:02:42 2017 +0800

----------------------------------------------------------------------
 .../taobao/weex/dom/action/AnimationAction.java | 37 ++++----
 .../weex/dom/action/UpdateStyleAction.java      |  4 +-
 .../ui/animation/DimensionUpdateListener.java   | 88 --------------------
 .../weex/ui/animation/HeightProperty.java       | 35 ++++++++
 .../weex/ui/animation/LayoutParamsProperty.java | 64 ++++++++++++++
 .../weex/ui/animation/WXAnimationBean.java      | 72 ++++++++++------
 .../taobao/weex/ui/animation/WidthProperty.java | 35 ++++++++
 .../taobao/weex/ui/component/WXComponent.java   | 16 +++-
 8 files changed, 213 insertions(+), 138 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cd911636/android/sdk/src/main/java/com/taobao/weex/dom/action/AnimationAction.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/action/AnimationAction.java b/android/sdk/src/main/java/com/taobao/weex/dom/action/AnimationAction.java
index 6f811fd..59afbca 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/action/AnimationAction.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/action/AnimationAction.java
@@ -38,7 +38,6 @@ import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
-
 import com.alibaba.fastjson.JSONObject;
 import com.taobao.weex.WXSDKInstance;
 import com.taobao.weex.WXSDKManager;
@@ -48,9 +47,10 @@ import com.taobao.weex.dom.RenderAction;
 import com.taobao.weex.dom.RenderActionContext;
 import com.taobao.weex.dom.WXDomObject;
 import com.taobao.weex.ui.animation.BackgroundColorProperty;
-import com.taobao.weex.ui.animation.DimensionUpdateListener;
+import com.taobao.weex.ui.animation.HeightProperty;
 import com.taobao.weex.ui.animation.WXAnimationBean;
 import com.taobao.weex.ui.animation.WXAnimationModule;
+import com.taobao.weex.ui.animation.WidthProperty;
 import com.taobao.weex.ui.component.WXComponent;
 import com.taobao.weex.ui.view.border.BorderDrawable;
 import com.taobao.weex.utils.SingleFunctionParser;
@@ -58,7 +58,6 @@ import com.taobao.weex.utils.WXLogUtils;
 import com.taobao.weex.utils.WXResourceUtils;
 import com.taobao.weex.utils.WXUtils;
 import com.taobao.weex.utils.WXViewUtils;
-
 import java.util.HashMap;
 import java.util.List;
 
@@ -190,28 +189,28 @@ class AnimationAction implements DOMAction, RenderAction {
               WXResourceUtils.getColor(style.backgroundColor)));
         }
       }
-      if (style.getPivot() != null) {
-        Pair<Float, Float> pair = style.getPivot();
-        target.setPivotX(pair.first);
-        target.setPivotY(pair.second);
-      }
-      animator = ObjectAnimator.ofPropertyValuesHolder(
-          target, holders.toArray(new PropertyValuesHolder[holders.size()]));
-      animator.setStartDelay(mAnimationBean.delay);
+
       if (target.getLayoutParams() != null &&
           (!TextUtils.isEmpty(style.width) || !TextUtils.isEmpty(style.height))) {
-        DimensionUpdateListener listener = new DimensionUpdateListener(target);
         ViewGroup.LayoutParams layoutParams = target.getLayoutParams();
         if (!TextUtils.isEmpty(style.width)) {
-          listener.setWidth(layoutParams.width,
-                            (int) WXViewUtils.getRealPxByWidth(WXUtils.getFloat(style.width), viewPortWidth));
+          holders.add(PropertyValuesHolder.ofInt(new WidthProperty(), layoutParams.width,
+              (int) WXViewUtils.getRealPxByWidth(WXUtils.getFloat(style.width), viewPortWidth)));
         }
         if (!TextUtils.isEmpty(style.height)) {
-          listener.setHeight(layoutParams.height,
-                             (int) WXViewUtils.getRealPxByWidth(WXUtils.getFloat(style.height), viewPortWidth));
+          holders.add(PropertyValuesHolder.ofInt(new HeightProperty(), layoutParams.height,
+              (int) WXViewUtils.getRealPxByWidth(WXUtils.getFloat(style.height), viewPortWidth)));
         }
-        animator.addUpdateListener(listener);
       }
+
+      if (style.getPivot() != null) {
+        Pair<Float, Float> pair = style.getPivot();
+        target.setPivotX(pair.first);
+        target.setPivotY(pair.second);
+      }
+      animator = ObjectAnimator.ofPropertyValuesHolder(
+          target, holders.toArray(new PropertyValuesHolder[holders.size()]));
+      animator.setStartDelay(mAnimationBean.delay);
       return animator;
     } else {
       return null;
@@ -225,8 +224,8 @@ class AnimationAction implements DOMAction, RenderAction {
       return new AnimatorListenerAdapter() {
         @Override
         public void onAnimationEnd(Animator animation) {
-          if (instance == null) {
-            WXLogUtils.e("RenderActionContextImpl-onAnimationEnd WXSDKInstance == null NPE");
+          if (instance == null || instance.isDestroy()) {
+            WXLogUtils.e("RenderActionContextImpl-onAnimationEnd WXSDKInstance == null NPE or instance is destroyed");
           } else {
             WXSDKManager.getInstance().callback(instance.getInstanceId(),
                                                 callBack,

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cd911636/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateStyleAction.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateStyleAction.java b/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateStyleAction.java
index 5b7822c..aa56e70 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateStyleAction.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateStyleAction.java
@@ -74,8 +74,8 @@ class UpdateStyleAction implements DOMAction, RenderAction {
     mBorder = domObject.getBorder();
 
     Map<String, Object> animationMap = new ArrayMap<>(2);
-    animationMap.put(WXDomObject.TRANSFORM, mData.remove(WXDomObject.TRANSFORM));
-    animationMap.put(WXDomObject.TRANSFORM_ORIGIN, mData.remove(WXDomObject.TRANSFORM_ORIGIN));
+    animationMap.put(WXDomObject.TRANSFORM, mData.get(WXDomObject.TRANSFORM));
+    animationMap.put(WXDomObject.TRANSFORM_ORIGIN, mData.get(WXDomObject.TRANSFORM_ORIGIN));
 
     context.addAnimationForElement(mRef, animationMap);
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cd911636/android/sdk/src/main/java/com/taobao/weex/ui/animation/DimensionUpdateListener.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/animation/DimensionUpdateListener.java b/android/sdk/src/main/java/com/taobao/weex/ui/animation/DimensionUpdateListener.java
deleted file mode 100644
index bfac085..0000000
--- a/android/sdk/src/main/java/com/taobao/weex/ui/animation/DimensionUpdateListener.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.animation;
-
-import android.animation.IntEvaluator;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.support.annotation.NonNull;
-import android.support.v4.util.Pair;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.taobao.weex.ui.component.WXComponent;
-import com.taobao.weex.ui.view.IRenderResult;
-
-public class DimensionUpdateListener implements ValueAnimator.AnimatorUpdateListener {
-
-  private View view;
-  private Pair<Integer, Integer> width;
-  private Pair<Integer, Integer> height;
-  private IntEvaluator intEvaluator;
-
-  public DimensionUpdateListener(@NonNull View view) {
-    this.view = view;
-    intEvaluator = new IntEvaluator();
-  }
-
-  public void setWidth(int from, int to) {
-    width = new Pair<>(from, to);
-  }
-
-  public void setHeight(int from, int to) {
-    height = new Pair<>(from, to);
-  }
-
-  @Override
-  public void onAnimationUpdate(ValueAnimator animation) {
-    if (view.getLayoutParams() != null) {
-      ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
-      TimeInterpolator interpolator = animation.getInterpolator();
-      float fraction = animation.getAnimatedFraction();
-      int preWidth = layoutParams.width;
-      int preHeight = layoutParams.height;
-      if (width != null) {
-        layoutParams.width = intEvaluator.evaluate(interpolator.getInterpolation(fraction),
-                                                   width.first,
-                                                   width.second);
-      }
-      if (height != null) {
-        layoutParams.height = intEvaluator.evaluate(interpolator.getInterpolation(fraction),
-                                                    height.first,
-                                                    height.second);
-      }
-      if (preHeight != layoutParams.height || preWidth != layoutParams.width) {
-        view.requestLayout();
-      }
-
-      if (view instanceof IRenderResult) {
-        WXComponent component = ((IRenderResult) view).getComponent();
-        if (component != null) {
-          if (preWidth != layoutParams.width || preHeight != layoutParams.height) {
-            //Notify the animated component it native size has changed
-            //The component will decides whether to update domobject
-            component.notifyNativeSizeChanged(layoutParams.width, layoutParams.height);
-          }
-        }
-      }
-    }
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cd911636/android/sdk/src/main/java/com/taobao/weex/ui/animation/HeightProperty.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/animation/HeightProperty.java b/android/sdk/src/main/java/com/taobao/weex/ui/animation/HeightProperty.java
new file mode 100644
index 0000000..b268ed2
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/animation/HeightProperty.java
@@ -0,0 +1,35 @@
+/**
+ * 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.animation;
+
+
+import android.view.ViewGroup.LayoutParams;
+
+public class HeightProperty extends LayoutParamsProperty {
+
+  @Override
+  protected Integer getProperty(LayoutParams layoutParams) {
+    return layoutParams.height;
+  }
+
+  @Override
+  protected void setProperty(LayoutParams layoutParams, Integer expected) {
+    layoutParams.height = expected;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cd911636/android/sdk/src/main/java/com/taobao/weex/ui/animation/LayoutParamsProperty.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/animation/LayoutParamsProperty.java b/android/sdk/src/main/java/com/taobao/weex/ui/animation/LayoutParamsProperty.java
new file mode 100644
index 0000000..312180e
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/animation/LayoutParamsProperty.java
@@ -0,0 +1,64 @@
+/**
+ * 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.animation;
+
+
+import android.util.Property;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import com.taobao.weex.ui.component.WXComponent;
+import com.taobao.weex.ui.view.IRenderResult;
+
+/**
+ * android.util.IntProperty<T> cannot be applied here, as it is only added at API 24.
+ */
+abstract class LayoutParamsProperty extends Property<View, Integer> {
+
+  LayoutParamsProperty() {
+    super(Integer.class, "layoutParams");
+  }
+
+  @Override
+  public Integer get(View object) {
+    LayoutParams layoutParams;
+    if (object != null && (layoutParams = object.getLayoutParams()) != null) {
+      return getProperty(layoutParams);
+    }
+    return 0;
+  }
+
+  @Override
+  public void set(View object, Integer value) {
+    LayoutParams layoutParams;
+    if (object != null && (layoutParams = object.getLayoutParams()) != null) {
+      setProperty(layoutParams, value);
+      if (object instanceof IRenderResult) {
+        WXComponent component = ((IRenderResult) object).getComponent();
+        if (component != null) {
+            component.notifyNativeSizeChanged(layoutParams.width, layoutParams.height);
+        }
+      }
+      object.requestLayout();
+    }
+  }
+
+  protected abstract Integer getProperty(LayoutParams layoutParams);
+
+  protected abstract void setProperty(LayoutParams layoutParams, Integer expected);
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cd911636/android/sdk/src/main/java/com/taobao/weex/ui/animation/WXAnimationBean.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/animation/WXAnimationBean.java b/android/sdk/src/main/java/com/taobao/weex/ui/animation/WXAnimationBean.java
index 0cd2901..2635d7c 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/animation/WXAnimationBean.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/animation/WXAnimationBean.java
@@ -26,13 +26,11 @@ import android.text.TextUtils;
 import android.util.Pair;
 import android.util.Property;
 import android.view.View;
-
 import com.taobao.weex.common.Constants;
 import com.taobao.weex.utils.FunctionParser;
 import com.taobao.weex.utils.WXDataStructureUtil;
 import com.taobao.weex.utils.WXUtils;
 import com.taobao.weex.utils.WXViewUtils;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -65,6 +63,8 @@ public class WXAnimationBean {
     public final static String WX_SCALE_X = "scaleX";
     public final static String WX_SCALE_Y = "scaleY";
     public final static String WX_SCALE = "scale";
+    public final static String WX_ROTATE_X ="rotateX";
+    public final static String WX_ROTATE_Y ="rotateY";
     public final static String BACKGROUND_COLOR = Constants.Name.BACKGROUND_COLOR;
     public final static String WIDTH = Constants.Name.WIDTH;
     public final static String HEIGHT = Constants.Name.HEIGHT;
@@ -86,6 +86,8 @@ public class WXAnimationBean {
       wxToAndroidMap.put(WX_TRANSLATE_X, Collections.singletonList(View.TRANSLATION_X));
       wxToAndroidMap.put(WX_TRANSLATE_Y, Collections.singletonList(View.TRANSLATION_Y));
       wxToAndroidMap.put(WX_ROTATE, Collections.singletonList(View.ROTATION));
+      wxToAndroidMap.put(WX_ROTATE_X, Collections.singletonList(View.ROTATION_X));
+      wxToAndroidMap.put(WX_ROTATE_Y, Collections.singletonList(View.ROTATION_Y));
       wxToAndroidMap.put(WX_SCALE, Arrays.asList(View.SCALE_X, View.SCALE_Y));
       wxToAndroidMap.put(WX_SCALE_X, Collections.singletonList(View.SCALE_X));
       wxToAndroidMap.put(WX_SCALE_Y, Collections.singletonList(View.SCALE_Y));
@@ -110,31 +112,34 @@ public class WXAnimationBean {
               @Override
               public Map<Property<View,Float>, Float> map(String functionName, List<String> raw) {
                 if (raw != null && !raw.isEmpty()) {
-                  if (WXAnimationBean.Style.wxToAndroidMap.containsKey(functionName)) {
-                    return convertParam(width, height,viewportW,
-                                        WXAnimationBean.Style.wxToAndroidMap.get(functionName), raw);
+                  if (wxToAndroidMap.containsKey(functionName)) {
+                    return convertParam(width, height,viewportW, wxToAndroidMap.get(functionName), raw);
                   }
                 }
                 return new HashMap<>();
               }
 
               private Map<Property<View,Float>, Float> convertParam(int width, int height,int viewportW,
-                                                      @NonNull List<Property<View,Float>> nameSet,
+                                                      @NonNull List<Property<View,Float>> propertyList,
                                                       @NonNull List<String> rawValue) {
-                Map<Property<View,Float>, Float> result = WXDataStructureUtil.newHashMapWithExpectedSize(nameSet.size());
-                List<Float> convertedList = new ArrayList<>(nameSet.size());
-                if (nameSet.contains(View.ROTATION)) {
-                  convertedList.addAll(parseRotation(rawValue));
-                } else if (nameSet.contains(View.TRANSLATION_X) ||
-                           nameSet.contains(View.TRANSLATION_Y)) {
-                  convertedList.addAll(parseTranslation(nameSet, width, height, rawValue,viewportW));
-                } else if (nameSet.contains(View.SCALE_X) ||
-                           nameSet.contains(View.SCALE_Y)) {
-                  convertedList.addAll(parseScale(nameSet.size(), rawValue));
+                Map<Property<View,Float>, Float> result = WXDataStructureUtil.newHashMapWithExpectedSize(propertyList.size());
+                List<Float> convertedList = new ArrayList<>(propertyList.size());
+                if (propertyList.contains(View.ROTATION)) {
+                  convertedList.addAll(parseRotationZ(rawValue));
+                }else if(propertyList.contains(View.ROTATION_X)) {
+                  convertedList.addAll(parseRotationXY(rawValue));
+                }else if(propertyList.contains(View.ROTATION_Y)) {
+                  convertedList.addAll(parseRotationXY(rawValue));
+                }else if (propertyList.contains(View.TRANSLATION_X) ||
+                           propertyList.contains(View.TRANSLATION_Y)) {
+                  convertedList.addAll(parseTranslation(propertyList, width, height, rawValue,viewportW));
+                } else if (propertyList.contains(View.SCALE_X) ||
+                           propertyList.contains(View.SCALE_Y)) {
+                  convertedList.addAll(parseScale(propertyList.size(), rawValue));
                 }
-                if (nameSet.size() == convertedList.size()) {
-                  for (int i = 0; i < nameSet.size(); i++) {
-                    result.put(nameSet.get(i), convertedList.get(i));
+                if (propertyList.size() == convertedList.size()) {
+                  for (int i = 0; i < propertyList.size(); i++) {
+                    result.put(propertyList.get(i), convertedList.get(i));
                   }
                 }
                 return result;
@@ -153,7 +158,15 @@ public class WXAnimationBean {
                 return convertedList;
               }
 
-              private List<Float> parseRotation(@NonNull List<String> rawValue) {
+              private List<Float> parseRotationXY(@NonNull List<String> rawValue) {
+                List<Float> intermediate = parseRotationZ(rawValue);
+                for (int i = 0; i < intermediate.size(); i++) {
+                  intermediate.set(i, -intermediate.get(i));
+                }
+                return intermediate;
+              }
+
+              private @NonNull List<Float> parseRotationZ(@NonNull List<String> rawValue) {
                 List<Float> convertedList = new ArrayList<>(1);
                 int suffix;
                 for (String raw : rawValue) {
@@ -166,25 +179,30 @@ public class WXAnimationBean {
                 return convertedList;
               }
 
-
-              private List<Float> parseTranslation(List<Property<View,Float>> nameSet,
+              /**
+               * As "translate(50%, 25%)" or "translate(25px, 30px)" both are valid,
+               * parsing translate is complicated than other method.
+               * Add your waste time here if you try to optimize this method like {@link #parseScale(int, List)}
+               * Time: 0.5h
+               */
+              private List<Float> parseTranslation(List<Property<View,Float>> propertyList,
                                                    int width, int height,
                                                    @NonNull List<String> rawValue,int viewportW) {
                 List<Float> convertedList = new ArrayList<>(2);
                 String first = rawValue.get(0);
-                if (nameSet.size() == 1) {
-                  parseSingleTranslation(nameSet, width, height, convertedList, first,viewportW);
+                if (propertyList.size() == 1) {
+                  parseSingleTranslation(propertyList, width, height, convertedList, first,viewportW);
                 } else {
                   parseDoubleTranslation(width, height, rawValue, convertedList, first,viewportW);
                 }
                 return convertedList;
               }
 
-              private void parseSingleTranslation(List<Property<View,Float>> nameSet, int width, int height,
+              private void parseSingleTranslation(List<Property<View,Float>> propertyList, int width, int height,
                                                   List<Float> convertedList, String first,int viewportW) {
-                if (nameSet.contains(View.TRANSLATION_X)) {
+                if (propertyList.contains(View.TRANSLATION_X)) {
                   convertedList.add(parsePercentOrPx(first, width,viewportW));
-                } else if (nameSet.contains(View.TRANSLATION_Y)) {
+                } else if (propertyList.contains(View.TRANSLATION_Y)) {
                   convertedList.add(parsePercentOrPx(first, height,viewportW));
                 }
               }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cd911636/android/sdk/src/main/java/com/taobao/weex/ui/animation/WidthProperty.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/animation/WidthProperty.java b/android/sdk/src/main/java/com/taobao/weex/ui/animation/WidthProperty.java
new file mode 100644
index 0000000..ca4288f
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/animation/WidthProperty.java
@@ -0,0 +1,35 @@
+/**
+ * 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.animation;
+
+
+import android.view.ViewGroup.LayoutParams;
+
+public class WidthProperty extends LayoutParamsProperty {
+
+  @Override
+  protected Integer getProperty(LayoutParams layoutParams) {
+    return layoutParams.width;
+  }
+
+  @Override
+  protected void setProperty(LayoutParams layoutParams, Integer expected) {
+    layoutParams.width = expected;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cd911636/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java
----------------------------------------------------------------------
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 659cb16..b725397 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
@@ -39,7 +39,6 @@ import android.view.Menu;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
-
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.taobao.weex.IWXActivityStateListener;
@@ -72,7 +71,6 @@ import com.taobao.weex.utils.WXReflectionUtils;
 import com.taobao.weex.utils.WXResourceUtils;
 import com.taobao.weex.utils.WXUtils;
 import com.taobao.weex.utils.WXViewUtils;
-
 import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -708,6 +706,19 @@ public abstract class  WXComponent<T extends View> implements IWXObject, IWXActi
     }
   }
 
+  private void setPerspective(Object param) {
+    T host = getHostView();
+    if (host != null) {
+      float value = WXUtils.getFloatByViewport(param, getInstance().getInstanceViewPortWidth());
+      float scale = host.getResources().getDisplayMetrics().density;
+      if (!Float.isNaN(value) && value > 0) {
+        host.setCameraDistance(value * scale);
+      } else {
+        host.setCameraDistance(Float.MAX_VALUE);
+      }
+    }
+  }
+
   @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
   protected void setAriaHidden(boolean isHidden) {
     View host = getHostView();
@@ -918,6 +929,7 @@ public abstract class  WXComponent<T extends View> implements IWXObject, IWXActi
    */
   @CallSuper
   protected void onHostViewInitialized(T host){
+    host.setCameraDistance(Float.MAX_VALUE);
     if (mAnimationHolder != null) {
       //Performs cached animation
       mAnimationHolder.execute(mInstance, this);