Android | Tangram动态页面之路(三)使用

赤发鬼
• 阅读 1699

本系列文章主要介绍天猫团队开源的Tangram框架的使用心得和原理,由于Tangram底层基于vlayout,所以也会简单讲解,该系列将按以下大纲进行介绍:

  1. 需求背景
  2. Tangram和vlayout介绍
  3. Tangram的使用
  4. vlayout原理
  5. Tangram原理
  6. Tangram二次封装

本文将对Tangram的简单使用进行介绍。

Demo代码

基础使用

引入依赖:

    //tangram相关:tangram使用3.0之前的最新版本,其他直接使用最新版本
    implementation 'com.alibaba.android:tangram:2.2.5@aar'
    //tangram底层支持:vlayout
    implementation 'com.alibaba.android:vlayout:1.2.36@aar'
    //tangram虚拟视图(更灵活的视图,后面单独开篇讲)
    implementation('com.alibaba.android:virtualview:1.4.6@aar') {
        transitive true
    }
    //tangram支持banner翻页用的
    implementation 'com.alibaba.android:ultraviewpager:1.0.7.8@aar'
    //tangram内部需要rxjava
    implementation 'io.reactivex.rxjava2:rxjava:2.1.12'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'

初始化,主要是传递上下文进去,和设置图片加载能力,这里我们使用Glide

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        TangramBuilder.init(this, new IInnerImageSetter() {
            @Override
            public <IMAGE extends ImageView> void doLoadImageUrl(@NonNull IMAGE view, @Nullable String url) {
                Glide.with(view.getContext()).load(url).
                        error(R.mipmap.ic_launcher).
                        into(view);
            }
        }, NetImageView.class);
    }
}

在activity中使用,

//MainActivity.java
void onCreate(Bundle savedInstanceState) {
    //创建builder来配置参数
    TangramBuilder.InnerBuilder builder = TangramBuilder.newInnerBuilder(this);
    //注册自己的cell
    builder.registerCell(ImageTextView.class.getSimpleName(), ImageTextView.class);
    builder.registerCell(SingleImageView.class.getSimpleName(), SingleImageView.class);

    //创建引擎
    mEngine = builder.build();
    //绑定RecyclerView
    mEngine.bindView(mBinding.rvList);

    mBinding.rvList.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            //在 scroll 事件中触发 engine 的 onScroll,内部会触发需要异步加载的卡片去提前加载数据
            mEngine.onScrolled();
        }
    });

    //设置数据,触发渲染
    String file = FileUtil.getAssertsFile(this, "main.json");
    try {
        mEngine.setData(new JSONArray(file));
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

前边的介绍篇提到过,Tangram内置了一些布局方式Card,基本满足需求了,所以我们只需定制自己的具体View也就是Cell即可,上边手动注册了两个CellImageTextViewSingleImageView,我们先来看ImageTextView,他是一个LinearLayout,上边一个图标,下边一个文本,需要实现ITangramViewLifeCycle接口,在相应的回调里执行自己的逻辑,

public class ImageTextView extends LinearLayout implements ITangramViewLifeCycle {
    private NetImageView mImgIcon;
    private TextView mTvTitle;

    public ImageTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setOrientation(VERTICAL);
        setGravity(Gravity.CENTER);
        inflate(getContext(), R.layout.cell_image_text, this);
        mImgIcon = findViewById(R.id.img_icon);
        mTvTitle = findViewById(R.id.tv_title);
    }

    @Override
    public void cellInited(BaseCell cell) {
    }

    @Override
    public void postBindView(BaseCell cell) {
        mImgIcon.load(cell.optStringParam("imgUrl"));
        mTvTitle.setText(cell.optStringParam("title"));
    }

    @Override
    public void postUnBindView(BaseCell cell) {
    }
}

其布局文件cell_image_text.xml如下,

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <com.holiday.tangram.view.NetImageView
        android:id="@+id/img_icon"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:scaleType="centerCrop"
        tools:background="@color/colorAccent" />

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:ellipsize="end"
        android:maxLines="1"
        tools:text="@string/app_name" />
</merge>

Cell都准备好了,下面就是准备json模板了,先来一个四列布局container-fourColumn

{
    "type": "container-fourColumn",
    "items": [
        {
            "imgUrl": "https://tva1.sinaimg.cn/large/007S8ZIlgy1geqp9zhftrj303r03r3yl.jpg",
            "title": "标题1",
            "type": "ImageTextView"
        },
        {
            "imgUrl": "https://tva1.sinaimg.cn/large/007S8ZIlgy1geqp9zhftrj303r03r3yl.jpg",
            "title": "标题2",
            "type": "ImageTextView"
        },
        {
            "imgUrl": "https://tva1.sinaimg.cn/large/007S8ZIlgy1geqp9zhftrj303r03r3yl.jpg",
            "title": "标题3",
            "type": "ImageTextView"
        },
        {
            "imgUrl": "https://tva1.sinaimg.cn/large/007S8ZIlgy1geqp9zhftrj303r03r3yl.jpg",
            "title": "标题4",
            "type": "ImageTextView"
        }
    ]
}

运行如下,

Android | Tangram动态页面之路(三)使用

下面再来看另一个自定义CellSingleImageView很简单,就是单图,

public class SingleImageView extends NetImageView implements ITangramViewLifeCycle {

    public SingleImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setScaleType(ScaleType.CENTER_CROP);
    }

    @Override
    public void cellInited(BaseCell cell) {
    }

    @Override
    public void postBindView(BaseCell cell) {
        load(cell.optStringParam("imgUrl"));
    }

    @Override
    public void postUnBindView(BaseCell cell) {
    }
}

然后来一个1拖n布局container-onePlusN

{
    "type": "container-onePlusN",
    "style": {
        "aspectRatio": "1.778",
        "margin": "[10,0,0,0]"
    },
    "items": [
        {
            "imgUrl": "https://wanandroid.com/blogimgs/942a5c62-ca87-4e7c-a93d-41ff59a15ba4.png",
            "type": "SingleImageView"
        },
        {
            "imgUrl": "https://www.wanandroid.com/blogimgs/62c1bd68-b5f3-4a3c-a649-7ca8c7dfabe6.png",
            "type": "SingleImageView"
        },
        {
            "imgUrl": "https://www.wanandroid.com/blogimgs/50c115c2-cf6c-4802-aa7b-a4334de444cd.png",
            "type": "SingleImageView"
        },
        {
            "imgUrl": "https://www.wanandroid.com/blogimgs/90c6cc12-742e-4c9f-b318-b912f163b8d0.png",
            "type": "SingleImageView"
        }
    ]
}

图片取自玩安卓的banner图,运行如下,

Android | Tangram动态页面之路(三)使用

因为有4条数据,所以展示的效果就是1拖3。

然后再来个轮播图布局container-banner,他的Cell还是使用单图SingleImageView

{
    "type": "container-banner",
    "style": {
        "margin": "[0,0,10,0]",
        "pageWidth": 200,
        "pageHeight": 100,
        "indicatorMargin": "5",
        "infinite": "true",
        "indicatorImg2": "https://img.alicdn.com/tps/TB1XRNFNXXXXXXKXXXXXXXXXXXX-32-4.png",
        "indicatorImg1": "https://img.alicdn.com/tps/TB16i4qNXXXXXbBXFXXXXXXXXXX-32-4.png",
        "scrollMarginLeft": "10",
        "indicatorGap": "2",
        "indicatorHeight": "1.5",
        "itemRatio": "2.654",
        "scrollMarginRight": "10",
        "indicatorGravity": "center",
        "hGap": "20"
    },
    "items": [
        {
            "imgUrl": "https://wanandroid.com/blogimgs/942a5c62-ca87-4e7c-a93d-41ff59a15ba4.png",
            "type": "SingleImageView"
        },
        {
            "imgUrl": "https://www.wanandroid.com/blogimgs/62c1bd68-b5f3-4a3c-a649-7ca8c7dfabe6.png",
            "type": "SingleImageView"
        },
        {
            "imgUrl": "https://www.wanandroid.com/blogimgs/50c115c2-cf6c-4802-aa7b-a4334de444cd.png",
            "type": "SingleImageView"
        },
        {
            "imgUrl": "https://www.wanandroid.com/blogimgs/90c6cc12-742e-4c9f-b318-b912f163b8d0.png",
            "type": "SingleImageView"
        }
    ]
}

可以看出可供配置的参数还是很多的,文档可以看这里,运行如下,

Android | Tangram动态页面之路(三)使用

整体效果如下,

Android | Tangram动态页面之路(三)使用

Android | Tangram动态页面之路(三)使用

内置support支持

Tangram内置了一些support支持,如处理点击SimpleClickSupport,卡片数据加载CardLoadSupport,曝光逻辑ExposureSupport等,可以通过TangramEngineadd方法注册,如下,

//MainActivity.java
mEngine.addSimpleClickSupport(new MyClickSupport());

然后看MyClickSupport

public class MyClickSupport extends SimpleClickSupport {
    public MyClickSupport() {
        setOptimizedMode(true);
    }

    @Override
    public void defaultClick(View targetView, BaseCell cell, int eventType) {
        super.defaultClick(targetView, cell, eventType);
        QrToast.show(cell.stringType);
    }
}

我们可以在自己的Cell里对view设置点击事件,也可以把点击事件交给support全局处理,如果要使用support处理点击事件,需要在Cell里加这行代码,

//SingleImageView.java
@Override
public void cellInited(BaseCell cell) {
    setOnClickListener(cell);
}

比如商城首页,大多数模块都是点击进行页面跳转,行为比较单一,不需要每个Cell都去做点击事件,SimpleClickSupport就能很好的支持,在defaultClick里取出页面短链进行跳转即可,如,

public class MyClickSupport extends SimpleClickSupport {
    public MyClickSupport() {
        setOptimizedMode(true);
    }

    @Override
    public void defaultClick(View targetView, BaseCell cell, int eventType) {
        super.defaultClick(targetView, cell, eventType);
        //取出页面短链,进行跳转。短链既可以是h5的,也可以是native的,由Router内部处理
        PageRouter.to(cell.optStringParam("link"));
    }
}

用起来很简单有木有!好啦,Tangram的使用就介绍到这里了,后面会分析原理,实现模板和数据分离等等,敬请期待~

Android | Tangram动态页面之路(三)使用

参考文章

Android | Tangram动态页面之路(三)使用

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
美凌格栋栋酱 美凌格栋栋酱
10个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
双十一预售活动分析
2022年双十一促销活动已经开始,大家应该都提前开始关注今年双十一活动的时间表了吧?2022年10月24日晚8:00天猫双11预售时间,第一波销售时间10月31日晚8:0,第二波销售时间11月10日晚8:00;天猫双11的优惠力度是跨店每满30050
东方客主 东方客主
4年前
Android输入法遮挡了输入框,使用android:fitsSystemWindows="true"后界面顶部出现白条
问题1、页面布局文件:<LinearLayoutxmlns:android"http://schemas.android.com/apk/res/android"android:id"@id/layoutorderdetail"android:layoutwidth"matchparent"android:layoutheigh
xxkfz xxkfz
4年前
Android期末项目(超详细附下载链接)
【第一部分】历史文章:【第二部分】主要问题解决:【第三部分】期末项目:Android期末大作业——今日头条一、主要的功能介绍|模块|主要功能|相关描述||||||登录、注册页面|Lite
Stella981 Stella981
4年前
Native层HIDL服务的获取原理
摘要:本节主要来讲解Android10.0Native层HIDL服务的获取原理阅读本文大约需要花费23分钟。文章首发微信公众号:IngresGe专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!\Android取经之路\的源码都基于AndroidQ(10.0)进
Wesley13 Wesley13
4年前
03.Android崩溃Crash库之ExceptionHandler分析
目录总结00.异常处理几个常用api01.UncaughtExceptionHandler02.Java线程处理异常分析03.Android中线程处理异常分析04.为何使用setDefaultUncaughtExceptionHandler前沿上一篇整体介绍了crash崩溃
Easter79 Easter79
4年前
SpringMvc接受特殊符号参数被转义
WEB开发时,在前端通过get/post方法传递参数的时候 如果实参附带特殊符号,后端接收到的值中特殊符号就会被转义例如该请求: http://localhost:10001/demo/index.do?name张三(1)注:中文()不会出现此种情况后台就收到的实际name值为:  张三&40;1&41;&40;其实为h
Wesley13 Wesley13
4年前
Unity横屏
Android下发现Unity里面的Player设置,并不能完全有效,比如打开了自动旋转,启动的时候还是会横屏,修改XML添加以下代码<applicationandroid:icon"@drawable/ic\_launcher"                    android:label"@string/app\_name"
Wesley13 Wesley13
4年前
MYSQL表的类型 静态表 动态表 压缩表
mysql在创建表的时候定义表的性质,共有三种:静态表,动态表,压缩表。默认是静态表,如果存在varchar、blob、text字段,表类型就是动态了。1.静态表:字段有固定长度,例如:char(20)。如果使用gbk字符集存储中文username,将占用40byte,如果username的实际内容没有达到40byte,将会填充空格,
Stella981 Stella981
4年前
SkyWalking系列(一):初探
SkyWalking已经再微服务商城系列里使用了,本篇将介绍如何再Windows系统下安装并简单使用。1.下载SkyWaling本篇测试使用6.0版本:http://skywalking.apache.org/downloads/!(https://oscimg.oschina.net/oscnet/ff6b065db4f6fd40db64c