* [android] Init commit for flatGUI
Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/bc6ea406 Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/bc6ea406 Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/bc6ea406 Branch: refs/heads/0.16-dev Commit: bc6ea406e05667712f7084b268bb16f81c2298fd Parents: 701c4b9 Author: YorkShen <shenyua...@gmail.com> Authored: Tue Aug 22 11:37:04 2017 +0800 Committer: YorkShen <shenyua...@gmail.com> Committed: Wed Sep 13 16:54:07 2017 +0800 ---------------------------------------------------------------------- .../adapter/PicassoBasedDrawableLoader.java | 112 ++++++++++++++ .../alibaba/weex/benchmark/BenchmarkTest.java | 29 ++-- .../java/com/alibaba/weex/WXApplication.java | 2 + .../java/com/taobao/weex/WXSDKInstance.java | 12 +- .../taobao/weex/adapter/DrawableStrategy.java | 5 + .../java/com/taobao/weex/common/Constants.java | 2 + .../com/taobao/weex/common/WXImageStrategy.java | 8 +- .../com/taobao/weex/dom/ImmutableDomObject.java | 21 ++- .../taobao/weex/ui/component/WXComponent.java | 127 +++++++++++----- .../com/taobao/weex/ui/component/WXDiv.java | 70 ++++++++- .../com/taobao/weex/ui/component/WXSlider.java | 4 +- .../com/taobao/weex/ui/component/WXText.java | 65 +++++---- .../taobao/weex/ui/component/WXVContainer.java | 44 ++++-- .../taobao/weex/ui/component/list/WXCell.java | 38 ++++- .../weex/ui/component/list/WXListComponent.java | 53 ++++--- .../com/taobao/weex/ui/flat/FlatComponent.java | 33 +++++ .../taobao/weex/ui/flat/FlatGUIIContext.java | 113 ++++++++++++++ .../taobao/weex/ui/flat/WidgetContainer.java | 92 ++++++++++++ .../weex/ui/flat/widget/AndroidViewWidget.java | 58 ++++++++ .../taobao/weex/ui/flat/widget/BaseWidget.java | 146 +++++++++++++++++++ .../taobao/weex/ui/flat/widget/ImageWidget.java | 102 +++++++++++++ .../taobao/weex/ui/flat/widget/TextWidget.java | 49 +++++++ .../com/taobao/weex/ui/flat/widget/Widget.java | 63 ++++++++ .../taobao/weex/ui/flat/widget/WidgetGroup.java | 50 +++++++ .../com/taobao/weex/ui/view/WXFrameLayout.java | 50 ++++++- 25 files changed, 1202 insertions(+), 146 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/commons/src/main/java/com/alibaba/weex/commons/adapter/PicassoBasedDrawableLoader.java ---------------------------------------------------------------------- diff --git a/android/commons/src/main/java/com/alibaba/weex/commons/adapter/PicassoBasedDrawableLoader.java b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/PicassoBasedDrawableLoader.java new file mode 100644 index 0000000..0d03934 --- /dev/null +++ b/android/commons/src/main/java/com/alibaba/weex/commons/adapter/PicassoBasedDrawableLoader.java @@ -0,0 +1,112 @@ +/* + * 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.alibaba.weex.commons.adapter; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.PixelFormat; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.view.Gravity; + +import com.squareup.picasso.Picasso; +import com.squareup.picasso.Target; +import com.taobao.weex.WXSDKManager; +import com.taobao.weex.adapter.DrawableStrategy; +import com.taobao.weex.adapter.IDrawableLoader; + + +public class PicassoBasedDrawableLoader implements IDrawableLoader { + + private Context mContext; + + public PicassoBasedDrawableLoader(Context context) { + mContext = context; + } + + @Override + public void setDrawable(final String url, + final DrawableTarget drawableTarget, + final DrawableStrategy drawableStrategy) { + WXSDKManager.getInstance().postOnUiThread(new Runnable() { + @Override + public void run() { + String temp = url; + if (url.startsWith("//")) { + temp = "http:" + url; + } + + /** This is a hack for picasso, as Picasso hold weakReference to Target. + * http://stackoverflow.com/questions/24180805/onbitmaploaded-of-target-object-not-called-on-first-load + */ + class PlaceHolderDrawableTarget extends Drawable implements Target { + + @Override + public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { + BitmapDrawable bitmapDrawable = new BitmapDrawable(mContext.getResources(), bitmap); + bitmapDrawable.setGravity(Gravity.FILL); + if(drawableTarget instanceof StaticTarget) { + ((StaticTarget) drawableTarget).setDrawable(bitmapDrawable, true); + } + } + + @Override + public void onBitmapFailed(Drawable errorDrawable) { + + } + + @Override + public void onPrepareLoad(Drawable placeHolderDrawable) { + if(drawableTarget instanceof StaticTarget) { + ((StaticTarget) drawableTarget).setDrawable(this, true); + } + } + + @Override + public void draw(Canvas canvas) { + + } + + @Override + public void setAlpha(int alpha) { + + } + + @Override + public void setColorFilter(ColorFilter colorFilter) { + + } + + @Override + public int getOpacity() { + return PixelFormat.UNKNOWN; + } + } + Picasso. + with(mContext). + load(temp). + into(new PlaceHolderDrawableTarget()); + } + }, 0); + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/playground/app/src/androidTest/java/com/alibaba/weex/benchmark/BenchmarkTest.java ---------------------------------------------------------------------- diff --git a/android/playground/app/src/androidTest/java/com/alibaba/weex/benchmark/BenchmarkTest.java b/android/playground/app/src/androidTest/java/com/alibaba/weex/benchmark/BenchmarkTest.java index dddada7..2c5f8e7 100644 --- a/android/playground/app/src/androidTest/java/com/alibaba/weex/benchmark/BenchmarkTest.java +++ b/android/playground/app/src/androidTest/java/com/alibaba/weex/benchmark/BenchmarkTest.java @@ -19,6 +19,10 @@ package com.alibaba.weex.benchmark; +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.matcher.ViewMatchers.withClassName; +import static org.hamcrest.MatcherAssert.assertThat; + import android.support.test.InstrumentationRegistry; import android.support.test.espresso.contrib.RecyclerViewActions; import android.support.test.filters.SdkSuppress; @@ -30,18 +34,9 @@ import android.support.test.uiautomator.UiObject2; import android.support.test.uiautomator.Until; import android.text.TextUtils; import android.util.Log; - import com.alibaba.weex.BenchmarkActivity; import com.taobao.weex.ui.view.listview.WXRecyclerView; import com.taobao.weex.utils.WXLogUtils; - -import org.hamcrest.Matchers; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; @@ -49,10 +44,12 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; - -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.matcher.ViewMatchers.withClassName; -import static org.hamcrest.MatcherAssert.assertThat; +import org.hamcrest.Matchers; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class BenchmarkTest { @@ -68,9 +65,7 @@ public class BenchmarkTest { private static List<Long> firstScreenRenderTime = new LinkedList<>(); private static List<Long> flingFrameSeconds = new LinkedList<>(); private static List<Long> scrollFrameSeconds = new LinkedList<>(); - private static final String DUMP_START = "Flags,IntendedVsync,Vsync,OldestInputEvent,NewestInputEvent," - + "HandleInputStart,AnimationStart,PerformTraversalsStart,DrawStart," - + "SyncQueued,SyncStart,IssueDrawCommandsStart,SwapBuffers,FrameCompleted,\n"; + private static final String DUMP_START = "QueueBufferDuration,\n"; private static final String DUMP_END = "---PROFILEDATA---"; private static final String DUMP_COMMAND = "dumpsys gfxinfo com.alibaba.weex framestats reset"; @@ -195,7 +190,7 @@ public class BenchmarkTest { private long calcTime() { BenchmarkActivity benchmarkActivity = mActivityRule.getActivity(); - benchmarkActivity.loadWeexPage(); + benchmarkActivity.loadWeexPage("http://30.8.53.163:8080/complicated.js"); onView(withClassName(Matchers.is(WXRecyclerView.class.getName()))).perform (RecyclerViewActions.scrollToPosition(0)); return benchmarkActivity.getWXInstance().getWXPerformance().screenRenderTime; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/playground/app/src/main/java/com/alibaba/weex/WXApplication.java ---------------------------------------------------------------------- diff --git a/android/playground/app/src/main/java/com/alibaba/weex/WXApplication.java b/android/playground/app/src/main/java/com/alibaba/weex/WXApplication.java index 561d292..5844341 100644 --- a/android/playground/app/src/main/java/com/alibaba/weex/WXApplication.java +++ b/android/playground/app/src/main/java/com/alibaba/weex/WXApplication.java @@ -25,6 +25,7 @@ import android.os.Bundle; import com.alibaba.weex.commons.adapter.DefaultWebSocketAdapterFactory; import com.alibaba.weex.commons.adapter.ImageAdapter; import com.alibaba.weex.commons.adapter.JSExceptionAdapter; +import com.alibaba.weex.commons.adapter.PicassoBasedDrawableLoader; import com.alibaba.weex.extend.PlayDebugAdapter; import com.alibaba.weex.extend.adapter.InterceptWXHttpAdapter; import com.alibaba.weex.extend.component.RichText; @@ -70,6 +71,7 @@ public class WXApplication extends Application { .setWebSocketAdapterFactory(new DefaultWebSocketAdapterFactory()) .setJSExceptionAdapter(new JSExceptionAdapter()) .setHttpAdapter(new InterceptWXHttpAdapter()) + .setDrawableLoader(new PicassoBasedDrawableLoader(this)) .build() ); http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java ---------------------------------------------------------------------- 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 d1bbd52..a3ae67e 100644 --- a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java +++ b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java @@ -28,6 +28,8 @@ import android.net.Uri; import android.os.Message; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.annotation.RestrictTo; +import android.support.annotation.RestrictTo.Scope; import android.text.TextUtils; import android.util.Log; import android.view.Menu; @@ -68,6 +70,7 @@ import com.taobao.weex.ui.component.NestedContainer; import com.taobao.weex.ui.component.WXBasicComponentType; import com.taobao.weex.ui.component.WXComponent; import com.taobao.weex.ui.component.WXComponentFactory; +import com.taobao.weex.ui.flat.FlatGUIIContext; import com.taobao.weex.ui.view.WXScrollView; import com.taobao.weex.ui.view.WXScrollView.WXScrollViewListener; import com.taobao.weex.utils.Trace; @@ -88,7 +91,6 @@ import java.util.concurrent.ConcurrentHashMap; import static com.taobao.weex.http.WXHttpUtil.KEY_USER_AGENT; - /** * Each instance of WXSDKInstance represents an running weex instance. * It can be a pure weex view, or mixed with native view @@ -120,6 +122,8 @@ public class WXSDKInstance implements IWXActivityStateListener,DomContext, View. private boolean mNeedReLoad = false; private static volatile int mViewPortWidth = 750; private int mInstanceViewPortWidth = 750; + private final @NonNull + FlatGUIIContext mUIImp =new FlatGUIIContext(); public long mRenderStartNanos; public int mExecJSTraceId = WXTracing.nextId(); @@ -200,6 +204,11 @@ public class WXSDKInstance implements IWXActivityStateListener,DomContext, View. enableLayerType = enable; } + public @NonNull + FlatGUIIContext getFlatUIContext(){ + return mUIImp; + } + public boolean isNeedValidate() { return mNeedValidate; } @@ -251,6 +260,7 @@ public class WXSDKInstance implements IWXActivityStateListener,DomContext, View. /** * For unittest only. */ + @RestrictTo(Scope.TESTS) WXSDKInstance(Context context,String id) { mInstanceId = id; init(context); http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/adapter/DrawableStrategy.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/adapter/DrawableStrategy.java b/android/sdk/src/main/java/com/taobao/weex/adapter/DrawableStrategy.java index c6daa5a..6c01aa8 100644 --- a/android/sdk/src/main/java/com/taobao/weex/adapter/DrawableStrategy.java +++ b/android/sdk/src/main/java/com/taobao/weex/adapter/DrawableStrategy.java @@ -20,8 +20,13 @@ package com.taobao.weex.adapter; +import com.taobao.weex.common.WXImageStrategy; +import com.taobao.weex.dom.WXImageQuality; + public class DrawableStrategy { public int width; public int height; + public WXImageStrategy imageStrategy; + public WXImageQuality imageQuality; } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/common/Constants.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/common/Constants.java b/android/sdk/src/main/java/com/taobao/weex/common/Constants.java index 06fb668..4be1f28 100644 --- a/android/sdk/src/main/java/com/taobao/weex/common/Constants.java +++ b/android/sdk/src/main/java/com/taobao/weex/common/Constants.java @@ -181,6 +181,8 @@ public class Constants { String ARIA_LABEL = "ariaLabel"; String ARIA_HIDDEN = "ariaHidden"; String UNDEFINED = "undefined"; + + String FLAT = "flat"; } public interface Value { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/common/WXImageStrategy.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/common/WXImageStrategy.java b/android/sdk/src/main/java/com/taobao/weex/common/WXImageStrategy.java index 994c99b..de2572e 100644 --- a/android/sdk/src/main/java/com/taobao/weex/common/WXImageStrategy.java +++ b/android/sdk/src/main/java/com/taobao/weex/common/WXImageStrategy.java @@ -19,7 +19,7 @@ package com.taobao.weex.common; import android.widget.ImageView; - +import com.taobao.weex.adapter.IDrawableLoader.DrawableTarget; import java.util.Map; public class WXImageStrategy { @@ -58,6 +58,12 @@ public class WXImageStrategy { ImageListener imageListener; + WidgetListener widgetListener; + + public interface WidgetListener{ + public void onImageFinish(String url,DrawableTarget drawableTarget,boolean result,Map extra); + } + public interface ImageListener{ public void onImageFinish(String url,ImageView imageView,boolean result,Map extra); } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/dom/ImmutableDomObject.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/ImmutableDomObject.java b/android/sdk/src/main/java/com/taobao/weex/dom/ImmutableDomObject.java index 55439c3..c19ca59 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/ImmutableDomObject.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/ImmutableDomObject.java @@ -19,11 +19,8 @@ package com.taobao.weex.dom; import android.support.annotation.NonNull; - import com.taobao.weex.dom.flex.Spacing; -import static com.taobao.weex.dom.WXDomObject.DESTROYED; - /** * Created by sospartan on 25/10/2016. */ @@ -33,8 +30,26 @@ public interface ImmutableDomObject { @NonNull Spacing getMargin(); float getLayoutWidth(); float getLayoutHeight(); + + /** + * Use {@link #getCSSLayoutLeft()} ()} instead + */ + @Deprecated float getLayoutX(); + + /** + * Use {@link #getCSSLayoutTop()} instead + */ + @Deprecated float getLayoutY(); + + public float getCSSLayoutTop(); + + public float getCSSLayoutBottom(); + + public float getCSSLayoutLeft(); + + public float getCSSLayoutRight(); boolean isFixed(); @NonNull WXStyle getStyles(); @NonNull WXEvent getEvents(); http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/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 dd7e470..d183544 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 @@ -22,6 +22,7 @@ import android.annotation.TargetApi; import android.content.Context; import android.content.Intent; import android.graphics.Color; +import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.Shader; @@ -39,8 +40,8 @@ import android.text.TextUtils; import android.view.Menu; import android.view.View; import android.view.ViewGroup; +import android.view.ViewGroup.MarginLayoutParams; import android.widget.FrameLayout; - import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.taobao.weex.ComponentObserver; @@ -66,6 +67,11 @@ import com.taobao.weex.ui.animation.WXAnimationModule; import com.taobao.weex.ui.component.pesudo.OnActivePseudoListner; import com.taobao.weex.ui.component.pesudo.PesudoStatus; import com.taobao.weex.ui.component.pesudo.TouchActivePseudoListener; +import com.taobao.weex.ui.flat.FlatComponent; +import com.taobao.weex.ui.flat.WidgetContainer; +import com.taobao.weex.ui.flat.FlatGUIIContext; +import com.taobao.weex.ui.flat.widget.AndroidViewWidget; +import com.taobao.weex.ui.flat.widget.Widget; import com.taobao.weex.ui.view.border.BorderDrawable; import com.taobao.weex.ui.view.gesture.WXGesture; import com.taobao.weex.ui.view.gesture.WXGestureObservable; @@ -76,7 +82,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.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -393,15 +398,17 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi protected BorderDrawable getOrCreateBorder() { if (mBackgroundDrawable == null) { - Drawable backgroundDrawable = mHost.getBackground(); - WXViewUtils.setBackGround(mHost,null); mBackgroundDrawable = new BorderDrawable(); - if (backgroundDrawable == null) { - WXViewUtils.setBackGround(mHost,mBackgroundDrawable); - } else { - //TODO Not strictly clip according to background-clip:border-box - WXViewUtils.setBackGround(mHost,new LayerDrawable(new Drawable[]{ - mBackgroundDrawable,backgroundDrawable})); + if (mHost != null) { + Drawable backgroundDrawable = mHost.getBackground(); + WXViewUtils.setBackGround(mHost, null); + if (backgroundDrawable == null) { + WXViewUtils.setBackGround(mHost, mBackgroundDrawable); + } else { + //TODO Not strictly clip according to background-clip:border-box + WXViewUtils.setBackGround(mHost, new LayerDrawable(new Drawable[]{ + mBackgroundDrawable, backgroundDrawable})); + } } } return mBackgroundDrawable; @@ -432,6 +439,9 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi parentBorder.get(Spacing.TOP)) + siblingOffset; int realRight = (int) margin.get(Spacing.RIGHT); int realBottom = (int) margin.get(Spacing.BOTTOM); + Point rawOffset = new Point( + (int) mDomObj.getCSSLayoutLeft(), + (int) mDomObj.getCSSLayoutTop()); if (mPreRealWidth == realWidth && mPreRealHeight == realHeight && mPreRealLeft == realLeft && mPreRealTop == realTop) { return; @@ -445,32 +455,71 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi mInstance.firstScreenRenderFinished(); } - if (mHost == null) { - return; - } MeasureOutput measureOutput = measure(realWidth, realHeight); realWidth = measureOutput.width; realHeight = measureOutput.height; - //fixed style - if (mDomObj.isFixed()) { - setFixedHostLayoutParams(mHost,realWidth,realHeight,realLeft,realRight,realTop,realBottom); - }else { - setHostLayoutParams(mHost, realWidth, realHeight, realLeft, realRight, realTop, realBottom); - } - - mPreRealWidth = realWidth; - mPreRealHeight = realHeight; - mPreRealLeft = realLeft; - mPreRealTop = realTop; - - onFinishLayout(); + setComponentLayoutParams(realWidth, realHeight, realLeft, realTop, realRight, realBottom, rawOffset); } + private void setComponentLayoutParams(int realWidth, int realHeight, int realLeft, int realTop, + int realRight, int realBottom, Point rawOffset) { + FlatGUIIContext UIImp = getInstance().getFlatUIContext(); + WidgetContainer ancestor; + Widget widget; + if ((ancestor = UIImp.getFlatComponentAncestor(this)) != null) { + if (this instanceof FlatComponent && !((FlatComponent) this).promoteToView(true)) { + widget = ((FlatComponent) this).getOrCreateFlatWidget(); + } else { + //TODO Be careful with nested hierarchy, such as widget, view, widget hierarchy. + widget = UIImp.getAndroidViewWidget(this); + } + setWidgetParams(widget, UIImp, rawOffset, realWidth, realHeight, realLeft, realRight, realTop, + realBottom); + } else if (mHost != null) { + if (mDomObj.isFixed()) { + setFixedHostLayoutParams(mHost, realWidth, realHeight, realLeft, realRight, realTop, + realBottom); + } else { + setHostLayoutParams(mHost, realWidth, realHeight, realLeft, realRight, realTop, realBottom); + } + mPreRealWidth = realWidth; + mPreRealHeight = realHeight; + mPreRealLeft = realLeft; + mPreRealTop = realTop; + onFinishLayout(); + } + } + + private void setWidgetParams(Widget widget, FlatGUIIContext UIImp, Point rawoffset, + int width, int height, int left, int right, int top, int bottom) { + Point childOffset = new Point(rawoffset.x, rawoffset.y); + if (mParent != null) { + if (mParent instanceof FlatComponent && + UIImp.getFlatComponentAncestor(mParent) != null && + UIImp.getAndroidViewWidget(mParent) == null) { + Point parentLayoutOffset = ((FlatComponent) mParent).getOrCreateFlatWidget().getLocInFlatContainer(); + childOffset.offset(parentLayoutOffset.x, parentLayoutOffset.y); + } + ViewGroup.LayoutParams lp = mParent + .getChildLayoutParams(this, mHost, width, height, left, right, top, bottom); + if (lp instanceof MarginLayoutParams) { + width = lp.width; + height = lp.height; + left = ((MarginLayoutParams) lp).leftMargin; + right = ((MarginLayoutParams) lp).rightMargin; + top = ((MarginLayoutParams) lp).topMargin; + bottom = ((MarginLayoutParams) lp).bottomMargin; + } + } + widget.setLayout(width, height, left, right, top, bottom, childOffset); - public int getLayoutTopOffsetForSibling(){ - return 0; + if (widget instanceof AndroidViewWidget) { + //TODO generic method if ever possible + setHostLayoutParams((T) ((AndroidViewWidget) widget).getView(), + width, height, childOffset.x, right, childOffset.y, bottom); + } } protected void setHostLayoutParams(T host, int width, int height, int left, int right, int top, int bottom){ @@ -513,6 +562,10 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi } } + public int getLayoutTopOffsetForSibling(){ + return 0; + } + public float getLayoutWidth(){ float w = 0f; if (mDomObj != null) { @@ -537,10 +590,11 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi int right = (int) (padding.get(Spacing.RIGHT) + border.get(Spacing.RIGHT)); int bottom = (int) (padding.get(Spacing.BOTTOM) + border.get(Spacing.BOTTOM)); - if (mHost == null) { - return; + if (this instanceof FlatComponent && !((FlatComponent) this).promoteToView(true)) { + ((FlatComponent) this).getOrCreateFlatWidget().setContentBox(left, top, right, bottom); + } else if (mHost != null) { + mHost.setPadding(left, top, right, bottom); } - mHost.setPadding(left, top, right, bottom); } private void addEvents() { @@ -610,6 +664,13 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi } } readyToRender(); + if (this instanceof FlatComponent && mBackgroundDrawable != null) { + FlatComponent flatComponent = (FlatComponent) this; + if (!flatComponent.promoteToView(true) && !(flatComponent + .getOrCreateFlatWidget() instanceof AndroidViewWidget)) { + flatComponent.getOrCreateFlatWidget().setBackgroundAndBorder(mBackgroundDrawable); + } + } } /** @@ -644,7 +705,7 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi return true; case Constants.Name.BACKGROUND_IMAGE: String bgImage = WXUtils.getString(param, null); - if (bgImage != null && mHost != null) { + if (bgImage != null) { setBackgroundImage(bgImage); } return true; @@ -1098,7 +1159,7 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi } public void setBackgroundColor(String color) { - if (!TextUtils.isEmpty(color)&& mHost!=null) { + if (!TextUtils.isEmpty(color)) { int colorInt = WXResourceUtils.getColor(color); if (!(colorInt == Color.TRANSPARENT && mBackgroundDrawable == null)){ getOrCreateBorder().setColor(colorInt); http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/component/WXDiv.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXDiv.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXDiv.java index 2772cc6..18c734e 100644 --- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXDiv.java +++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXDiv.java @@ -20,41 +20,95 @@ package com.taobao.weex.ui.component; import android.content.Context; import android.support.annotation.NonNull; - import com.taobao.weex.WXSDKInstance; import com.taobao.weex.annotation.Component; import com.taobao.weex.dom.WXDomObject; import com.taobao.weex.ui.ComponentCreator; +import com.taobao.weex.ui.flat.FlatComponent; +import com.taobao.weex.ui.flat.WidgetContainer; +import com.taobao.weex.ui.flat.widget.WidgetGroup; import com.taobao.weex.ui.view.WXFrameLayout; - import java.lang.reflect.InvocationTargetException; /** * div component */ @Component(lazyload = false) -public class WXDiv extends WXVContainer<WXFrameLayout> { +public class WXDiv extends WidgetContainer<WXFrameLayout> implements FlatComponent<WidgetGroup> { + + private WidgetGroup mWidgetGroup; public static class Ceator implements ComponentCreator { - public WXComponent createInstance(WXSDKInstance instance, WXDomObject node, WXVContainer parent) throws IllegalAccessException, InvocationTargetException, InstantiationException { - return new WXDiv(instance,node,parent); + + public WXComponent createInstance(WXSDKInstance instance, WXDomObject node, WXVContainer parent) + throws IllegalAccessException, InvocationTargetException, InstantiationException { + return new WXDiv(instance, node, parent); } } @Deprecated - public WXDiv(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, String instanceId, boolean isLazy) { - this(instance,dom,parent); + public WXDiv(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, String instanceId, + boolean isLazy) { + this(instance, dom, parent); } public WXDiv(WXSDKInstance instance, WXDomObject node, WXVContainer parent) { super(instance, node, parent); } + @Override protected WXFrameLayout initComponentHostView(@NonNull Context context) { - WXFrameLayout frameLayout =new WXFrameLayout(context); + WXFrameLayout frameLayout = new WXFrameLayout(context); frameLayout.holdComponent(this); return frameLayout; } + @Override + public boolean promoteToView(boolean checkAncestor) { + return !intendToBeFlatContainer() || + getInstance().getFlatUIContext().promoteToView(this, checkAncestor, WXDiv.class); + } + + /** + * Create View tree there. Either this method or {@link #createViewImpl()} get called. + * If this object will be promoted to view, then getOrCreateFlatWidget() should never be called. + */ + @Override + @NonNull + public WidgetGroup getOrCreateFlatWidget() { + if (mWidgetGroup == null) { + mWidgetGroup = new WidgetGroup(getInstance().getFlatUIContext().getFlatComponentAncestor(this).getHostView()); + for (int i = 0; i < getChildCount(); i++) { + createChildViewAt(i); + } + mountFlatGUI(); + } + return mWidgetGroup; + } + + @Override + protected void mountFlatGUI() { + if (promoteToView(true)) { + getHostView().mountFlatGUI(widgets); + } else { + mWidgetGroup.replaceAll(widgets); + } + } + + @Override + public void unmountFlatGUI() { + //TODO unmout must be called before you mount FlatGUI second times. + } + + @Override + public boolean intendToBeFlatContainer() { + return getInstance().getFlatUIContext().isFlatUIEnabled() && WXDiv.class.equals(getClass()); + } + + @Override + public boolean isVirtualComponent() { + return !promoteToView(true); + } + } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/component/WXSlider.java ---------------------------------------------------------------------- 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 4ef51f3..1023e3e 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 @@ -29,7 +29,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.widget.FrameLayout; - import com.taobao.weex.WXEnvironment; import com.taobao.weex.WXSDKInstance; import com.taobao.weex.WXSDKManager; @@ -45,7 +44,6 @@ import com.taobao.weex.ui.view.gesture.WXGestureType; import com.taobao.weex.utils.WXLogUtils; import com.taobao.weex.utils.WXUtils; import com.taobao.weex.utils.WXViewUtils; - import java.lang.ref.WeakReference; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; @@ -132,7 +130,7 @@ public class WXSlider extends WXVContainer<FrameLayout> { */ @Override public LayoutParams getChildLayoutParams(WXComponent child,View childView, int width, int height, int left, int right, int top, int bottom) { - ViewGroup.LayoutParams lp = childView.getLayoutParams(); + ViewGroup.LayoutParams lp = childView == null ? null : childView.getLayoutParams(); if (lp == null) { lp = new FrameLayout.LayoutParams(width, height); } else { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/component/WXText.java ---------------------------------------------------------------------- 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 aad2bf4..e07a037 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 @@ -33,6 +33,8 @@ import com.taobao.weex.annotation.Component; import com.taobao.weex.common.Constants; import com.taobao.weex.dom.WXDomObject; import com.taobao.weex.ui.ComponentCreator; +import com.taobao.weex.ui.flat.FlatComponent; +import com.taobao.weex.ui.flat.widget.TextWidget; import com.taobao.weex.ui.view.WXTextView; import com.taobao.weex.utils.FontDO; import com.taobao.weex.utils.TypefaceUtil; @@ -44,7 +46,9 @@ import java.lang.reflect.InvocationTargetException; * Text component */ @Component(lazyload = false) -public class WXText extends WXComponent<WXTextView> { +public class WXText extends WXComponent<WXTextView> implements FlatComponent<TextWidget> { + + private TextWidget mTextWidget; /** * The default text size @@ -53,6 +57,25 @@ public class WXText extends WXComponent<WXTextView> { private BroadcastReceiver mTypefaceObserver; private String mFontFamily; + @Override + public boolean promoteToView(boolean checkAncestor) { + return getInstance().getFlatUIContext().promoteToView(this, checkAncestor, WXText.class); + } + + @Override + @NonNull + public TextWidget getOrCreateFlatWidget() { + if (mTextWidget == null) { + mTextWidget = new TextWidget(getInstance().getFlatUIContext().getFlatComponentAncestor(this).getHostView()); + } + return mTextWidget; + } + + @Override + public boolean isVirtualComponent() { + return !promoteToView(true); + } + public static class Creator implements ComponentCreator { public WXComponent createInstance(WXSDKInstance instance, WXDomObject node, WXVContainer parent) throws IllegalAccessException, InvocationTargetException, InstantiationException { @@ -79,11 +102,14 @@ public class WXText extends WXComponent<WXTextView> { @Override public void updateExtra(Object extra) { - if (extra instanceof Layout && - getHostView() != null && !extra.equals(getHostView().getTextLayout())) { + if(extra instanceof Layout) { final Layout layout = (Layout) extra; - getHostView().setTextLayout(layout); - getHostView().invalidate(); + if (!promoteToView(true)) { + getOrCreateFlatWidget().updateTextDrawable(layout); + } else if (getHostView() != null && !extra.equals(getHostView().getTextLayout())) { + getHostView().setTextLayout(layout); + getHostView().invalidate(); + } } } @@ -127,28 +153,6 @@ public class WXText extends WXComponent<WXTextView> { } } - /** - * Flush view no matter what height and width the {@link WXDomObject} specifies. - * @param extra must be a {@link Layout} object, otherwise, nothing will happen. - */ - private void flushView(Object extra) { - if (extra instanceof Layout && - getHostView() != null && !extra.equals(getHostView().getTextLayout())) { - final Layout layout = (Layout) extra; - /**The following if block change the height of the width of the textView. - * other part of the code is the same to updateExtra - */ - ViewGroup.LayoutParams layoutParams = getHostView().getLayoutParams(); - if (layoutParams != null) { - layoutParams.height = layout.getHeight(); - layoutParams.width = layout.getWidth(); - getHostView().setLayoutParams(layoutParams); - } - getHostView().setTextLayout(layout); - getHostView().invalidate(); - } - } - @Override protected Object convertEmptyProperty(String propName, Object originalValue) { switch (propName) { @@ -161,6 +165,13 @@ public class WXText extends WXComponent<WXTextView> { } @Override + protected void createViewImpl() { + if(promoteToView(true)) { + super.createViewImpl(); + } + } + + @Override public void destroy() { super.destroy(); if (WXEnvironment.getApplication() != null && mTypefaceObserver != null) { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java ---------------------------------------------------------------------- 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 f769c2a..43b45a7 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 @@ -19,15 +19,14 @@ package com.taobao.weex.ui.component; import android.content.Intent; +import android.util.Pair; import android.support.annotation.Nullable; import android.view.Menu; import android.view.View; import android.view.ViewGroup; - import com.taobao.weex.WXSDKInstance; import com.taobao.weex.common.Constants; import com.taobao.weex.dom.WXDomObject; - import java.util.ArrayList; /** @@ -115,7 +114,11 @@ public abstract class WXVContainer<T extends ViewGroup> extends WXComponent<T> { * */ public ViewGroup.LayoutParams getChildLayoutParams(WXComponent child,View childView, int width, int height, int left, int right, int top, int bottom){ - ViewGroup.LayoutParams lp = childView.getLayoutParams(); + ViewGroup.LayoutParams lp = null; + if (childView != null) { + lp = childView.getLayoutParams(); + } + if(lp == null) { lp = new ViewGroup.LayoutParams(width,height); }else{ @@ -228,6 +231,11 @@ public abstract class WXVContainer<T extends ViewGroup> extends WXComponent<T> { return original; } + /** + * Use {@link #getChildCount()} instead + * @return + */ + @Deprecated public int childCount() { return mChildren == null ? 0 : mChildren.size(); } @@ -242,7 +250,7 @@ public abstract class WXVContainer<T extends ViewGroup> extends WXComponent<T> { } public int getChildCount() { - return mChildren.size(); + return childCount(); } public void addChild(WXComponent child) { @@ -268,21 +276,31 @@ public abstract class WXVContainer<T extends ViewGroup> extends WXComponent<T> { return mChildren.indexOf(comp); } - public void createChildViewAt(int index){ + public void createChildViewAt(int index) { long startNanos = System.nanoTime(); + Pair<WXComponent, Integer> ret = rearrangeIndexAndGetChild(index); + if (ret.first != null) { + WXComponent child = ret.first; + child.createView(); + if (!child.isVirtualComponent()) { + addSubView(child.getHostView(), ret.second); + } + } + mTraceInfo.uiThreadNanos += (System.nanoTime() - startNanos); + } + + protected Pair<WXComponent, Integer> rearrangeIndexAndGetChild(int index){ int indexToCreate = index; if(indexToCreate < 0){ indexToCreate = childCount()-1; - if(indexToCreate < 0 ){ - return; - } } - WXComponent child = getChild(indexToCreate); - child.createView(); - if(!child.isVirtualComponent()){ - addSubView(child.getHostView(),indexToCreate); + + if (indexToCreate<0){ + return new Pair<>(null, indexToCreate); + } + else { + return new Pair<>(getChild(indexToCreate), indexToCreate); } - mTraceInfo.uiThreadNanos += (System.nanoTime() - startNanos); } protected void addSubView(View child, int index) { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java index 3095c04..cac3048 100644 --- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java +++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java @@ -20,22 +20,25 @@ package com.taobao.weex.ui.component.list; import android.content.Context; import android.support.annotation.NonNull; +import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; - import com.taobao.weex.WXSDKInstance; import com.taobao.weex.annotation.Component; +import com.taobao.weex.common.Constants.Name; import com.taobao.weex.dom.WXDomObject; import com.taobao.weex.ui.component.WXVContainer; +import com.taobao.weex.ui.flat.WidgetContainer; import com.taobao.weex.ui.view.WXFrameLayout; +import com.taobao.weex.utils.WXUtils; /** * Root component for components in {@link WXListComponent} */ @Component(lazyload = false) -public class WXCell extends WXVContainer<WXFrameLayout> { +public class WXCell extends WidgetContainer<WXFrameLayout> { private int mLastLocationY = 0; private ViewGroup mRealView; @@ -49,11 +52,11 @@ public class WXCell extends WXVContainer<WXFrameLayout> { @Deprecated public WXCell(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, String instanceId, boolean isLazy) { - this(instance,dom,parent,isLazy); + super(instance, dom, parent); } public WXCell(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, boolean isLazy) { - super(instance, dom, parent,true ); + super(instance, dom, parent); } @Override @@ -82,6 +85,17 @@ public class WXCell extends WXVContainer<WXFrameLayout> { } } + @Override + protected boolean setProperty(String key, Object param) { + if(TextUtils.equals(Name.FLAT, key)){ + getInstance().getFlatUIContext().setFlatUIEnabled(WXUtils.getBoolean(param, false)); + return true; + } + else { + return super.setProperty(key, param); + } + } + public int getLocationFromStart(){ return mLastLocationY; } @@ -127,4 +141,20 @@ public class WXCell extends WXVContainer<WXFrameLayout> { mHeadView.setTranslationX(0); mHeadView.setTranslationY(0); } + + @Override + protected void mountFlatGUI() { + getHostView().mountFlatGUI(widgets); + } + + @Override + public void unmountFlatGUI() { + + } + + @Override + public boolean intendToBeFlatContainer() { + //TODO Is it possible to remove the cell class judge + return getInstance().getFlatUIContext().isFlatUIEnabled() && WXCell.class.equals(getClass()); + } } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXListComponent.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXListComponent.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXListComponent.java index ab53f78..c5ef8b5 100644 --- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXListComponent.java +++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXListComponent.java @@ -19,6 +19,7 @@ package com.taobao.weex.ui.component.list; import android.content.Context; +import android.util.Pair; import com.taobao.weex.WXSDKInstance; import com.taobao.weex.annotation.Component; @@ -187,35 +188,31 @@ public class WXListComponent extends BasicListComponent<BounceRecyclerView> { @Override public void createChildViewAt(int index) { - int indexToCreate = index; - if (indexToCreate < 0) { - indexToCreate = childCount() - 1; - if (indexToCreate < 0) { - return; - } - } - final WXComponent child = getChild(indexToCreate); - if (child instanceof WXBaseRefresh) { - child.createView(); - if (child instanceof WXRefresh) { - getHostView().setOnRefreshListener((WXRefresh) child); - getHostView().postDelayed(new Runnable() { - @Override - public void run() { - getHostView().setHeaderView(child); - } - }, 100); - } else if (child instanceof WXLoading) { - getHostView().setOnLoadingListener((WXLoading) child); - getHostView().postDelayed(new Runnable() { - @Override - public void run() { - getHostView().setFooterView(child); - } - }, 100); + Pair<WXComponent, Integer> ret = rearrangeIndexAndGetChild(index); + if(ret.first != null) { + final WXComponent child = getChild(ret.second); + if (child instanceof WXBaseRefresh) { + child.createView(); + if (child instanceof WXRefresh) { + getHostView().setOnRefreshListener((WXRefresh) child); + getHostView().postDelayed(new Runnable() { + @Override + public void run() { + getHostView().setHeaderView(child); + } + }, 100); + } else if (child instanceof WXLoading) { + getHostView().setOnLoadingListener((WXLoading) child); + getHostView().postDelayed(new Runnable() { + @Override + public void run() { + getHostView().setFooterView(child); + } + }, 100); + } + } else { + super.createChildViewAt(ret.second); } - } else { - super.createChildViewAt(indexToCreate); } } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/flat/FlatComponent.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/flat/FlatComponent.java b/android/sdk/src/main/java/com/taobao/weex/ui/flat/FlatComponent.java new file mode 100644 index 0000000..2c0cc46 --- /dev/null +++ b/android/sdk/src/main/java/com/taobao/weex/ui/flat/FlatComponent.java @@ -0,0 +1,33 @@ +/** + * 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.flat; + + +import android.support.annotation.NonNull; +import android.support.annotation.RestrictTo; +import android.support.annotation.RestrictTo.Scope; +import com.taobao.weex.ui.flat.widget.Widget; + +@RestrictTo(Scope.LIBRARY) +public interface FlatComponent<T extends Widget> { + + boolean promoteToView(boolean checkAncestor); + + @NonNull T getOrCreateFlatWidget(); +} http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/flat/FlatGUIIContext.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/flat/FlatGUIIContext.java b/android/sdk/src/main/java/com/taobao/weex/ui/flat/FlatGUIIContext.java new file mode 100644 index 0000000..1026730 --- /dev/null +++ b/android/sdk/src/main/java/com/taobao/weex/ui/flat/FlatGUIIContext.java @@ -0,0 +1,113 @@ +/** + * 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.flat; + + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.RestrictTo; +import android.support.annotation.RestrictTo.Scope; +import android.support.v4.util.ArrayMap; +import android.text.TextUtils; +import com.taobao.weex.common.Constants.Name; +import com.taobao.weex.dom.ImmutableDomObject; +import com.taobao.weex.dom.WXAttr; +import com.taobao.weex.dom.WXDomObject; +import com.taobao.weex.dom.WXStyle; +import com.taobao.weex.ui.component.WXComponent; +import com.taobao.weex.ui.flat.widget.AndroidViewWidget; +import java.util.Map; + +//TODO when Weex instance is destroyed, there is a work of garbage collection. +//TODO !!!!The index of weex playground show empty cell sometimes. +//TODO The constructor of FlatGUIContext should have a flag decide whether to enable flagGUI. + +@RestrictTo(Scope.LIBRARY) +public class FlatGUIIContext { + + private boolean mFlatUIEnabled; + private Map<WXComponent, WidgetContainer> mWidgetRegistry = new ArrayMap<>(); + private Map<WXComponent, AndroidViewWidget> mViewWidgetRegistry = new ArrayMap<>(); + + @RestrictTo(Scope.LIBRARY) + public void setFlatUIEnabled(boolean flag){ + mFlatUIEnabled = flag; + } + + public boolean isFlatUIEnabled() { + return mFlatUIEnabled; + } + + public void register(@NonNull WXComponent descendant, @NonNull WidgetContainer ancestor) { + if (!(ancestor instanceof FlatComponent) || + ((FlatComponent) ancestor).promoteToView(true)) { + mWidgetRegistry.put(descendant, ancestor); + } + } + + public void register(@NonNull WXComponent component, @NonNull AndroidViewWidget viewWidget){ + mViewWidgetRegistry.put(component, viewWidget); + } + + public + @Nullable + WidgetContainer getFlatComponentAncestor(@NonNull WXComponent flatWidget) { + return mWidgetRegistry.get(flatWidget); + } + + public + @Nullable + AndroidViewWidget getAndroidViewWidget(@NonNull WXComponent component) { + return mViewWidgetRegistry.get(component); + } + + public boolean promoteToView(@NonNull WXComponent component, boolean checkAncestor, + @NonNull Class<? extends WXComponent<?>> expectedClass) { + return !isFlatUIEnabled() || + !expectedClass.equals(component.getClass()) || + TextUtils.equals(component.getRef(), WXDomObject.ROOT) || + (checkAncestor && getFlatComponentAncestor(component) == null) || + checkComponent(component); + } + + private boolean checkComponent(@NonNull WXComponent component) { + boolean ret = false; + ImmutableDomObject domObject = component.getDomObject(); + if (domObject != null) { + WXStyle style = domObject.getStyles(); + WXAttr attr = domObject.getAttrs(); + //disabled && pro_fixed_size, attr or style + if (style.containsKey(Name.OPACITY) || + style.containsKey(Name.TRANSFORM) || + attr.containsKey(Name.ELEVATION) || + attr.containsKey(Name.ARIA_HIDDEN) || + attr.containsKey(Name.ARIA_LABEL) || + attr.containsKey(WXComponent.PROP_FIXED_SIZE) || + style.containsKey(Name.VISIBILITY) || + style.containsKey(Name.POSITION) || + attr.containsKey(Name.DISABLED) || + attr.containsKey(Name.PREVENT_MOVE_EVENT) || + !style.getPesudoStyles().isEmpty() || + domObject.getEvents().size() > 0) { + ret = true; + } + } + return ret; + } +} http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/flat/WidgetContainer.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/flat/WidgetContainer.java b/android/sdk/src/main/java/com/taobao/weex/ui/flat/WidgetContainer.java new file mode 100644 index 0000000..d501802 --- /dev/null +++ b/android/sdk/src/main/java/com/taobao/weex/ui/flat/WidgetContainer.java @@ -0,0 +1,92 @@ +/** + * 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.flat; + + +import android.support.annotation.RestrictTo; +import android.support.annotation.RestrictTo.Scope; +import android.util.Pair; +import android.view.ViewGroup; +import com.taobao.weex.WXSDKInstance; +import com.taobao.weex.dom.WXDomObject; +import com.taobao.weex.ui.component.WXComponent; +import com.taobao.weex.ui.component.WXVContainer; +import com.taobao.weex.ui.flat.widget.AndroidViewWidget; +import com.taobao.weex.ui.flat.widget.Widget; +import java.util.LinkedList; +import java.util.List; + +@RestrictTo(Scope.LIBRARY) +public abstract class WidgetContainer<T extends ViewGroup> extends WXVContainer<T> { + + protected List<Widget> widgets = new LinkedList<>(); + + public WidgetContainer(WXSDKInstance instance, WXDomObject node, WXVContainer parent) { + super(instance, node, parent); + } + + protected abstract void mountFlatGUI(); + + protected abstract void unmountFlatGUI(); + + public boolean intendToBeFlatContainer() { + return false; + } + + @Override + public void createChildViewAt(int index) { + if (intendToBeFlatContainer()) { + Pair<WXComponent, Integer> ret = rearrangeIndexAndGetChild(index); + if (ret.first != null) { + WXComponent child = ret.first; + Widget flatChild; + FlatGUIIContext uiImp = getInstance().getFlatUIContext(); + WidgetContainer parent = uiImp.getFlatComponentAncestor(this); + if (parent == null || uiImp.getAndroidViewWidget(this) != null) { + parent = this; + } + uiImp.register(child, parent); + + if (child instanceof FlatComponent && !((FlatComponent) child).promoteToView(false)) { + flatChild = ((FlatComponent) child).getOrCreateFlatWidget(); + } else { + flatChild = new AndroidViewWidget(parent.getHostView()); + uiImp.register(child, (AndroidViewWidget) flatChild); + child.createView(); + ((AndroidViewWidget) flatChild).setContentView(child.getHostView()); + //TODO Use a sort algorithm to decide the childIndex of AndroidViewWidget + parent.addSubView(child.getHostView(), -1); + } + addFlatChild(flatChild, ret.second); + } + } else { + super.createChildViewAt(index); + } + } + + private void addFlatChild(Widget widget, int index) { + if (index >= widgets.size()) { + widgets.add(widget); + } else { + widgets.add(index, widget); + } + //TODO do a partial update, not mount the whole flatContainer. + mountFlatGUI(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/AndroidViewWidget.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/AndroidViewWidget.java b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/AndroidViewWidget.java new file mode 100644 index 0000000..c33c2a9 --- /dev/null +++ b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/AndroidViewWidget.java @@ -0,0 +1,58 @@ +/** + * 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.flat.widget; + + +import android.graphics.Canvas; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.RestrictTo; +import android.support.annotation.RestrictTo.Scope; +import android.view.View; + +@RestrictTo(Scope.LIBRARY) +public class AndroidViewWidget extends BaseWidget { + + private @Nullable View mView; + public AndroidViewWidget(@NonNull View flatContainer) { + super(flatContainer); + } + + public void setContentView(@NonNull View view){ + this.mView = view; + } + + @Override + public void setContentBox(int leftOffset, int topOffset, int rightOffset, int bottomOffset) { + if(mView!=null) { + mView.setPadding(leftOffset, topOffset, rightOffset, bottomOffset); + } + } + + @Override + public void onDraw(@NonNull Canvas canvas) { + if(mView!=null) { + mView.draw(canvas); + } + } + + public @Nullable View getView() { + return mView; + } +} http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/BaseWidget.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/BaseWidget.java b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/BaseWidget.java new file mode 100644 index 0000000..f0964d8 --- /dev/null +++ b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/BaseWidget.java @@ -0,0 +1,146 @@ +/** + * 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.flat.widget; + + +import android.graphics.Canvas; +import android.graphics.Point; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.RestrictTo; +import android.support.annotation.RestrictTo.Scope; +import android.view.View; +import com.taobao.weex.ui.view.border.BorderDrawable; + +@RestrictTo(Scope.LIBRARY) +abstract class BaseWidget implements Widget { + + //TODO Reconsider the field parameter in this class and the operation during draw(); Make a CPU/Memory balance. + //TODO use float to avoid 1px problem + private BorderDrawable backgroundBorder; + private int leftOffset, topOffset, rightOffset, bottomOffset; + private Rect borderBox = new Rect(); + private Point offsetOfContainer = new Point(); + private View flatContainer; + + BaseWidget(@NonNull View flatContainer){ + //TODO maybe FlatUIImp is better. + this.flatContainer = flatContainer; + } + + @Override + public void setLayout(int width, int height, int left, int right, int top, int bottom, Point offset) { + this.offsetOfContainer = offset; + borderBox.set(left, top, left + width, top + height); + if (backgroundBorder != null) { + setBackgroundAndBorder(backgroundBorder); + } + invalidate(); + } + + @Override + public void setContentBox(int leftOffset, int topOffset, int rightOffset, int bottomOffset) { + this.leftOffset = leftOffset; + this.topOffset = topOffset; + this.rightOffset = rightOffset; + this.bottomOffset = bottomOffset; + invalidate(); + } + + @Override + public void setBackgroundAndBorder(@NonNull BorderDrawable backgroundBorder) { + //TODO Change the code of BorderDrawable is more appropriate as it draws the borderLine from (0,0) not from getBounds + //TODO If the above is finished, no more traslate in draw in needed, only clip is enough. + this.backgroundBorder = backgroundBorder; + Rect backgroundBox = new Rect(borderBox); + backgroundBox.offset(-borderBox.left, -borderBox.top); + backgroundBorder.setBounds(backgroundBox); + setCallback(backgroundBorder); + invalidate(); + } + + @Override + public + @NonNull + Rect getBorderBox() { + return borderBox; + } + + @NonNull + @Override + public Point getLocInFlatContainer() { + return offsetOfContainer; + } + + @Nullable + @Override + public BorderDrawable getBackgroundAndBorder() { + return backgroundBorder; + } + + @Override + public int getLeftOffset() { + return leftOffset; + } + + @Override + public int getTopOffset() { + return topOffset; + } + + @Override + public int getRightOffset() { + return rightOffset; + } + + @Override + public int getBottomOffset() { + return bottomOffset; + } + + @Override + public final void draw(@NonNull Canvas canvas) { + canvas.save(); + canvas.clipRect(borderBox); + canvas.translate(borderBox.left, borderBox.top); + if (backgroundBorder != null) { + backgroundBorder.draw(canvas); + } + canvas.clipRect(leftOffset, topOffset, borderBox.width()-rightOffset, borderBox.height() - bottomOffset); + canvas.translate(leftOffset, topOffset); + onDraw(canvas); + canvas.restore(); + } + + @Override + public void invalidate() { + Rect dirtyRegion= new Rect(borderBox); + dirtyRegion.offset(offsetOfContainer.x, offsetOfContainer.y); + flatContainer.invalidate(dirtyRegion); + } + + protected void setCallback(@NonNull Drawable drawable){ + if(flatContainer!=null){ + drawable.setCallback(flatContainer); + } + } +} + http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/ImageWidget.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/ImageWidget.java b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/ImageWidget.java new file mode 100644 index 0000000..5054119 --- /dev/null +++ b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/ImageWidget.java @@ -0,0 +1,102 @@ +/** + * 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.flat.widget; + + +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.RestrictTo; +import android.support.annotation.RestrictTo.Scope; +import android.view.View; +import android.widget.ImageView.ScaleType; +import com.taobao.weex.adapter.IDrawableLoader.AnimatedTarget; +import com.taobao.weex.adapter.IDrawableLoader.StaticTarget; +import com.taobao.weex.ui.component.WXImage; +import com.taobao.weex.utils.ImageDrawable; +import java.util.Arrays; + +@RestrictTo(Scope.LIBRARY) +public class ImageWidget extends BaseWidget implements StaticTarget, AnimatedTarget { + + //TODO WXImage.src.readyToRender + //TODO blur + private Drawable mImageDrawable; + private ScaleType mScaleType = WXImage.DEFAULT_SCALE_TYPE; + private float[] borderRadius; + + public ImageWidget(@NonNull View flatContainer) { + super(flatContainer); + } + + @Override + public void onDraw(@NonNull Canvas canvas) { + if (mImageDrawable != null) { + mImageDrawable.draw(canvas); + } + } + + @Override + public void setAnimatedDrawable(@Nullable Drawable drawable) { + mImageDrawable = drawable; + initDrawable(); + } + + @Override + public void setDrawable(@Nullable Drawable drawable, boolean resetBounds) { + setDrawable(drawable); + } + + public void setDrawable(@Nullable Drawable imageDrawable) { + //As there is a translate operation in BaseWidget, + //width and height of the widget instead of borderBox should be passed to ImageDrawable. + mImageDrawable = ImageDrawable + .createImageDrawable(imageDrawable, mScaleType, null, + getBorderBox().width() - getLeftOffset() - getRightOffset(), + getBorderBox().height() - getTopOffset() - getBottomOffset(), false); + if (mImageDrawable instanceof ImageDrawable) { + if (!Arrays.equals(((ImageDrawable) mImageDrawable).getCornerRadii(), borderRadius)) { + ((ImageDrawable) mImageDrawable).setCornerRadii(borderRadius); + } + } + initDrawable(); + } + + public void setScaleType(ScaleType scaleType) { + this.mScaleType = scaleType; + setDrawable(mImageDrawable); + } + + public void setBorderRadius(float[] borderRadius) { + this.borderRadius = borderRadius; + } + + public @Nullable Drawable getDrawable(){ + return mImageDrawable; + } + + private void initDrawable(){ + if(mImageDrawable!=null) { + mImageDrawable.setBounds(0, 0, getBorderBox().width(), getBorderBox().height()); + setCallback(mImageDrawable); + invalidate(); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/TextWidget.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/TextWidget.java b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/TextWidget.java new file mode 100644 index 0000000..992a01b --- /dev/null +++ b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/TextWidget.java @@ -0,0 +1,49 @@ +/** + * 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.flat.widget; + + +import android.graphics.Canvas; +import android.support.annotation.NonNull; +import android.support.annotation.RestrictTo; +import android.support.annotation.RestrictTo.Scope; +import android.text.Layout; +import android.view.View; + +@RestrictTo(Scope.LIBRARY) +public class TextWidget extends BaseWidget { + + private Layout mLayout; + + public TextWidget(@NonNull View flatContainer) { + super(flatContainer); + } + + @Override + public void onDraw(@NonNull Canvas canvas) { + if (mLayout != null) { + mLayout.draw(canvas); + } + } + + public void updateTextDrawable(Layout layout) { + this.mLayout = layout; + invalidate(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/Widget.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/Widget.java b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/Widget.java new file mode 100644 index 0000000..0b4e724 --- /dev/null +++ b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/Widget.java @@ -0,0 +1,63 @@ +/** + * 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.flat.widget; + + +import android.graphics.Canvas; +import android.graphics.Point; +import android.graphics.Rect; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.RestrictTo; +import android.support.annotation.RestrictTo.Scope; +import com.taobao.weex.ui.view.border.BorderDrawable; + +@RestrictTo(Scope.LIBRARY) +public interface Widget { + + public static final String TAG = "Widget"; + + void draw(@NonNull Canvas canvas); + + void onDraw(@NonNull Canvas canvas); + + void setBackgroundAndBorder(@NonNull BorderDrawable backgroundBorder); + + void setLayout(int width, int height, int left, int right, int top, int bottom, Point offset); + + void setContentBox(int leftOffset, int topOffset, int rightOffset, int bottomOffset); + + @NonNull Rect getBorderBox(); + + @Nullable + BorderDrawable getBackgroundAndBorder(); + + @NonNull Point getLocInFlatContainer(); + + int getLeftOffset(); + + int getTopOffset(); + + int getRightOffset(); + + int getBottomOffset(); + + void invalidate(); + +} http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/WidgetGroup.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/WidgetGroup.java b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/WidgetGroup.java new file mode 100644 index 0000000..297cd4e --- /dev/null +++ b/android/sdk/src/main/java/com/taobao/weex/ui/flat/widget/WidgetGroup.java @@ -0,0 +1,50 @@ +/** + * 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.flat.widget; + + +import android.graphics.Canvas; +import android.support.annotation.NonNull; +import android.support.annotation.RestrictTo; +import android.support.annotation.RestrictTo.Scope; +import android.view.View; +import java.util.LinkedList; +import java.util.List; + +@RestrictTo(Scope.LIBRARY) +public class WidgetGroup extends BaseWidget { + + private List<Widget> mChildren = new LinkedList<>(); + + public WidgetGroup(@NonNull View flatContainer) { + super(flatContainer); + } + + public void replaceAll(@NonNull List<Widget> widgets) { + mChildren = widgets; + invalidate(); + } + + @Override + public void onDraw(@NonNull Canvas canvas) { + for (Widget child : mChildren) { + child.draw(canvas); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/bc6ea406/android/sdk/src/main/java/com/taobao/weex/ui/view/WXFrameLayout.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/view/WXFrameLayout.java b/android/sdk/src/main/java/com/taobao/weex/ui/view/WXFrameLayout.java index ec39462..db9a8ec 100644 --- a/android/sdk/src/main/java/com/taobao/weex/ui/view/WXFrameLayout.java +++ b/android/sdk/src/main/java/com/taobao/weex/ui/view/WXFrameLayout.java @@ -20,27 +20,32 @@ package com.taobao.weex.ui.view; import android.content.Context; import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.MotionEvent; import android.widget.FrameLayout; - import com.taobao.weex.ui.component.WXDiv; +import com.taobao.weex.ui.flat.widget.Widget; import com.taobao.weex.ui.view.gesture.WXGesture; import com.taobao.weex.ui.view.gesture.WXGestureObservable; import com.taobao.weex.utils.WXViewUtils; - import java.lang.ref.WeakReference; +import java.util.List; /** * FrameLayout wrapper * */ +//TODO Read the code of View.draw, and override the correct method. public class WXFrameLayout extends FrameLayout implements WXGestureObservable,IRenderStatus<WXDiv>,IRenderResult<WXDiv> { private WXGesture wxGesture; private WeakReference<WXDiv> mWeakReference; + private List<Widget> mWidgets; + public WXFrameLayout(Context context) { super(context); } @@ -60,12 +65,6 @@ public class WXFrameLayout extends FrameLayout implements WXGestureObservable,IR } @Override - protected void onDraw(Canvas canvas) { - WXViewUtils.clipCanvasWithinBorderBox(this, canvas); - super.onDraw(canvas); - } - - @Override public void holdComponent(WXDiv component) { mWeakReference = new WeakReference<WXDiv>(component); } @@ -75,4 +74,39 @@ public class WXFrameLayout extends FrameLayout implements WXGestureObservable,IR public WXDiv getComponent() { return null != mWeakReference ? mWeakReference.get() : null; } + + public void mountFlatGUI(List<Widget> widgets){ + this.mWidgets = widgets; + if (mWidgets != null) { + setWillNotDraw(true); + } + invalidate(); + } + + public void unmountFlatGUI(){ + mWidgets = null; + setWillNotDraw(false); + invalidate(); + } + + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return mWidgets != null || super.verifyDrawable(who); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (mWidgets != null) { + canvas.save(); + //TODO need clip here + canvas.translate(getPaddingLeft(), getPaddingTop()); + for (Widget widget : mWidgets) { + widget.draw(canvas); + } + canvas.restore(); + } else { + WXViewUtils.clipCanvasWithinBorderBox(this, canvas); + super.dispatchDraw(canvas); + } + } }