Merge branch 'feature/opt_parsing' into develop

This commit is contained in:
longerian
2018-09-20 15:35:36 +08:00
22 changed files with 405 additions and 158 deletions
+4
View File
@@ -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)。
# 特点
+4
View File
@@ -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
+3 -2
View File
@@ -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```实例
+3 -2
View File
@@ -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
+123 -100
View File
@@ -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"
}
]
},
+4 -4
View File
@@ -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
@@ -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
@@ -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: ");
}
}
@@ -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<IScrollListener> 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);
}
}
}
+1 -1
View File
@@ -23,5 +23,5 @@
-->
<resources>
<string name="app_name">Example for Tangram</string>
<string name="app_name">Tangram</string>
</resources>
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
}
}
@@ -68,7 +68,6 @@ public class MVHelper {
private ArrayMap<BaseCell, Method> postBindMap = new ArrayMap<>(128);
private ArrayMap<BaseCell, Method> postUnBindMap = new ArrayMap<>(128);
private ArrayMap<BaseCell, Method> cellInitedMap = new ArrayMap<>(128);
private ArrayMap<BaseCell, String> 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();
@@ -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<String, Class<? extends BaseCell>> typeCellMap = new ArrayMap(64);
private ArrayMap<String, Card> idCardMap = new ArrayMap<>();
private HashMap<String, Card> idCardMap = new HashMap<>();
private ArrayMap<BaseCell, View> mvMap = new ArrayMap<>(128);
private ArrayMap<View, BaseCell> vmMap = new ArrayMap<>(128);
@Deprecated
private ArrayMap<String, View> 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<Card> 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) {
@@ -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.
*
* <p>
* The core of Tangram used to access data, bind view, register service.
*/
public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card, BaseCell> implements Engine {
@@ -81,8 +84,8 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
private static final int NO_SWIPE = -1;
public TangramEngine(@NonNull Context context,
@NonNull DataParser<JSONObject, JSONArray, Card, BaseCell> dataParser,
@NonNull IAdapterBuilder<Card, BaseCell> adapterBuilder) {
@NonNull DataParser<JSONObject, JSONArray, Card, BaseCell> dataParser,
@NonNull IAdapterBuilder<Card, BaseCell> adapterBuilder) {
super(context, dataParser, adapterBuilder);
this.register(DataParser.class, dataParser);
}
@@ -124,7 +127,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
}
view.addOnItemTouchListener(mSwipeItemTouchListener);
view.setOnScrollListener(new RecyclerView.OnScrollListener(){
view.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
@@ -145,6 +148,14 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
getLayoutManager().setNoScrolling(noScrolling);
}
public void setCanScrollVertically(boolean canScrollVertically) {
getLayoutManager().setCanScrollVertically(canScrollVertically);
}
public void setCanScrollHorizontally(boolean canScrollHorizontally) {
getLayoutManager().setCanScrollHorizontally(canScrollHorizontally);
}
public void setEnableOverlapMargin(boolean enable) {
getLayoutManager().setEnableMarginOverlapping(enable);
}
@@ -261,7 +272,6 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
}
/**
*
* @param enable True to auto trigger loading data for card whose's position in within 0 to {{@link #mPreLoadNumber}}.
*/
public void setEnableLoadFirstPageCard(boolean enable) {
@@ -328,7 +338,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
@Override
public boolean isMatch(Card data) {
return data.loadMore && data.hasMore && !data.loading
&& !TextUtils.isEmpty(data.load);
&& !TextUtils.isEmpty(data.load);
}
});
@@ -351,7 +361,6 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
}
/**
*
* @param id Target cell's id. Can not be null
* @return
* @since 3.0.0
@@ -551,8 +560,9 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* A high performance method to insert cells. TODO handle nested card
*
* @param insertPosition the position to be inserted.
* @param data new cell data
* @param data new cell data
* @since 2.1.0
*/
public void insertWith(int insertPosition, BaseCell data) {
@@ -562,8 +572,9 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* A high performance method to insert cells. Do not allowed to insert to an empty Tangram. TODO handle nested card
*
* @param insertPosition the position to be inserted
* @param list new cell data list
* @param list new cell data list
* @since 2.1.0
*/
public void insertWith(int insertPosition, List<BaseCell> list) {
@@ -598,7 +609,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* @param insertIdx the index to be inserted
* @param group a group of data
* @param group a group of data
* @since 2.1.0
*/
public void insertBatchWith(int insertIdx, Card group) {
@@ -607,7 +618,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* @param insertIdx the index to be inserted
* @param groups a group list
* @param groups a group list
* @since 2.1.0
*/
public void insertBatchWith(int insertIdx, List<Card> groups) {
@@ -639,6 +650,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* NOTE new API, use this to replace {@link BaseTangramEngine#appendData(List)} and {@link BaseTangramEngine#appendData(Object)}
*
* @param groups new groups to be append at tail.
* @since 2.1.0
*/
@@ -650,6 +662,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* Remove cell at target position. TODO handle nested card
*
* @param position
* @since 2.1.0
*/
@@ -664,6 +677,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* Remove target cell. TODO handle nested card, cell in staggered, cell in onePlusN
*
* @param data
* @since 2.1.0
*/
@@ -709,6 +723,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* Remove all cells in a card with target index
*
* @param removeIdx target card's index
* @since 2.1.0
*/
@@ -723,6 +738,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* Remove all cells in a card.
*
* @param group
* @since 2.1.0
*/
@@ -759,6 +775,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* Replace cell one by one.
*
* @param oldOne
* @param newOne
* @since 2.1.0
@@ -778,6 +795,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* Replace parent card's children. Cells' size should be equal with parent's children size.
*
* @param parent
* @param cells
* @since 2.1.0
@@ -818,6 +836,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* Replace card one by one. New one's children size should be equal with old one's children size.
*
* @param oldOne
* @param newOne
* @since 2.1.0
@@ -844,6 +863,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* Update a view's UI by its cell's data, you should change cell's data first.
*
* @param cell
* @since 3.0.0
*/
@@ -912,6 +932,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* Make engine as a consumer to accept data to append at the end of list
*
* @return
* @since 3.0.0
*/
@@ -926,6 +947,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* Make engine as a consumer to accept data to append at the end of list
*
* @return
* @since 3.0.0
*/
@@ -1024,6 +1046,7 @@ public class TangramEngine extends BaseTangramEngine<JSONObject, JSONArray, Card
/**
* Make engine as a consumer to accept cell'data change
*
* @return
* @since 3.0.0
*/
@@ -31,15 +31,18 @@ import com.alibaba.android.vlayout.layout.FixAreaLayoutHelper;
import com.alibaba.android.vlayout.layout.MarginLayoutHelper;
import android.support.v4.util.ArrayMap;
import com.tmall.wireless.tangram.Engine;
import com.tmall.wireless.tangram.MVHelper;
import com.tmall.wireless.tangram.TangramBuilder;
import com.tmall.wireless.tangram.core.service.ServiceManager;
import com.tmall.wireless.tangram.structure.BaseCell;
import com.tmall.wireless.tangram.structure.TemplateInfo;
import com.tmall.wireless.tangram.structure.card.BannerCard;
import com.tmall.wireless.tangram.structure.card.LinearScrollCard;
import com.tmall.wireless.tangram.support.CardSupport;
import com.tmall.wireless.tangram.support.ExposureSupport;
import com.tmall.wireless.tangram.support.TemplateUpdateSupport;
import com.tmall.wireless.tangram.util.ImageUtils;
import com.tmall.wireless.tangram.util.LogUtils;
import com.tmall.wireless.tangram.util.Preconditions;
@@ -271,7 +274,7 @@ public abstract class Card extends ComponentLifecycle {
}
public static BaseCell createCell(@Nullable Card parent, @NonNull MVHelper resolver, @NonNull JSONObject cellData,
@NonNull ServiceManager serviceManager, boolean appended) {
@NonNull ServiceManager serviceManager, boolean appended) {
if (cellData != null) {
BaseCell cell = null;
String cellType = cellData.optString(Card.KEY_TYPE);
@@ -347,6 +350,28 @@ public abstract class Card extends ComponentLifecycle {
} else {
//support virtual view at layout
BaseCellBinderResolver componentBinderResolver = serviceManager.getService(BaseCellBinderResolver.class);
//if exist template need update, just do it
TemplateUpdateSupport templateUpdateSupport = serviceManager.getService(TemplateUpdateSupport.class);
if (templateUpdateSupport != null) {
if (cellData.has(TemplateInfo.KEY_TEMPLATE_INFO)) {
JSONObject templateInfoJson = cellData.optJSONObject(TemplateInfo.KEY_TEMPLATE_INFO);
MVHelper mvHelper = serviceManager.getService(MVHelper.class);
int currVersion = mvHelper.getVafContext().getViewManager().getViewVersion(cellType);
int newVersion = templateInfoJson.optInt(TemplateInfo.KEY_TEMPLATE_VERSION);
if (newVersion > 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<Range<Integer>, Card> getChildrenCards(){
public ArrayMap<Range<Integer>, Card> getChildrenCards() {
return mChildren;
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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<BaseCell> cells = new ArrayList<BaseCell>();
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
@@ -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) {
}
}
@@ -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<BinderViewHolder> mViewHolders = new ArrayList<BinderViewHolder>();
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];
+1
View File
@@ -31,4 +31,5 @@
<item name="TANGRAM_BANNER_FOOTER_ID" type="id" />
<item name="tk_banner" type="id" />
<item name="TANGRAM_BANNER_INDICATOR_POS" type="id"/>
<item name="TANGRAM_LINEAR_SCROLL_POS" type="id"/>
</resources>