diff --git a/README-ch.md b/README-ch.md index 39c721f..20cc7c5 100644 --- a/README-ch.md +++ b/README-ch.md @@ -17,6 +17,10 @@ + [Virtualview-iOS](https://github.com/alibaba/VirtualView-iOS) + [LazyScrollView](https://github.com/alibaba/lazyscrollview) +### Server + ++ [TAC](https://github.com/alibaba/tac) + Tangram是一套动态化构建 Native 页面的框架,它包含 Tangram Android、Tangram iOS,管理后台等一些列基础设施。本工程是 Tangram Android 的sdk 项目地址,底层依赖于[vlayout](https://github.com/alibaba/vlayout) 和 [UltraViewPager](https://github.com/alibaba/UltraViewPager)。 # 特点 diff --git a/README.md b/README.md index 3c57d54..dffdc21 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,10 @@ + [Virtualview-iOS](https://github.com/alibaba/VirtualView-iOS) + [LazyScrollView](https://github.com/alibaba/lazyscrollview) +### Server + ++ [TAC](https://github.com/alibaba/tac) + Tangram is a modular UI solution for building native page dynamically including Tangram for Android, Tangram for iOS and even backend CMS. This project provides the sdk on Android which is based on [vlayout](https://github.com/alibaba/vlayout) and [UltraViewPager](https://github.com/alibaba/UltraViewPager). # Features diff --git a/docs/Tutorial-ch.md b/docs/Tutorial-ch.md index 6142664..1d6c962 100644 --- a/docs/Tutorial-ch.md +++ b/docs/Tutorial-ch.md @@ -63,11 +63,12 @@ TangramBuilder.InnerBuilder builder = TangramBuilder.newInnerBuilder(TangramActi 一般情况下,内置卡片的类型已经满足大部分场景了,业务方主要是注册一下自定义组件。注册组件有3种方式: -+ 注册绑定组件类型和自定义```View```,比如```builder.registerCell(1, TestView.class);```。意思是类型为1的组件渲染时会被绑定到```TestView```的实例上,这种方式注册的组件使用通用的组件模型```BaseCell```。 ++ 注册绑定组件类型和自定义```View```,比如```builder.registerCell("testView", TestView.class);```。意思是类型为1的组件渲染时会被绑定到```TestView```的实例上,这种方式注册的组件使用通用的组件模型```BaseCell```。 + 注册绑定组件类型、自定义 model、自定义```View```,比如```builder.registerCell(1, TestCell.class, TestView.class);```。意思是类型为1的组件使用自定义的组件模型```TestCell```,它应当继承于```BaseCell```,在渲染时会被绑定到```TestView```的实例上。 + 注册绑定组件类型、自定义model、自定义```ViewHolder```,比如```builder.registerCell(1, TestCell.class, new ViewHolderCreator<>(R.layout.item_holder, TestViewHolder.class, TestView.class));```。意思是类型为1的组件使用自定义的组件模型```TestCell```,它应当继承于```BaseCell```,在渲染时以```R.layout.item_holder```为布局创建类型为```TestView ```的 view,并绑定到类型为```TestViewHolder```的 viewHolder 上,组件数据被绑定到定到```TestView```的实例上。 -一般情况下,使用前两种方式注册组件即可。至于组件开发规范,请参考[组件文档]()。 +所有的组件注册推荐使用 string 作为 type,便于理解及追溯。 +一般情况下,使用前两种方式注册组件即可。至于组件开发规范,请参考[组件文档](http://tangram.pingguohe.net/docs/android/develop-component)。 ## 5.生成```TangramEngine```实例 diff --git a/docs/Tutorial.md b/docs/Tutorial.md index ef6d28b..5972477 100644 --- a/docs/Tutorial.md +++ b/docs/Tutorial.md @@ -63,11 +63,12 @@ When the builder object created, default cards and cells supported by Tangram is The default cards provided by framework meets the most UI situation, while cells need be provided by Tangram users. There's three ways to register a custom: -+ bind a cell's type to a custom view class using ```builder.registerCell(1, TestView.class);```, which means a cell's data with type 1 will be binded to an instance of type ```TestView```. Registering in this way, the cell use general model class ```BaseCell```. ++ bind a cell's type to a custom view class using ```builder.registerCell("testView", TestView.class);```, which means a cell's data with type 1 will be binded to an instance of type ```TestView```. Registering in this way, the cell use general model class ```BaseCell```. + bind a cell's type to a custom model class and custom view class using ```builder.registerCell(1, TestCell.class, TestView.class);```, which means a cell with type 1 will use custom model class ```TestCell``` which should be extended from ```BaseCell``` and its data will be binded to an instance of ```TestView``` during rendering. + bind a cell's type to a custom class and custom viewholder class using ```builder.registerCell(1, TestCell.class, new ViewHolderCreator<>(R.layout.item_holder, TestViewHolder.class, TestView.class));```, which means a cell with type 1 will use custom model class ```TestCell``` which should be extended from ```BaseCell``` and its data will be binded to a view instance created by ```ViewHolderCreator ```. The view creator inflates the view from ```R.layout.item_holder``` and binds it to the ```TestViewHolder``` instance. -The most common way to regiser custom cell is the former two. As to developping a custom cell, please read [document]() here. +We recommend to use string as type to register component. +The most common way to regiser custom cell is the former two. As to developping a custom cell, please read [document](http://tangram.pingguohe.net/docs/android/develop-component) here. ## 5.Create ```TangramEngine``` instance diff --git a/examples/src/main/assets/data.json b/examples/src/main/assets/data.json index 24df57d..a4f1fd9 100644 --- a/examples/src/main/assets/data.json +++ b/examples/src/main/assets/data.json @@ -1,6 +1,11 @@ [ { - "type": "container-oneColumn", + "type": "container-scroll", + "style": { + "pageWidth": 200, + "hGap": 100, + "pageHeight": 100 + }, "items": [ { "imgUrl": "https://gw.alicdn.com/tfs/TB1vqF.PpXXXXaRaXXXXXXXXXXX-110-72.png", @@ -77,12 +82,12 @@ }, "items": [ { - "bizId":"item1", + "bizId": "item1", "type": 110, "msg": "info1" }, { - "bizId":"item2", + "bizId": "item2", "type": 110, "msg": "info2" } @@ -106,37 +111,37 @@ }, "items": [ { - "type": 1, + "type": "testView", "msg": "info1", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info2", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info3", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info4", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info5", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info6", "style": { } @@ -165,37 +170,37 @@ }, "items": [ { - "type": 1, + "type": "testView", "msg": "info1", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info2", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info3", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info4", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info5", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info6", "style": { } @@ -226,37 +231,37 @@ }, "items": [ { - "type": 1, + "type": "testView", "msg": "info1", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info2", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info3", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info4", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info5", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info6", "style": { } @@ -270,41 +275,62 @@ "style": { "hGap": "15", "vGap": "15", - "margin": [null, null, null, null], - "padding": ["15", "15", "15", "15"] + "margin": [ + null, + null, + null, + null + ], + "padding": [ + "15", + "15", + "15", + "15" + ] }, "type": 25, - "items": [{ - "title": "A", - "type": 199 - }, { - "title": "B", - "type": 199 - }, { - "title": "C", - "type": 199 - }, { - "title": "D", - "type": 199 - }, { - "title": "E", - "type": 199 - }, { - "title": "F", - "type": 199 - }, { - "title": "G", - "type": 199 - }, { - "title": "H", - "type": 199 - }, { - "title": "I", - "type": 199 - }, { - "title": "G", - "type": 199 - }] + "items": [ + { + "title": "A", + "type": 199 + }, + { + "title": "B", + "type": 199 + }, + { + "title": "C", + "type": 199 + }, + { + "title": "D", + "type": 199 + }, + { + "title": "E", + "type": 199 + }, + { + "title": "F", + "type": 199 + }, + { + "title": "G", + "type": 199 + }, + { + "title": "H", + "type": 199 + }, + { + "title": "I", + "type": 199 + }, + { + "title": "G", + "type": 199 + } + ] }, { "type": 1, @@ -313,11 +339,11 @@ }, "items": [ { - "type": 10, + "type": "singleImgView", "imgUrl": "https://gw.alicdn.com/tfs/TB1pdJFQpXXXXbUXpXXXXXXXXXX-750-243.png" }, { - "type": 10, + "type": "singleImgView", "imgUrl": "https://gw.alicdn.com/tfs/TB1pdJFQpXXXXbUXpXXXXXXXXXX-750-243.png" } ] @@ -326,15 +352,12 @@ "type": 20, "style": { "sticky": "start" - }, "items": [ { - "type": 1, + "type": "testView", "msg": "sticky", "style": { - "height": 80 - } } ] @@ -357,37 +380,37 @@ }, "items": [ { - "type": 1, + "type": "testView", "msg": "info11", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info12", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info13", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info14", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info15", "style": { } }, { - "type": 1, + "type": "testView", "msg": "info16", "style": { } @@ -450,16 +473,16 @@ }, "items": [ { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" } ] }, @@ -467,20 +490,20 @@ "type": "3", "items": [ { - "type": 1, + "type": "testView", "msg": "block", "style": { "display": "block" } }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" } ] }, @@ -488,16 +511,16 @@ "type": 4, "items": [ { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" } ] }, @@ -509,7 +532,7 @@ }, "items": [ { - "type": 1, + "type": "testView", "style": { "height": 120 }, @@ -522,7 +545,7 @@ "id": "dividerShow", "items": [ { - "type": 1, + "type": "testView", "msg": "I am a divider" } ] @@ -537,16 +560,16 @@ }, "items": [ { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" } ] }, @@ -559,7 +582,7 @@ }, "items": [ { - "type": 1, + "type": "testView", "style": { "margin": [ 4, @@ -570,7 +593,7 @@ } }, { - "type": 1, + "type": "testView", "style": { "margin": [ 0, @@ -581,7 +604,7 @@ } }, { - "type": 1 + "type": "testView" } ] }, @@ -591,10 +614,10 @@ }, "items": [ { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" } ] }, @@ -602,7 +625,7 @@ "type": "1", "items": [ { - "type": 1 + "type": "testView" } ] }, @@ -631,40 +654,40 @@ }, "items": [ { - "type": 1, + "type": "testView", "style": { "colspan": 2 } }, { - "type": 1, + "type": "testView", "style": { "colspan": 2 } }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" }, { - "type": 1 + "type": "testView" } ] }, diff --git a/examples/src/main/assets/data_third.json b/examples/src/main/assets/data_third.json index 6c850fa..3e4ea77 100644 --- a/examples/src/main/assets/data_third.json +++ b/examples/src/main/assets/data_third.json @@ -17,22 +17,22 @@ { "subTitle": "测试内容10jm", "title": "测试内容7774", - "type": 1 + "type": "testView" }, { "subTitle": "测试内容10jm", "title": "测试内容7774", - "type": 1 + "type": "testView" }, { "subTitle": "测试内容10jm", "title": "测试内容7774", - "type": 1 + "type": "testView" }, { "subTitle": "测试内容10jm", "title": "测试内容7774", - "type": 1 + "type": "testView" } ], "type": 2000 diff --git a/examples/src/main/java/com/tmall/wireless/tangram/example/TangramActivity.java b/examples/src/main/java/com/tmall/wireless/tangram/example/TangramActivity.java index 7d3951c..db063b0 100644 --- a/examples/src/main/java/com/tmall/wireless/tangram/example/TangramActivity.java +++ b/examples/src/main/java/com/tmall/wireless/tangram/example/TangramActivity.java @@ -65,6 +65,7 @@ import com.tmall.wireless.tangram.example.data.TestViewHolder; import com.tmall.wireless.tangram.example.data.TestViewHolderCell; import com.tmall.wireless.tangram.example.data.VVTEST; import com.tmall.wireless.tangram.example.support.SampleClickSupport; +import com.tmall.wireless.tangram.example.support.SampleScrollSupport; import com.tmall.wireless.tangram.structure.BaseCell; import com.tmall.wireless.tangram.structure.viewcreator.ViewHolderCreator; import com.tmall.wireless.tangram.support.async.AsyncLoader; @@ -152,6 +153,12 @@ public class TangramActivity extends Activity { builder = TangramBuilder.newInnerBuilder(this); //Step 3: register business cells and cards + // recommend to use string type to register component + builder.registerCell("testView", TestView.class); + builder.registerCell("singleImgView", SimpleImgView.class); + builder.registerCell("ratioTextView", RatioTextView.class); + + // register component with integer type was not recommend to use builder.registerCell(1, TestView.class); builder.registerCell(10, SimpleImgView.class); builder.registerCell(2, SimpleImgView.class); @@ -298,6 +305,9 @@ public class TangramActivity extends Activity { } catch (JSONException e) { e.printStackTrace(); } + + //Demo for component to listen container's event + engine.register(SampleScrollSupport.class, new SampleScrollSupport(recyclerView)); } @Override diff --git a/examples/src/main/java/com/tmall/wireless/tangram/example/data/TestView.java b/examples/src/main/java/com/tmall/wireless/tangram/example/data/TestView.java index d9c1a66..ce0c6c0 100644 --- a/examples/src/main/java/com/tmall/wireless/tangram/example/data/TestView.java +++ b/examples/src/main/java/com/tmall/wireless/tangram/example/data/TestView.java @@ -25,11 +25,14 @@ package com.tmall.wireless.tangram.example.data; import android.content.Context; +import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; +import android.util.Log; import android.widget.FrameLayout; import android.widget.TextView; import com.tmall.wireless.tangram.example.R; +import com.tmall.wireless.tangram.example.support.SampleScrollSupport; import com.tmall.wireless.tangram.structure.BaseCell; import com.tmall.wireless.tangram.structure.CellRender; import com.tmall.wireless.tangram.structure.view.ITangramViewLifeCycle; @@ -37,7 +40,7 @@ import com.tmall.wireless.tangram.structure.view.ITangramViewLifeCycle; /** * Created by villadora on 15/8/24. */ -public class TestView extends FrameLayout implements ITangramViewLifeCycle { +public class TestView extends FrameLayout implements ITangramViewLifeCycle, SampleScrollSupport.IScrollListener { private TextView textView; private BaseCell cell; @@ -56,7 +59,7 @@ public class TestView extends FrameLayout implements ITangramViewLifeCycle { init(); } - private void init(){ + private void init() { inflate(getContext(), R.layout.item, this); textView = (TextView) findViewById(R.id.title); } @@ -65,6 +68,10 @@ public class TestView extends FrameLayout implements ITangramViewLifeCycle { public void cellInited(BaseCell cell) { setOnClickListener(cell); this.cell = cell; + if (cell.serviceManager != null) { + SampleScrollSupport scrollSupport = cell.serviceManager.getService(SampleScrollSupport.class); + scrollSupport.register(this); + } } @Override @@ -90,4 +97,14 @@ public class TestView extends FrameLayout implements ITangramViewLifeCycle { @Override public void postUnBindView(BaseCell cell) { } + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + Log.i("TestView", "onScrollStateChanged: "); + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + Log.i("TestView", "onScrolled: "); + } } diff --git a/examples/src/main/java/com/tmall/wireless/tangram/example/support/SampleScrollSupport.java b/examples/src/main/java/com/tmall/wireless/tangram/example/support/SampleScrollSupport.java new file mode 100644 index 0000000..3d8508e --- /dev/null +++ b/examples/src/main/java/com/tmall/wireless/tangram/example/support/SampleScrollSupport.java @@ -0,0 +1,44 @@ +package com.tmall.wireless.tangram.example.support; + +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.OnScrollListener; + +import java.util.ArrayList; +import java.util.List; + +public class SampleScrollSupport { + public interface IScrollListener { + public void onScrollStateChanged(RecyclerView recyclerView, int newState); + + public void onScrolled(RecyclerView recyclerView, int dx, int dy); + } + + private RecyclerView recyclerView; + + private List scrollListeners = new ArrayList<>(); + + public SampleScrollSupport(RecyclerView recyclerView) { + this.recyclerView = recyclerView; + recyclerView.addOnScrollListener(new OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + for (IScrollListener listener : scrollListeners) { + listener.onScrollStateChanged(recyclerView, newState); + } + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + for (IScrollListener listener : scrollListeners) { + listener.onScrolled(recyclerView, dx, dy); + } + } + }); + } + + public void register(IScrollListener scrollListener) { + if (!scrollListeners.contains(scrollListener)) { + scrollListeners.add(scrollListener); + } + } +} diff --git a/examples/src/main/res/values/strings.xml b/examples/src/main/res/values/strings.xml index d79d0bb..9f91e7b 100644 --- a/examples/src/main/res/values/strings.xml +++ b/examples/src/main/res/values/strings.xml @@ -23,5 +23,5 @@ --> - Example for Tangram + Tangram diff --git a/gradle.properties b/gradle.properties index 2ba1ea7..c24879c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -46,7 +46,7 @@ org.gradle.jvmargs=-Xmx1536M GROUP=com.alibaba.android ARTIFACT=tangram VERSION=1 -VERSION_NAME=3.0.2 +VERSION_NAME=3.1.4.1 PACKAGING_TYPE=aar systemProp.compileSdkVersion=25 systemProp.targetSdkVersion=25 diff --git a/tangram/build.gradle b/tangram/build.gradle index 6625dd1..d9d673d 100644 --- a/tangram/build.gradle +++ b/tangram/build.gradle @@ -117,7 +117,7 @@ dependencies { exclude group: 'com.android.support', module: 'support-annotations' } } else { - compile('com.alibaba.android:vlayout:1.2.14@aar') { + compile('com.alibaba.android:vlayout:1.2.17@aar') { changing = true } } diff --git a/tangram/src/main/java/com/tmall/wireless/tangram/MVHelper.java b/tangram/src/main/java/com/tmall/wireless/tangram/MVHelper.java index 19418b9..56d2e2c 100644 --- a/tangram/src/main/java/com/tmall/wireless/tangram/MVHelper.java +++ b/tangram/src/main/java/com/tmall/wireless/tangram/MVHelper.java @@ -68,7 +68,6 @@ public class MVHelper { private ArrayMap postBindMap = new ArrayMap<>(128); private ArrayMap postUnBindMap = new ArrayMap<>(128); private ArrayMap cellInitedMap = new ArrayMap<>(128); - private ArrayMap cellFlareIdMap = new ArrayMap<>(128); public MVHelper(MVResolver mvResolver) { this.mvResolver = mvResolver; @@ -98,7 +97,6 @@ public class MVHelper { postBindMap.clear(); postUnBindMap.clear(); cellInitedMap.clear(); - cellFlareIdMap.clear(); mvResolver.reset(); } @@ -114,7 +112,7 @@ public class MVHelper { public void mountView(BaseCell cell, View view) { try { - mvResolver.register(getCellUniqueId(cell), cell, view); + mvResolver.register(cell, view); if (cell.serviceManager != null) { if (cell.serviceManager.supportRx()) { cell.emitNext(BDE.BIND); @@ -160,15 +158,6 @@ public class MVHelper { } } - public String getCellUniqueId(BaseCell cell) { - String flareId = cellFlareIdMap.get(cell); - if (flareId == null) { - flareId = String.format("%s_%s", cell.parent == null ? "null" : cell.parent.id, cell.pos); - cellFlareIdMap.put(cell, flareId); - } - return flareId; - } - public void unMountView(BaseCell cell, View view) { if (view instanceof IContainer) { ViewBase vb = ((IContainer)view).getVirtualView(); diff --git a/tangram/src/main/java/com/tmall/wireless/tangram/MVResolver.java b/tangram/src/main/java/com/tmall/wireless/tangram/MVResolver.java index 1c07790..997dde1 100644 --- a/tangram/src/main/java/com/tmall/wireless/tangram/MVResolver.java +++ b/tangram/src/main/java/com/tmall/wireless/tangram/MVResolver.java @@ -39,6 +39,7 @@ import com.tmall.wireless.tangram.util.Utils; import org.json.JSONException; import org.json.JSONObject; +import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -67,15 +68,12 @@ public class MVResolver { private ArrayMap> typeCellMap = new ArrayMap(64); - private ArrayMap idCardMap = new ArrayMap<>(); + private HashMap idCardMap = new HashMap<>(); private ArrayMap mvMap = new ArrayMap<>(128); private ArrayMap vmMap = new ArrayMap<>(128); - @Deprecated - private ArrayMap idViewMap = new ArrayMap<>(128); - private ServiceManager mServiceManager; public void setServiceManager(ServiceManager serviceManager) { @@ -98,29 +96,30 @@ public class MVResolver { return typeCellMap.get(type); } - public void register(String cellId, BaseCell cell, View view) { + public void register(BaseCell cell, View view) { mvMap.put(cell, view); vmMap.put(view, cell); - - idViewMap.put(cellId, view); } public void setCards(List list) { - for (Card card : list) { - if (!TextUtils.isEmpty(card.id)) { - idCardMap.put(card.id, card); + synchronized (idCardMap) { + for (Card card : list) { + if (!TextUtils.isEmpty(card.id)) { + idCardMap.put(card.id, card); + } } } } public Card findCardById(String id) { - return idCardMap.get(id); + synchronized (idCardMap) { + return idCardMap.get(id); + } } public void reset() { mvMap.clear(); vmMap.clear(); - idViewMap.clear(); } public View getView(BaseCell cell) { @@ -129,7 +128,7 @@ public class MVResolver { @Deprecated public View getView(String uniqueId) { - return idViewMap.get(uniqueId); + return null; } public BaseCell getCell(View view) { diff --git a/tangram/src/main/java/com/tmall/wireless/tangram/TangramEngine.java b/tangram/src/main/java/com/tmall/wireless/tangram/TangramEngine.java index 21f0900..23bcb0a 100644 --- a/tangram/src/main/java/com/tmall/wireless/tangram/TangramEngine.java +++ b/tangram/src/main/java/com/tmall/wireless/tangram/TangramEngine.java @@ -41,6 +41,7 @@ import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.util.Pair; import android.view.View; + import com.tmall.wireless.tangram.dataparser.DataParser; import com.tmall.wireless.tangram.dataparser.IAdapterBuilder; import com.tmall.wireless.tangram.dataparser.concrete.Card; @@ -66,14 +67,16 @@ import com.tmall.wireless.tangram.support.SimpleClickSupport; import com.tmall.wireless.tangram.support.async.CardLoadSupport; import com.tmall.wireless.tangram.util.Predicate; import com.tmall.wireless.vaf.virtualview.core.ViewCache; + import io.reactivex.functions.Consumer; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; /** * Created by villadora on 15/8/24. - * + *

* The core of Tangram used to access data, bind view, register service. */ public class TangramEngine extends BaseTangramEngine implements Engine { @@ -81,8 +84,8 @@ public class TangramEngine extends BaseTangramEngine dataParser, - @NonNull IAdapterBuilder adapterBuilder) { + @NonNull DataParser dataParser, + @NonNull IAdapterBuilder adapterBuilder) { super(context, dataParser, adapterBuilder); this.register(DataParser.class, dataParser); } @@ -124,7 +127,7 @@ public class TangramEngine extends BaseTangramEngine list) { @@ -598,7 +609,7 @@ public class TangramEngine extends BaseTangramEngine groups) { @@ -639,6 +650,7 @@ public class TangramEngine extends BaseTangramEngine currVersion) { + TemplateInfo templateInfo = new TemplateInfo(); + templateInfo.setType(cellType); + templateInfo.setBinary(templateInfoJson.optString(TemplateInfo.KEY_TEMPLATE_BINARY_BASE64)); + templateInfo.setVersion(newVersion); + + templateUpdateSupport.onUpdate(templateInfo); + } + } + } + if (componentBinderResolver.has(cellType)) { cell = new BaseCell(cellType); cell.serviceManager = serviceManager; @@ -390,7 +415,7 @@ public abstract class Card extends ComponentLifecycle { */ private LayoutHelper mLayoutHelper = null; - public LayoutHelper getExistLayoutHelper(){ + public LayoutHelper getExistLayoutHelper() { return mLayoutHelper; } @@ -475,9 +500,9 @@ public abstract class Card extends ComponentLifecycle { if (helper instanceof MarginLayoutHelper) { ((MarginLayoutHelper) helper).setMargin(style.margin[Style.MARGIN_LEFT_INDEX], style.margin[Style.MARGIN_TOP_INDEX], - style.margin[Style.MARGIN_RIGHT_INDEX], style.margin[Style.MARGIN_BOTTOM_INDEX]); + style.margin[Style.MARGIN_RIGHT_INDEX], style.margin[Style.MARGIN_BOTTOM_INDEX]); ((MarginLayoutHelper) helper).setPadding(style.padding[Style.MARGIN_LEFT_INDEX], style.padding[Style.MARGIN_TOP_INDEX], - style.padding[Style.MARGIN_RIGHT_INDEX], style.padding[Style.MARGIN_BOTTOM_INDEX]); + style.padding[Style.MARGIN_RIGHT_INDEX], style.padding[Style.MARGIN_BOTTOM_INDEX]); } } @@ -820,7 +845,7 @@ public abstract class Card extends ComponentLifecycle { if (TangramBuilder.isPrintLog()) { if (mPendingCells.size() > 0 && mInQueueCells.size() > 0) { Preconditions.checkState(mPendingCells.get(0).position >= mInQueueCells.get(mInQueueCells.size() - 1).position - , "Items in pendingQueue must have large position than Items in queue"); + , "Items in pendingQueue must have large position than Items in queue"); } } } @@ -954,7 +979,7 @@ public abstract class Card extends ComponentLifecycle { public boolean requirePlaceholderCell() { return mPlaceholderRequired && mPlaceholderCell != null && !TextUtils.isEmpty(load) - && (mCells.size() == 0 || (mCells.size() == 1 && mCells.contains(mPlaceholderCell))); + && (mCells.size() == 0 || (mCells.size() == 1 && mCells.contains(mPlaceholderCell))); } private MVHelper getMVHelper() { @@ -1038,7 +1063,7 @@ public abstract class Card extends ComponentLifecycle { return null; } - public ArrayMap, Card> getChildrenCards(){ + public ArrayMap, Card> getChildrenCards() { return mChildren; } diff --git a/tangram/src/main/java/com/tmall/wireless/tangram/structure/TemplateInfo.java b/tangram/src/main/java/com/tmall/wireless/tangram/structure/TemplateInfo.java new file mode 100644 index 0000000..95ccb4b --- /dev/null +++ b/tangram/src/main/java/com/tmall/wireless/tangram/structure/TemplateInfo.java @@ -0,0 +1,65 @@ +/* + * MIT License + * + * Copyright (c) 2018 Alibaba Group + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.tmall.wireless.tangram.structure; + +import android.util.Base64; + +public class TemplateInfo { + public static final String KEY_TEMPLATE_INFO = "templateInfo"; + + public static final String KEY_TEMPLATE_BINARY_BASE64 = "binary"; + + public static final String KEY_TEMPLATE_VERSION = "version"; + + private String type; + + private byte[] binary; + + private int version; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public byte[] getBinary() { + return binary; + } + + public int getVersion() { + return version; + } + + public void setVersion(int version) { + this.version = version; + } + + public void setBinary(String binary) { + this.binary = Base64.decode(binary, Base64.DEFAULT); + } +} diff --git a/tangram/src/main/java/com/tmall/wireless/tangram/structure/card/LinearScrollCard.java b/tangram/src/main/java/com/tmall/wireless/tangram/structure/card/LinearScrollCard.java index 2087c67..8d67625 100644 --- a/tangram/src/main/java/com/tmall/wireless/tangram/structure/card/LinearScrollCard.java +++ b/tangram/src/main/java/com/tmall/wireless/tangram/structure/card/LinearScrollCard.java @@ -133,6 +133,7 @@ public class LinearScrollCard extends Card { cell.retainScrollState = data.optBoolean(LinearScrollCell.KEY_RETAIN_SCROLL_STATE, true); cell.scrollMarginLeft = Style.parseSize(data.optString(LinearScrollCell.KEY_SCROLL_MARGIN_LEFT), 0); cell.scrollMarginRight = Style.parseSize(data.optString(LinearScrollCell.KEY_SCROLL_MARGIN_RIGHT), 0); + cell.hGap = data.optDouble(LinearScrollCell.KEY_HGAP, 0); } } diff --git a/tangram/src/main/java/com/tmall/wireless/tangram/structure/cell/LinearScrollCell.java b/tangram/src/main/java/com/tmall/wireless/tangram/structure/cell/LinearScrollCell.java index 3351124..5b63c26 100644 --- a/tangram/src/main/java/com/tmall/wireless/tangram/structure/cell/LinearScrollCell.java +++ b/tangram/src/main/java/com/tmall/wireless/tangram/structure/cell/LinearScrollCell.java @@ -28,6 +28,7 @@ import android.graphics.Color; import android.support.v7.widget.RecyclerView; import android.view.ViewGroup; +import com.tmall.wireless.tangram.core.R; import com.tmall.wireless.tangram.core.adapter.BinderViewHolder; import com.tmall.wireless.tangram.core.adapter.GroupBasicAdapter; import com.tmall.wireless.tangram.dataparser.concrete.Style; @@ -66,6 +67,8 @@ public class LinearScrollCell extends BaseCell { public static final int DEFAULT_DEFAULT_INDICATOR_COLOR = Color.parseColor("#80ffffff"); public static final int DEFAULT_INDICATOR_COLOR = Color.parseColor("#ffffff"); + public static final String KEY_HGAP = "hGap"; + public List cells = new ArrayList(); public BaseCell mHeader; @@ -81,6 +84,7 @@ public class LinearScrollCell extends BaseCell { public int bgColor = Color.TRANSPARENT; public int scrollMarginLeft; public int scrollMarginRight; + public double hGap; // current distance that responding recycler view has scrolled. public int currentDistance = 0; @@ -149,6 +153,7 @@ public class LinearScrollCell extends BaseCell { lp.width = Style.parseSize(cell.extras.optString("pageWidth"), 0); } binderViewHolder.itemView.setLayoutParams(lp); + binderViewHolder.itemView.setTag(R.id.TANGRAM_LINEAR_SCROLL_POS, position); } @Override diff --git a/tangram/src/main/java/com/tmall/wireless/tangram/support/TemplateUpdateSupport.java b/tangram/src/main/java/com/tmall/wireless/tangram/support/TemplateUpdateSupport.java new file mode 100644 index 0000000..d199c0c --- /dev/null +++ b/tangram/src/main/java/com/tmall/wireless/tangram/support/TemplateUpdateSupport.java @@ -0,0 +1,9 @@ +package com.tmall.wireless.tangram.support; + +import com.tmall.wireless.tangram.structure.TemplateInfo; + +public class TemplateUpdateSupport { + public void onUpdate(TemplateInfo templateInfo) { + + } +} diff --git a/tangram/src/main/java/com/tmall/wireless/tangram/view/LinearScrollView.java b/tangram/src/main/java/com/tmall/wireless/tangram/view/LinearScrollView.java index 954fe3d..c9a019d 100644 --- a/tangram/src/main/java/com/tmall/wireless/tangram/view/LinearScrollView.java +++ b/tangram/src/main/java/com/tmall/wireless/tangram/view/LinearScrollView.java @@ -30,6 +30,7 @@ import java.util.List; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; +import android.graphics.Rect; import android.graphics.drawable.GradientDrawable; import android.support.annotation.NonNull; import android.support.v4.util.ArrayMap; @@ -78,6 +79,8 @@ public class LinearScrollView extends LinearLayout implements ITangramViewLifeCy private List mViewHolders = new ArrayList(); + private RecyclerView.ItemDecoration itemDecoration; + private RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { @@ -184,6 +187,29 @@ public class LinearScrollView extends LinearLayout implements ITangramViewLifeCy recyclerView.setRecycledViewPool(lSCell.getRecycledViewPool()); + recyclerView.removeItemDecoration(itemDecoration); + if (lSCell.hGap > 0) { + itemDecoration = new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + outRect.set(0, 0, 0, 0); + + int viewIndex = (int) view.getTag(R.id.TANGRAM_LINEAR_SCROLL_POS); + if (viewIndex == lSCell.cells.size() - 1) { + // last view only set left + outRect.left = (int) (lSCell.hGap / 2); + } else if (viewIndex == 0) { + // first view only set right + outRect.right = (int) (lSCell.hGap / 2); + } else { + outRect.left = (int) (lSCell.hGap / 2); + outRect.right = (int) (lSCell.hGap / 2); + } + } + }; + recyclerView.addItemDecoration(itemDecoration); + } + float[] starts = null; if (lSCell.cells != null && lSCell.cells.size() > 0) { starts = new float[lSCell.cells.size()]; @@ -333,7 +359,7 @@ public class LinearScrollView extends LinearLayout implements ITangramViewLifeCy header.setId(R.id.TANGRAM_BANNER_HEADER_ID); //为了解决在 item 复用过程中,itemView 的 layoutParams 复用造成 layout 错误,这里要提供一个新的 layoutParams。 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT); + ViewGroup.LayoutParams.WRAP_CONTENT); lp.topMargin = cell.style.margin[Style.MARGIN_TOP_INDEX]; lp.leftMargin = cell.style.margin[Style.MARGIN_LEFT_INDEX]; lp.bottomMargin = cell.style.margin[Style.MARGIN_BOTTOM_INDEX]; @@ -350,7 +376,7 @@ public class LinearScrollView extends LinearLayout implements ITangramViewLifeCy footer.setId(R.id.TANGRAM_BANNER_FOOTER_ID); //为了解决在 item 复用过程中,itemView 的 layoutParams 复用造成 layout 错误,这里要提供一个新的 layoutParams。 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT); + ViewGroup.LayoutParams.WRAP_CONTENT); lp.topMargin = cell.style.margin[Style.MARGIN_TOP_INDEX]; lp.leftMargin = cell.style.margin[Style.MARGIN_LEFT_INDEX]; lp.bottomMargin = cell.style.margin[Style.MARGIN_BOTTOM_INDEX]; diff --git a/tangram/src/main/res/values/ids.xml b/tangram/src/main/res/values/ids.xml index a7d7351..4cfba25 100644 --- a/tangram/src/main/res/values/ids.xml +++ b/tangram/src/main/res/values/ids.xml @@ -31,4 +31,5 @@ + \ No newline at end of file