今天我们拆解一下专车的意见反馈,涉及到TextWatcher监听、特殊字符过滤Pattern等知识点和hideInputMethod收键盘、setEnabled按钮使能、shape圆角矩形、maxLength最大长度、hint默认提示、String.format优化效率等细节,如图是我们开发时的标注图,聚焦到每一像素,对UI敏感,练就一双火眼金睛···
现在我们一一拆解这些细节和知识点,绝不仅仅是输入提交看上去这么简单。
交互层面
1.通过TextWatcher监听,
1.1在onTextChanged中处理,无内容时按钮置灰,有内容时按钮高亮;
1.2在afterTextChanged中处理,提示用户还可输入的字数;
2.在onClick中处理点击事件,点击提交按钮后,进行下一步操作:
2.1通过正则和String API过滤特殊字符,防止注入攻击;
2.2将意见通过网络传回后台;
2.2.1如果网络请求成功
Toast提示“提交成功”--》通过系统服务InputMethodManager收键盘--》finish()关闭当前页面,回到上一页面
2.2.2如果网络请求失败
Toast提示“提交失败”--》保留键盘并停在当前页面
视觉层面
UI设计师专业把控+前端工程师经验直觉,从整体到局部,一个个像素、一个个样式的推敲。
拆解输入框,不仅仅是一个输入框。
如图,最外层一个圆角矩形样式,垂直分布的LinearLayout,里面包着一个EditText输入框和一个TextView动态显示字数。
安全层面
通过Pattern进行特殊字符过滤,防止注入攻击做好安全防范。
Coding实战
1.通过TextWatcher监听,为EditText输入框添加监听事件。
mContentEt.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
1.1在onTextChanged中处理,无内容时按钮置灰,有内容时按钮高亮;
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (TextUtils.isEmpty(mContentEt.getText().toString())) {
mCommitTv.setEnabled(false);
} else {
mCommitTv.setEnabled(true);
}
}
1.2在afterTextChanged中处理,提示用户还可输入的字数;
1.3在afterTextChanged中处理,字数到达上限后进行拦截并给出提示。
@Override
public void afterTextChanged(Editable s) {
int length = mContentEt.getText().length();
if (length > MAXNUM) {
Toast.makeText(mContext, getString(R.string.input_feedback_content_long), Toast.LENGTH_SHORT).show();
String text = mContentEt.getText().toString()
.substring(0, MAXNUM - 1);
mContentEt.setText(text);
length = MAXNUM;
}
int left = MAXNUM - length;
mWatchWordsTv.setText(String.format(getResources().getString(R.string.default_feedback_words), Integer.toString(left)));
}
2.在onClick中处理点击事件,点击提交按钮后,进行下一步操作:
@Override
public void onClick(View v) {
super.onClick(v);
switch (v.getId()) {
case R.id.commit_tv_feedback:
~~~
default:
break;
}
}
2.1通过正则和String API过滤特殊字符,防止注入攻击;
/**
* 过滤特殊字符
*/
public static String stringFilter(String str) {
if (TextUtils.isEmpty(str)) {
return "";
}
String regEx = "[<>'\"]";
str = str.replaceAll(" ", "").replaceAll("&", "")
.replaceAll("#160;", "").replaceAll("<", "")
.replaceAll(">", "").replaceAll(""", "")
.replaceAll("<", "").replaceAll(">", "")
.replaceAll("&", "").replaceAll(""", "");
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(str);
return m.replaceAll("").trim();
}
2.2将意见通过网络传回后台;
以后专门拿一篇文章讲Volley,在这不做实现。
2.2.1如果网络请求成功
Toast提示“提交成功”--》通过系统服务InputMethodManager收键盘--》finish()关闭当前页面,回到上一页面
Toast.makeText(mContext, getString(R.string.feedback_success), Toast.LENGTH_SHORT).show();
hideInputMethod();
finish();
/**
* 隐藏软键盘
*/
public void hideInputMethod() {
InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null && this.getCurrentFocus() != null) {
imm.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0);
}
}
2.2.2如果网络请求失败
Toast提示“提交失败”--》保留键盘并停在当前页面
至此,主流程拆解完毕。
关于shape圆角矩形、maxLength最大长度、hint默认提示、String.format优化效率等细节可以参考源码,在此不一一展开了。
最后效果如图,画面有点不流畅,大家最好自己动手试试哈。
原创不易,转载请注明出处哈。
权兴权意
产品可以更优雅~
项目源代码,欢迎提建议(Star和Fork)。
项目实战:优雅的实现专车意见反馈 · HXQWill/QuanStudy@f489374 https://github.com/HXQWill/QuanStudy/commit/f489374d0e3f7ad3e0b9b2831f63ab96bec9d7ea