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

相關文章
相關標籤/搜索