WeexAndroid扩展组件Spinner(对应前端select标签)

WeexAndroid扩展组件Spinner(对应前端select标签)

作为一名Android开发者,在使用weex编写项目的过程中,业务需要实现一个下拉框的组件,于是动手写了个。
Android扩展的组件Spinner在weex上的效果

  • Android扩展之Component 扩展
  • Android扩展组件的步骤
  • Js如何调用Android扩展组件
  • Android扩展组件如何传参到Js

Android的Component 扩展要点

  • 要点复制官方的,给第一次看Component 扩展的同行。
  • Component 扩展类必须继承 WXComponent.
  • Component 对应的设置属性的方法必须添加注解@WXComponentProp(name=value)
  • Component 扩展的方法可以使用 int, double, float, String, Map, List 类型的参数
  • 完成 Component 后一定要在初始化时注册 WXSDKEngine.registerComponent(“js调用时的名字”,自定义的组件.class);

咱们先定它个小目标,比如说写一个自定义组件

在Android Studio的项目中新建一个类继承自WXComponent,实现其中四个参数的构造函数。

public class WXSpinnerTest extends WXComponent<Spinner> {

    public WXSpinnerTest(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, boolean isLazy) {
        super(instance, dom, parent, isLazy);
    }
}

private定义一个Spinner控件,实现初始化组件主视图方法。

private Spinner spinner;
 @Override
    protected Spinner initComponentHostView(@NonNull Context context) {
        spinner = new Spinner(context);
        return spinner;
    }

实现Js设置属性的方法必须添加注解,在公司实际项目中需要通过type查询出数据,而这里作为演示故没有做处理。

 @WXComponentProp(name = "type")
    public void initSpinner(String type){
        //这里的type实际项目当中查询数据库时必要的参数,所以预留出来
        list = new ArrayList<>();//list要在外部声明 private List<String> list
        for (int i=0;i<10;i++){
            list.add("霍比特人"+i);
        }
        ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), R.layout.row_spn, list);
        adapter.setDropDownViewResource(R.layout.row_spn_dropdown);
        spinner.setAdapter(adapter);
    }

    public List<String> getList() {
        List<String> list = new ArrayList<>();
        for (int i=0;i<10;i++){
            list.add("霍比特人"+i);
        }
        return list;
    }
//adapter所用到的:row_spn.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/row_spn_tv"
    android:layout_width="wrap_content"
    android:layout_height="32dp"
    android:gravity="center_vertical"
    android:background="?selectableItemBackground"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:textDirection="locale"
    android:textSize="16sp"/>

//adapter所用到的:row_spn_dropdown.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/row_spn_tv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:drawableTop="@mipmap/recycler_line"
    android:drawablePadding="10dp"
    android:textSize="16sp"
    android:drawableBottom="@mipmap/recycler_line"
    android:textDirection="locale"/>

到这里算基本完成Spinner组件的自定义(后面会写数据如何回显及Android事件传递到Js),接着需要在Application中注册扩展的组件关于Application步骤不懂的看别人的吧

   InitConfig config = new InitConfig.Builder()
                .setImgAdapter(new ImageAdapter())
                .setHttpAdapter(new OkgoAdapter())
                .setJSExceptionAdapter(new JSExceptionAdapter())
//                .setUtAdapter(new UserTrackAdapter())
                .build();
        WXSDKEngine.initialize(this, config);
        //注册模块和组件
        try {
            WXSDKEngine.registerComponent("wxspinnertest", WXSpinnerTest.class);

        } catch (WXException e) {
            e.printStackTrace();
        }

Js调用Android扩展的组件

关于weex项目的初始化
(偷懒)随便打开一个能最快被android项目打开的文件,直接输入我们在Application里定义的wxspinnertest。

<template>
  <div class="app">
    <div class="div-top-link">
    </div>
    <div class="style_div">
      <text class="label_text">魔戒</text>
      <wxspinnertest class="value_text mobile" :type="type"></wxspinnertest>
    </div>
  </div>
  </div>
</template>
<script>

export default {
  name: 'app',
  data () {
    return {
      type:1
    }
  }
}
</script>
<style>
  .div-top-link {
    width: 750px;
    height: 128px;
    flex-direction: row;
    justify-content: space-between;
    background-color: #456ea6;
    align-items: center;
    padding-left: 20px;
    padding-right: 20px;
  }
 .style_div{
        background-color: #ffffff;
        height: 70px;
        flex-direction: row;
        justify-content: center;
        align-items:center;
        border-bottom-width: 1px;
        border-bottom-color: #f2f2f2;
        border-bottom-style: solid;
        font-size: 50px;   
        margin-top: 20px;    
        margin-bottom: 20px;   
        padding-top: 20px;
        padding-bottom: 20px;
        padding-right: 20px;
    }
    .label_text{
      width: 187px;
      color: #333;
      font-size: 34px;
      height: 70px;
      line-height: 70px;
    }
     .value_text{
       width: 460px;
       height: 70px;
       line-height: 70px;
       color: #333;
       font-size: 34px;

    }


</style>

效果
这一步算是基本完成了简单的Spinner下拉选择,实际项目中不光有名字,还有已选择的Value等数据实体。那么问题来了,如何把Android选择的内容返回到Js当中呢?
这里写图片描述

Android扩展的组件如何传参到Js

我们需要看一下继承的WXComponent类中关于事件传递,其中发现了fireEvent方法适合我们,方法内调用的是WXSDKInstance.fireEvent,而内部又调用WXBridgeManager.getInstance().fireEventOnNode方法,在此方法里边调用addJSEventTask方法,里边使用WXHashMap把我们想要传递的参数封装到KEY_ARGS(args)中。
如果以上没看懂的可以去看看内部如何调用,这里不做过多解释,回到我们初衷,如何实现Android扩展组件Spinner选择的数据回传到Js当中。
重点内容: 在Android扩展组件Spinner类的initSpinner方法中实现监听事件并调用fireEvent方法

spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
                Map<String, Object> resp = new HashMap();
                resp.put("data", list.get(position));
                fireEvent("refresh",resp);
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });

划重点: put的是Key是’data’, fireEvent的是”refresh”
在Vue文件中,绑定refresh的监听事件,事件回调AndroidWeex源码内封装的KEY_ARGS(args),具体如下:
1、在template模板spinnertest标签中增加事件refresh

 <wxspinnertest class="value_text" :type="type" @refresh="onrefresh"></wxspinnertest>

2、在script脚本实现onrefresh事件,并增加回调的args。

  const modal = weex.requireModule('modal')
  export default {
    name: 'app',
    data () {
      return {
        type:1
      }
    },
    methods:{
      onrefresh(args){
        modal.toast({
          message: '选择的魔戒是'+args.data,
          duration: 0.3
        })
      },
    }
  }

事件回调效果

Vue文件如何让扩展组件Spinner显示指定的值

一般情况下,有新增就会有详情修改,那么我们只实现了新增的情况,而实际项目中,获取的详情譬如:魔戒为霍比特人4,要如何处理呢?
我们需要再增加个扩展方法用于回显:
1、Android扩展组件Spinner文件中增加扩展方法value,贴下最终Spinner类全部代码

public class WXSpinnerTest extends WXComponent<Spinner> {

    private Spinner spinner;
    private List<String> list;
    public WXSpinnerTest(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, boolean isLazy) {
        super(instance, dom, parent, isLazy);
    }

    @Override
    protected Spinner initComponentHostView(@NonNull Context context) {
        spinner = new Spinner(context);
        return spinner;
    }

    @WXComponentProp(name = "type")
    public void initSpinner(String type){
        //这里的type实际项目当中查询数据库时必要的参数,所以预留出来
        list = new ArrayList<>();
        for (int i=0;i<10;i++){
            list.add("霍比特人"+i);
        }
        ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), R.layout.row_spn, list);
        adapter.setDropDownViewResource(R.layout.row_spn_dropdown);
        spinner.setAdapter(adapter);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
                Map<String, Object> resp = new HashMap();
                    resp.put("data", list.get(position));
                fireEvent("refresh",resp);
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });
    }

    @WXComponentProp(name = "value")
    public void onSpinnerValue(int value){
        spinner.setSelection(value);//这里直接传入的是下标
    }

}

2、Vue文件Script的data中增加个value,值为4,
template的wxspinnertest标签增加绑定value,贴下全部代码。

<template>
  <div class="app">
    <div class="div-top-link">
    </div>
    <div class="style_div">
      <text class="label_text">魔戒</text>
      <wxspinnertest class="value_text" :type="type" :value="value" @refresh="onrefresh"></wxspinnertest>
    </div>
  </div>
  </div>
</template>
<script>

  const modal = weex.requireModule('modal')
  export default {
    name: 'app',
    data () {
      return {
        type:1,
        value:4
      }
    },
    methods:{
      onrefresh(args){
        modal.toast({
          message: '选择的魔戒是'+args.data,
          duration: 0.3
        })
      }
    }
  }
</script>
<style>
  .div-top-link {
    width: 750px;
    height: 128px;
    flex-direction: row;
    justify-content: space-between;
    background-color: #456ea6;
    align-items: center;
    padding-left: 20px;
    padding-right: 20px;
  }
 .style_div{
        background-color: #ffffff;
        height: 70px;
        flex-direction: row;
        justify-content: center;
        align-items:center;
        border-bottom-width: 1px;
        border-bottom-color: #f2f2f2;
        border-bottom-style: solid;
        font-size: 50px;   
        margin-top: 20px;    
        margin-bottom: 20px;   
        padding-top: 20px;
        padding-bottom: 20px;
        padding-right: 20px;
    }
    .label_text{
      width: 187px;
      color: #333;
      font-size: 34px;
      height: 70px;
      line-height: 70px;
    }
     .value_text{
       width: 460px;
       height: 70px;
       line-height: 70px;
       color: #333;
       font-size: 34px;

    }


</style>

详情回显固定为霍比特人4

结语

自此,Android扩展组件Spinner的实现过程已经介绍完毕,因个人技术有限,在实现过程中可能存在并不是很好的处理方式,如事件传递,下拉框位置固定等,在Vue文件中需要将原生扩展的组件进行再次封装,以减少不必要的style等。另一方面IOS及Web如何配合实现并没有了解,还望多多指正,共同学习成长。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值