安卓pad仿写element-ui表单验证
安卓pad仿写element-ui表单验证
- 背景:
- 仿写对象:
- showcase:
- 布局总览:
- 核心代码总览:
- 代码仓:
背景:
最近半年开始接触安卓开发,平时开发接触的点比较零碎,计划闲暇时做一些个人Demo进行总结,此文主要在安卓pad端设备仿写element-ui表单验证功能,用到的布局有组件有LinearLayout、TableLayout、用到的组件有TextView、EditText、Spinner、Switch、CheckBox、Button
仿写对象:
element-ui 表单验证案例
showcase:
布局总览:
总体采用LinearLayout垂直布局,上部分使用TableLayout布局表单,下部分用LinearLayout水平布局包裹Button。
详细代码见layout/fragment_custom_form.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/white"
tools:context=".fragment.CustomFormFragment">
<TableLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginTop="10dp"
android:stretchColumns="1">
<!--活动名称-->
<TableRow>
<TextView
android:text="活动名称"
android:textSize="16sp"/>
<EditText
android:id="@+id/activityName"
android:textSize="16sp"
android:background="@drawable/element_edit"
android:paddingStart="10dp"
android:layout_marginStart="5dp"/>
</TableRow>
<TextView
android:id="@+id/activityNameTip"
android:textStyle="bold"
android:textColor="@color/tip_red"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<!--活动区域-->
<TableRow android:minHeight="50dp">
<TextView
android:text="活动区域"
android:textSize="16sp"/>
<Spinner
android:id="@+id/activityArea"
android:layout_gravity="start"
android:textSize="16sp"/>
</TableRow>
<TextView
android:id="@+id/activityAreaTip"
android:textColor="@color/tip_red"
android:textStyle="bold"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<!--活动时间 自定义时间&日期-->
<TableRow android:minHeight="50dp">
<TextView
android:text="活动时间"
android:textSize="16sp"
android:layout_marginTop="10dp"/>
<LinearLayout android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/activityDate"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="@color/pale_gray"
android:text="选择日期"
android:background="@drawable/white_blue_background"
android:padding="10dp"
android:drawableLeft="@mipmap/date_icon"
android:layout_marginStart="5dp"/>
<View
android:layout_width="10dp"
android:layout_height="2dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:background="@color/gray"/>
<Button
android:id="@+id/activityTime"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="@color/pale_gray"
android:text="选择时间"
android:background="@drawable/white_blue_background"
android:padding="10dp"
android:drawableLeft="@mipmap/time_icon"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:orientation="horizontal">
<TextView
android:id="@+id/activityDateTip"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="@color/tip_red"
android:layout_marginStart="5dp"/>
<View
android:layout_width="10dp"
android:layout_height="2dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:background="@color/white"/>
<TextView
android:id="@+id/activityTimeTip"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="@color/tip_red"
android:padding="10dp"/>
</LinearLayout>
</LinearLayout>
</TableRow>
<!--及时配送 开关按钮-->
<TableRow android:minHeight="50dp">
<TextView
android:text="及时配送"
android:textSize="16sp"/>
<Switch
android:id="@+id/timelyDelivery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:thumbTint="@color/blue_switch"
android:layout_marginStart="10dp"/>
</TableRow>
<!--活动性质-->
<TableRow android:minHeight="50dp">
<TextView
android:text="活动性质"
android:textSize="16sp"
android:layout_marginTop="5dp"/>
<LinearLayout
android:id="@+id/activityLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<CheckBox
android:id="@+id/onlineActivity"
android:text="美食/餐厅线上活动"
android:textSize="16sp"
android:buttonTint="@color/blue_checked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:id="@+id/pushActivity"
android:text="地推活动"
android:textSize="16sp"
android:buttonTint="@color/blue_checked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:id="@+id/offlineActivity"
android:text="线下主题活动"
android:textSize="16sp"
android:buttonTint="@color/blue_checked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:id="@+id/brandExposure"
android:text="单纯品牌曝光"
android:textSize="16sp"
android:buttonTint="@color/blue_checked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</TableRow>
<TextView
android:id="@+id/activityNatureTip"
android:textStyle="bold"
android:textColor="@color/tip_red"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<!--特殊资源-->
<TableRow android:minHeight="50dp">
<TextView
android:text="特殊资源"
android:layout_marginTop="10dp"
android:textSize="16sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:paddingTop="5dp"
android:orientation="horizontal">
<CheckBox
style="@style/Widget.AppCompat.CompoundButton.RadioButton"
android:buttonTint="@color/blue_checked"
android:id="@+id/onlineBrandSponsorship"
android:text="线上品牌商赞助"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:id="@+id/offlineFree"
style="@style/Widget.AppCompat.CompoundButton.RadioButton"
android:buttonTint="@color/blue_checked"
android:text="线下场地免费"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</TableRow>
<TextView
android:id="@+id/specialTip"
android:textStyle="bold"
android:textColor="@color/tip_red"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<!--活动形式-->
<TableRow android:minHeight="50dp">
<TextView
android:text="活动形式"
android:textSize="16sp"/>
<EditText
android:id="@+id/eventFormat"
android:layout_marginStart="5dp"
android:textSize="16sp"
android:background="@drawable/element_edit"
android:paddingStart="10dp"
android:maxLines="3"/>
</TableRow>
<TextView
android:id="@+id/eventFormatTip"
android:textStyle="bold"
android:textColor="@color/tip_red"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
</TableLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
>
<Button
android:id="@+id/createBtn"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:textSize="16sp"
android:background="@drawable/sky_blue_background"
android:textColor="@color/white"
android:text="立即创建"/>
<Button
android:id="@+id/resetBtn"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:textSize="16sp"
android:background="@drawable/white_blue_background"
android:textColor="@color/gray"
android:text="重置"/>
</LinearLayout>
</LinearLayout>
核心代码总览:
总体逻辑抽取在CustomFormFragment#onViewCreated
中,主要功能如下:
详细代码见:com/example/myapplication1_java/fragment/CustomFormFragment.java
package com.example.myapplication1_java.fragment;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import com.example.myapplication1_java.R;
import com.example.myapplication1_java.adapter.SpinnerHintAdapter;
import com.example.myapplication1_java.databinding.FragmentCustomFormBinding;
import com.example.myapplication1_java.util.ConvertUtil;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author PineTree
* @description: 仿element-ui表单
* @date 2025/1/24 14:16
*/
public class CustomFormFragment extends Fragment {
private FragmentCustomFormBinding binding;
private TextView activityNameTip;
private TextView activityDateTip;
private TextView activityTimeTip;
private TextView activityNatureTip;
private TextView activityAreaTip;
private String selectArea;
private TextView specialTip;
private TextView eventFormatTip;
private EditText activityName;
private Spinner activityArea;
private Button activityDate;
private Button activityTime;
private Switch timelyDelivery;
private String timelyDeliveryValue;
private CheckBox onlineActivity;
private String onlineActivityValue;
LinearLayout activityLayout;
private CheckBox pushActivity;
private String pushActivityValue;
private CheckBox offlineActivity;
private String offlineActivityValue;
private CheckBox brandExposure;
private String brandExposureValue;
private CheckBox onlineBrandSponsorship;
private String onlineBrandSponsorshipValue;
private CheckBox offlineFree;
private String offlineFreeValue;
private EditText eventFormat;
private Button createBtn;
private boolean createVerifyPass;
private Button resetBtn;
private boolean resetBtnClickFlag = false;
private String selectDate;
private String selectTime;
List<String> areaSelect = Arrays.asList("区域一", "区域二");
List<String> allAreas = new ArrayList<>(areaSelect);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentCustomFormBinding.inflate(inflater, container, false);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
bindingLayoutId();
setActivityAreaEvent();
setActivityNameEvent();
setActivityDateEvent(view);
setActivityTimeEvent(view);
setTimelyDeliveryEvent();
setActivityNatureEvent();
setSpecialResourceEvent();
setEventFormatEvent();
handleCreateEvent();
handleResetEvent();
}
private void handleResetEvent() {
resetBtn.setOnClickListener(v -> {
resetBtnClickFlag = true;
activityName.setText(null);
selectArea = null;
activityAreaTip.setText(null);
setActivityAreaEvent();
selectDate = null;
activityDateTip.setText(null);
activityDate.setText("选择日期");
activityDate.setTextColor(ContextCompat.getColor(getContext(), R.color.pale_gray));
selectTime = null;
activityTimeTip.setText(null);
activityTime.setText("选择时间");
activityTime.setTextColor(ContextCompat.getColor(getContext(), R.color.pale_gray));
timelyDelivery.setChecked(false);
onlineActivity.setChecked(false);
pushActivity.setChecked(false);
offlineActivity.setChecked(false);
brandExposure.setChecked(false);
activityNatureTip.setText(null);
onlineBrandSponsorship.setChecked(false);
offlineFree.setChecked(false);
specialTip.setText(null);
eventFormat.setText(null);
resetBtnClickFlag = false;
});
}
private void handleCreateEvent() {
createBtn.setOnClickListener(v -> {
createVerifyPass = true;
// 必填校验
verifyActivityName();
verifyActivityArea();
verifyActivityDate();
verifyActivityTime();
verifyActivityNature();
verifySpecialResource();
verifyEventFormat();
// 校验通过后弹出提示已选择的信息
if (!createVerifyPass) {
return;
}
String submitMsg = String.format("表单的数据为:活动名称:%s,活动区域:%s,活动时间:%s,及时配送:%s " +
"活动性质:美食/餐厅线上活动:%s、地推活动:%s、线下主题活动:%s、单纯品牌曝光:%s " +
"特殊资源:线上品牌赞助商:%s,线下场地免费:%s " +
"活动形式:%s", activityName.getText(), selectArea, selectDate + "-" + selectTime, timelyDeliveryValue,
onlineActivityValue, pushActivityValue, offlineActivityValue, brandExposureValue,
onlineBrandSponsorshipValue, offlineFreeValue, eventFormat.getText());
Toast.makeText(getContext(), submitMsg, Toast.LENGTH_SHORT).show();
});
}
private void setTimelyDeliveryEvent() {
if (timelyDelivery.isChecked()) {
timelyDeliveryValue = "Y";
} else {
timelyDeliveryValue = "N";
}
}
private void setEventFormatEvent() {
eventFormat.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) {
verifyEventFormat();
}
});
}
private void setSpecialResourceEvent() {
onlineBrandSponsorship.setOnCheckedChangeListener((buttonView, isChecked) -> verifySpecialResource());
if (onlineBrandSponsorship.isChecked()) {
onlineBrandSponsorshipValue = "Y";
} else {
onlineBrandSponsorshipValue = "N";
}
offlineFree.setOnCheckedChangeListener((buttonView, isChecked) -> verifySpecialResource());
if (offlineFree.isChecked()) {
offlineFreeValue = "Y";
} else {
offlineFreeValue = "N";
}
}
private void setActivityNatureEvent() {
onlineActivity.setOnCheckedChangeListener((buttonView, isChecked) -> verifyActivityNature());
if (onlineActivity.isChecked()) {
onlineActivityValue = "Y";
} else {
onlineActivityValue = "N";
}
pushActivity.setOnCheckedChangeListener((buttonView, isChecked) -> verifyActivityNature());
if (pushActivity.isChecked()) {
pushActivityValue = "Y";
} else {
pushActivityValue = "N";
}
offlineActivity.setOnCheckedChangeListener((buttonView, isChecked) -> verifyActivityNature());
if (offlineActivity.isChecked()) {
offlineActivityValue = "Y";
} else {
offlineActivityValue = "N";
}
brandExposure.setOnCheckedChangeListener((buttonView, isChecked) -> verifyActivityNature());
if (brandExposure.isChecked()) {
brandExposureValue = "Y";
} else {
brandExposureValue = "N";
}
}
private void verifyEventFormat() {
// 活动形式校验
if (!resetBtnClickFlag && StringUtils.isEmpty(eventFormat.getText())) {
eventFormatTip.setText("请填写活动形式");
createVerifyPass = false;
} else {
eventFormatTip.setText(null);
}
}
private void verifySpecialResource() {
// 特殊资源校验
if (resetBtnClickFlag || onlineBrandSponsorship.isChecked() || offlineFree.isChecked()) {
specialTip.setText(null);
} else {
specialTip.setText("请选择活动资源");
createVerifyPass = false;
}
}
private void verifyActivityNature() {
if (resetBtnClickFlag || onlineActivity.isChecked() || pushActivity.isChecked() || offlineActivity.isChecked() || brandExposure.isChecked()) {
activityNatureTip.setText(null);
} else {
activityNatureTip.setText("请至少选择一个活动性质");
createVerifyPass = false;
}
}
private void verifyActivityTime() {
if (StringUtils.isEmpty(selectTime)) {
activityTimeTip.setText("请选择时间");
createVerifyPass = false;
} else {
activityTimeTip.setText(null);
}
}
private void verifyActivityDate() {
if (StringUtils.isEmpty(selectDate)) {
activityDateTip.setText("请选择日期");
createVerifyPass = false;
} else {
activityDateTip.setText(null);
}
}
private void verifyActivityArea() {
if (!areaSelect.contains(selectArea)) {
activityAreaTip.setText("请选择活动区域");
createVerifyPass = false;
} else {
activityAreaTip.setText(null);
}
}
private void setActivityAreaEvent() {
if (allAreas.size() == areaSelect.size()) {
allAreas.add("请选择区域");
}
SpinnerHintAdapter hintAdapter = new SpinnerHintAdapter(getContext(), R.id.activityArea, R.layout.support_simple_spinner_dropdown_item, allAreas);
activityArea.setAdapter(hintAdapter);
activityArea.setSelection(allAreas.size() - 1, true);
activityArea.setDropDownVerticalOffset(ConvertUtil.dp2px(40));
activityArea.setDropDownHorizontalOffset(ConvertUtil.dp2px(10));
activityArea.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position < areaSelect.size()) {
selectArea = areaSelect.get(position);
verifyActivityArea();
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
private void setActivityNameEvent() {
activityName.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) {
verifyActivityName();
}
});
}
private void verifyActivityName() {
Editable activityNameValue = activityName.getText();
if (!resetBtnClickFlag && StringUtils.isEmpty(activityNameValue)) {
activityNameTip.setText("请输入活动名称");
createVerifyPass = false;
} else {
if (!resetBtnClickFlag && (activityNameValue.length() < 3 || activityNameValue.length() > 5)) {
activityNameTip.setText("长度在3到5个字符");
createVerifyPass = false;
} else {
activityNameTip.setText(null);
}
}
}
private void setActivityTimeEvent(View view) {
activityTime.setOnClickListener(v -> {
View timePickView = LayoutInflater.from(getContext()).inflate(R.layout.activity_time_picker, null, false);
// 构造一个PopupWindow,参数依次是加载的View,宽高
final PopupWindow timePickPop = new PopupWindow(timePickView,
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
// 设置加载动画
timePickPop.setAnimationStyle(R.anim.anim_pop);
timePickPop.setBackgroundDrawable(new ColorDrawable(Color.WHITE));
timePickPop.setTouchable(true);
// 设置pop边缘阴影,单位像素
timePickPop.setElevation(10);
timePickPop.showAtLocation(view, Gravity.CENTER, 0, 0);
TimePicker timePicker = timePickView.findViewById(R.id.timePicker);
// 设置24小时制
timePicker.setIs24HourView(true);
timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
@Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
selectTime = hourOfDay + ":" + minute;
activityTime.setText(selectTime);
activityTime.setTextColor(Color.BLACK);
verifyActivityTime();
}
});
TextView confirmBtn = timePickView.findViewById(R.id.confirm_btn);
confirmBtn.setOnClickListener(click -> {
selectTime = timePicker.getHour() + ":" + timePicker.getMinute();
activityTime.setText(selectTime);
activityTime.setTextColor(Color.BLACK);
timePickPop.dismiss();
});
TextView cancelBtn = timePickView.findViewById(R.id.cancel_btn);
cancelBtn.setOnClickListener(click -> timePickPop.dismiss());
});
}
private void setActivityDateEvent(View view) {
activityDate.setOnClickListener(v -> {
View datePickView = LayoutInflater.from(getContext()).inflate(R.layout.activity_date_picker, null, false);
// 构造一个PopupWindow,参数依次是加载的View,宽高
final PopupWindow datePickPop = new PopupWindow(datePickView,
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
// 设置加载动画
datePickPop.setAnimationStyle(R.anim.anim_pop);
datePickPop.setBackgroundDrawable(new ColorDrawable(Color.WHITE));
datePickPop.setTouchable(true);
// 设置pop边缘阴影,单位像素
datePickPop.setElevation(10);
datePickPop.showAtLocation(view, Gravity.CENTER, 0, 0);
DatePicker datePicker = datePickView.findViewById(R.id.datePicker);
// 隐藏头部
ViewGroup childAt = (ViewGroup) datePicker.getChildAt(0);
childAt.getChildAt(0).setVisibility(View.GONE);
// 获取日期选择
datePicker.setOnDateChangedListener(new DatePicker.OnDateChangedListener() {
@Override
public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
selectDate = year + "-" + (monthOfYear + 1) + "-" + dayOfMonth;
activityDate.setText(selectDate);
activityDate.setTextColor(Color.BLACK);
verifyActivityDate();
}
});
TextView confirmBtn = datePickView.findViewById(R.id.confirm_btn);
confirmBtn.setOnClickListener(click -> {
selectDate = datePicker.getYear() + "-" + (datePicker.getMonth() + 1) + "-" + datePicker.getDayOfMonth();
activityDate.setText(selectDate);
activityDate.setTextColor(Color.BLACK);
datePickPop.dismiss();
});
TextView cancelBtn = datePickView.findViewById(R.id.cancel_btn);
cancelBtn.setOnClickListener(click -> datePickPop.dismiss());
});
}
private void bindingLayoutId() {
activityNameTip = binding.activityNameTip;
activityDateTip = binding.activityDateTip;
activityTimeTip = binding.activityTimeTip;
activityNatureTip = binding.activityNatureTip;
activityAreaTip = binding.activityAreaTip;
eventFormatTip = binding.eventFormatTip;
specialTip = binding.specialTip;
activityName = binding.activityName;
activityArea = binding.activityArea;
activityDate = binding.activityDate;
activityTime = binding.activityTime;
timelyDelivery = binding.timelyDelivery;
onlineActivity = binding.onlineActivity;
activityLayout = binding.activityLayout;
pushActivity = binding.pushActivity;
offlineActivity = binding.offlineActivity;
brandExposure = binding.brandExposure;
onlineBrandSponsorship = binding.onlineBrandSponsorship;
offlineFree = binding.offlineFree;
eventFormat = binding.eventFormat;
createBtn = binding.createBtn;
resetBtn = binding.resetBtn;
}
}
代码仓:
码云
github
欢迎在评论区讨论,后续会根据常见的问题补充博客或视频