关于Android的必填项,包括登陆、注册等,因为Edittext比较少,所以大多数人选择gettext然后一一判空,但是如果Edittext比较多的时候,就比较繁琐了。考虑到优化方案有二:1、重写Edittext,然后利用注册,在保存时判定每个Edittext;二、考虑到所有的数据最后都会保存成一个类,所以不管Edittext,保存之前只判断自定义类。本文主要阐述第一种方式,优点是不需要反射,耗时短。
首先,我们看效果图:

实现方法:用单例模式建立注册器,支持动态注册,注册方式有xml,view以及自定义的Edittext,考虑到多Activity的操作与复用,Edittext集合采用CopyOnWriterArrayList,全局集合采用ConcurrentHashMap。最后解绑的时候只需要在基类Activity的onDestroy方法中进行UNRegister即可,非常的方便。
最后,前端Activity的代码:
public class CustomEditActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_edittext);
}
public void onCheck(View view){
EditTextUtil.getInstance().checkEmpty(this);
}
@Override
protected void onDestroy() {
EditTextUtil.getInstance().unRegister(this);
super.onDestroy();
}
}
与其对应的xml文件:
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<java.wen.com.view.EmptyEditText
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="用户名"
app:toast_text="请输入用户名"
app:necessary="true"/>
<java.wen.com.view.EmptyEditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="密码"
app:toast_text="请输入用户密码"
app:necessary="true"/>
<java.wen.com.view.EmptyEditText
android:id="@+id/code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="邀请码"
app:toast_text="请输入用户邀请码"/>
<Button
android:id="@+id/btn_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="检查必填项"
android:onClick="onCheck"/>
</LinearLayout>
自定义的EditText,支持xml中配置必填项与提示:
public class EmptyEditText extends EditText {
private boolean necessary = false;
private String toastString = "";
public EmptyEditText(Context context) {
super(context);
}
public EmptyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init(context,attrs);
}
public EmptyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context,attrs);
}
private void init(Context context, @Nullable AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.EmptyEditText);
if(null != ta) {
toastString = ta.getString(R.styleable.EmptyEditText_toast_text);
necessary = ta.getBoolean(R.styleable.EmptyEditText_necessary,false);
ta.recycle();
}
}
public boolean checkEmpty(){
return checkEmpty(false);
}
public boolean checkEmpty(boolean toast){
if(necessary) {
Object value = getText();
if (null == value || TextUtils.isEmpty(value.toString().trim())) {
if (toast && !TextUtils.isEmpty(toastString)) {
Toast.makeText(getContext(), toastString, Toast.LENGTH_SHORT).show();
}
return true;
}
}
return false;
}
}
最后就是单例模式的注册器,懒加载的模式:
public class EditTextUtil {
static volatile EditTextUtil defaultInstance;
private static ConcurrentHashMap<Context,CopyOnWriteArrayList<EmptyEditText>> textMap = new ConcurrentHashMap<>();
public static EditTextUtil getInstance(){
if(defaultInstance == null)
defaultInstance = new EditTextUtil();
return defaultInstance;
}
public void register(Context context,int xml){
View view = LayoutInflater.from(context).inflate(xml,null);
register(context,view);
}
public void register(Context context, View view){
List<EmptyEditText> textList = getChildEdit(view);
register(context,textList);
}
public void register(Context context, List<EmptyEditText> textList){
CopyOnWriteArrayList<EmptyEditText> editList = new CopyOnWriteArrayList<>();
editList.addAll(textList);
textMap.put(context, editList);
}
public void register(Context context, EmptyEditText textList){
CopyOnWriteArrayList<EmptyEditText> editList = null;
if(textMap.containsKey(context)){
editList= textMap.get(context);
}
if(null == editList){
editList = new CopyOnWriteArrayList<>();
}
editList.add(textList);
textMap.put(context, editList);
}
private List<EmptyEditText> getChildEdit(View view){
List<EmptyEditText> textList = new ArrayList<>();
getChildEdit(textList,view);
return textList;
}
private List<EmptyEditText> getChildEdit(List<EmptyEditText> textList,View view){
if(view instanceof ViewGroup) {
ViewGroup vp = (ViewGroup) view;
for (int i = 0; i < vp.getChildCount(); i++) {
View viewchild = vp.getChildAt(i);
if(viewchild instanceof ViewGroup){
getChildEdit(textList,viewchild);
}else if(viewchild instanceof EmptyEditText){
textList.add((EmptyEditText) viewchild);
}
}
}
return textList;
}
public boolean checkEmpty(Context context){
CopyOnWriteArrayList data = textMap.get(context);
if(null == data || data.size() ==0){
if(context instanceof Activity){
List<EmptyEditText> textList = getAllViews((Activity) context);
register(context,textList);
return checkEmpty(textList);
}
return checkEmpty(data);
}
return checkEmpty(data);
}
public boolean checkEmpty(CopyOnWriteArrayList<EmptyEditText> editList){
boolean result = false;
if(null == editList || editList.size() ==0){
return result;
}
for (EmptyEditText edittext:editList) {
if(edittext.checkEmpty(true)){
result = true;
break;
}
}
return result;
}
private List<EmptyEditText> getAllViews(Activity act) {
return getAllChildViews(act.getWindow().getDecorView());
}
private List<EmptyEditText> getAllChildViews(View view) {
List<EmptyEditText> allchildren = new ArrayList<>();
if (view instanceof ViewGroup) {
ViewGroup vp = (ViewGroup) view;
for (int i = 0; i < vp.getChildCount(); i++) {
View viewchild = vp.getChildAt(i);
if(viewchild instanceof EmptyEditText){
allchildren.add((EmptyEditText) viewchild);
}else if(viewchild instanceof ViewGroup){
//再次 调用本身(递归)
allchildren.addAll(getAllChildViews(viewchild));
}
}
}
return allchildren;
}
public boolean checkEmpty(List<EmptyEditText> data){
CopyOnWriteArrayList<EmptyEditText> editList = new CopyOnWriteArrayList<>();
editList.addAll(data);
return checkEmpty(editList);
}
public void unRegister(Context context){
textMap.remove(context);
}
}
values中自定义EditText所需要的提示与是否必须:
<declare-styleable name="EmptyEditText">
<attr name="toast_text" format="string|reference" />
<attr name="necessary" format="boolean|reference" />
</declare-styleable>
至此,目前两种Android必填项判空的方式已完成,如果只是单纯的登陆界面无所谓,但是如果是大量添加表单的页面,这样精简还是很有必要的。另外这样的注册器还有一个问题,就是当采用xml的注册方式时,EditText的getText值一直为空,希望大家有好的解决方式!

本文探讨了在Android中处理多个Edittext必填项的方法,建议使用单例模式创建注册器来动态注册Edittext,并在保存前进行判断。这种方法避免了反射操作,减少了耗时。通过XML、View和自定义Edittext注册,以及在基类Activity的onDestroy中解绑,实现了方便的必填项检查。同时,文章提到了在XML注册方式下EditText的getText值可能为空的问题,期待解决方案。
377

被折叠的 条评论
为什么被折叠?



