Android Form组件

场景

Android APP里面时常有于登陆、注册、信息填写提交等页面,业务逻辑差很少都是用户输入或者选择某些信息,而后点击提交,客户端这边依次判断用户名是否为空,长度是否在某个范围内等等,若是某一个不符合要求,就提示相应信息,若是都符合,就组合成key=value形式发起请求。php

引伸

上述场景相似于HTML里面的form标签html

<form action="form_action.asp" method="get">
  <p>First name: <input type="text" name="fname" /></p>
  <p>Last name: <input type="text" name="lname" /></p>
  <input type="submit" value="Submit" />
</form>
复制代码

在Android里面,登陆、注册这些页面是否也像一个个form呢,咱们可否也用一个配置文件配置请求的URL,请求方式,而后配置相关的控件,最后在点击提交按钮时自动组装?java

再引伸一步,登陆页面里面,咱们须要判断用户名为空、长度、匹配规则等,密码为空、长度、匹配规则等,而后分别给提示。在信息填写页面就更多了,有可能须要用户输入好几十条的信息分别判断,这样就致使了代码冗余和重复。可否在配置里面就配置好相应的检查规则,在点击提交的时候自动依次检查?android

答案是能够的~下面就来看看例子git

示例布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="20dp">
    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" >
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/chose_sex" />
        <RadioGroup android:id="@+id/rg_sex" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" >
            <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/sex_male" />
            <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/sex_female" />
        </RadioGroup>
    </LinearLayout>
    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" android:layout_marginTop="10dp" >
        <ImageView android:layout_width="25dp" android:layout_height="25dp" android:src="@mipmap/user" />
        <EditText android:id="@+id/et_user" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/et_name_hint" android:layout_marginLeft="10dp" android:inputType="number" />
    </LinearLayout>
    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" android:layout_marginTop="10dp" >
        <ImageView android:layout_width="25dp" android:layout_height="25dp" android:src="@mipmap/password" />
        <EditText android:id="@+id/et_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/et_password_hint" android:layout_marginLeft="10dp" android:inputType="textPassword" />
    </LinearLayout>
    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" android:layout_marginTop="10dp" >
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/protocol_num" />
        <com.kongge.formlikedemo.view.DIYView android:id="@+id/diy_view" android:layout_width="match_parent" android:layout_height="30dp" android:layout_marginLeft="10dp" />
    </LinearLayout>
    <Button android:id="@+id/btn_login" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/login_btn_bg" android:text="@string/btn_login" android:layout_marginTop="10dp" />
</LinearLayout>
复制代码

为了简单快捷,都是用的LinearLayout,这样影响性能,这里当一个反面教材吧。。。json

常规写法

  1. 先findByID,获取所有的控件。
  2. 按钮设置监听。
  3. 按钮点击以后依次判断:性别是否选择?没有就提示;帐号是否为空?长度是不是11位?没有分别弹提示;密码是否为空?长度是否大于6?长度是否小于16?没有分别弹提示;协议编号是否为空?是否都是字母?没有弹提示。
  4. 若是还有其余信息,依次增长一样的逻辑。

封装以后

json配置
{
  "action":"https://www.xxx.com",
  "method":"post",
  "item":[
    {
      "id":"rg_sex",
      "rules":{
        "notNull":[true, "性别不能为空"]
      },
      "paramName":"sex"
    },
    {
      "id":"et_user",
      "rules":{
        "notNull":[true, "帐号不能为空"],
        "length":[11, "帐号长度必须是11位"]
      },
      "paramName":"userName"
    },
    {
      "id":"et_password",
      "rules":{
        "notNull":[true, "密码不能为空"],
        "minLength":[6, "密码最短为6位"],
        "maxLength":[16, "密码最长为16位"]
      },
      "paramName":"userPwd"
    },
    {
      "id":"diy_view",
      "rules":{
        "notNull":[true, "协议编号不能为空"],
        "textMatch":["[a-zA-Z]+", "协议编号须要所有为字母"]
      },
      "paramName":"protocol"
    },
    {
      "id":"btn_login",
      "type":"submit"
    }
  ]
}
复制代码

action:提交的URLbash

method:提交的方式ide

item:Form里面的控件,好比选择按钮、文本框和提交按钮等。布局

id:控件定义的id,使用反射获取控件。post

rules:检测规则,好比不为空、长度检查等。点击提交时会按照里面配置的规则依次检查。

paramName:点击提交时,对应的key。value就是控件里面的内容。

type表明控件类型,无此字段时,则默认须要获取该控件内容上传,若是为“submit”,则表示是个提交按钮,当点击该按钮时,会逐个检查其余字段是否匹配规则,若是都经过了,则会组装所有参数返回。

程序代码
// 自定义View,里面绘制了文字
        DIYView diyView = findViewById(R.id.diy_view);
        diyView.setText("abxcSDDFsdcAd");

        // 自定义规则,名称是“textmatch”,类名是RuleTextMatch.java
        Form.addRule("textMatch", RuleTextMatch.class);
        // 自定义检查的View,用于检查DIYView等其余View的输入,可经过instanceof判断类型以后获取相应内容
        Form.setCheckView(DIYCheckView.class);

        String jsonStr = FileUtil.parseAssetsFile(this, "config/testConfig01.json");
        Form form = new Form();
        form.parseView(view, jsonStr);
        form.setFormCommitListener(new OnFormCommitListener() {
            @Override
            public void onFormCommitChecked(Form form, String method, String url, Map<String, String> paramMap) {
                Toast.makeText(MainActivity.this, "method=" + method + "\nurl=" + url + "\n" + "paramMap=" + paramMap.toString(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onFormCommitError(Form form, ICheckItem checkItem, IRule errorRule) {
                Toast.makeText(MainActivity.this, errorRule.getErrorMsg(), Toast.LENGTH_SHORT).show();
            }
        });
复制代码
说明

因为json配置文件里面写明了id,因此库里面就自动findViewByID了,外部调用省去了该过程。rules写明了判断规则,第一个参数是条件,第二个参数默认是未符合的状况下的提示,固然,这个在实现了IRule接口以后能够本身定义参数的顺序和含义。rules里面的顺序决定了程序判断的顺序。

扩展

扩展规则

例如扩展一个正则匹配的规则,名称是“textMatch”。

  1. 新建一个类RuleTextMatch继承AbsRule,或者实现IRule接口。
public class RuleTextMatch extends AbsRule {

    private String matchFormatStr = null;
    @Override
    public void setParam(List<Object> paramList) {
        super.setParam(paramList);
        if (paramList != null && paramList.size() > 0) {
            Object item = paramList.get(0);
            if (item instanceof String) {
                matchFormatStr = (String) item;
            }
        }
    }

    @Override
    public boolean check(ICheckItem checkItem) {
        if (TextUtils.isEmpty(matchFormatStr)) {
            return true;
        }
        String content = checkItem.getCheckContent();
        if (content == null) {
            return false;
        }
        Pattern pattern = Pattern.compile(matchFormatStr);
        Matcher matcher = pattern.matcher(content);
        return matcher.matches();
    }
}
复制代码
  1. 注册该规则
//在程序启动的时候就能够注册了,使用Form的静态方法addRule
Form.addRule("textMatch", RuleTextMatch.class);
复制代码
  1. json配置
{
      "id":"diy_view",
      "rules":{
        "notNull":[true, "协议编号不能为空"],
        "textMatch":["[a-zA-Z]+", "协议编号须要所有为字母"]
      },
      "paramName":"protocol"
    }
复制代码
扩展View

目前阶段只支持RadioGroup和TextView(EditText, Button等继承了TextView),若是想扩展其余的View,只须要建立一个类继承CheckView或者实现ICheckItem接口便可。 例如咱们自定义了一个DIYView。

  1. DIYView
public class DIYView extends View {
    // ...省略其余方法
    private String text;
    public String getText() {
        return text;
    }
    // ...省略其余方法
}
复制代码
  1. 须要扩展一个类DIYCheckView,来解析DIYView和其余扩展的View。整个外部扩展解析类只须要这一个就能够了。
public class DIYCheckView extends CheckView {

    @Override
    public String getCheckContent() {
        String content = super.getCheckContent();
        if (content != null) {
            return content;
        }
        // 经过instanceof判断各个类型View的获取文本的方法。
        if (view instanceof DIYView) {
            return ((DIYView) view).getText();
        }
        return content;
    }
}
复制代码
  1. 使用
// 在程序启动时,调用Form的静态方法setCheckView就能够了
Form.setCheckView(DIYCheckView.class);
复制代码

小结

  1. 文中的输入信息的就三四个,可能以为本身写也挺快。可是若是须要用户填写详细信息好几十条的时候,每一个都要判断一些乱七八糟的规则,这个就轻松多了。
  2. 因为加载的是配置文件,也就是说该文件是能够随时更新的,当某一个规则发生变化的时候能够及时更新,例如本地判断了用户名11位,后来需求更改不限制位数了,只须要更新配置文件便可。
  3. 因为是一个aar库,不用每次去编译,扩展的时候也不须要修改库里面的文件。

现阶段处于起始阶段,支持的规则和判断的View比较少,后续会增长,连接以下,但愿你们不腻赐教,谢谢!

git连接:FormLike

相关文章
相关标签/搜索