first commit
@@ -0,0 +1,24 @@
|
||||
package com.example.defenseapplication
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.example.defenseapplication", appContext.packageName)
|
||||
}
|
||||
}
|
||||
31
app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.DefenseApplication">
|
||||
<activity
|
||||
android:name=".login.ForgetPasswordActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".login.RegisterActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".login.LoginActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,205 @@
|
||||
package com.example.defenseapplication.login
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.CountDownTimer
|
||||
import android.text.InputType
|
||||
import android.text.TextUtils
|
||||
import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.ForgetPasswordActivityBinding
|
||||
import com.example.defenseapplication.okhttp.OkHttpClientManager
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.random.Random
|
||||
|
||||
class ForgetPasswordActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ForgetPasswordActivityBinding
|
||||
private var verifyCode: String? = null // 存储模拟验证码
|
||||
private var countDownTimer: CountDownTimer? = null
|
||||
private var isSendingCode = false // 防止重复发送验证码
|
||||
|
||||
companion object {
|
||||
private const val COUNTDOWN_DURATION = 60000L // 60秒倒计时
|
||||
private const val COUNTDOWN_INTERVAL = 1000L
|
||||
private const val MIN_PASSWORD_LENGTH = 6
|
||||
private const val MAX_PASSWORD_LENGTH = 20
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ForgetPasswordActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setupClickListeners()
|
||||
}
|
||||
|
||||
private fun setupClickListeners() {
|
||||
// 返回按钮
|
||||
binding.backIcon.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
// 发送验证码按钮
|
||||
binding.sendCodeBtn.setOnClickListener {
|
||||
if (!isSendingCode && countDownTimer == null) {
|
||||
val phoneNumber = binding.etPhoneNumber.text.toString().trim()
|
||||
if (isPhoneNumberValid(phoneNumber)) {
|
||||
sendVerificationCode(phoneNumber)
|
||||
} else {
|
||||
Toast.makeText(this, "请输入有效的11位手机号", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(this, "请稍后再试", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
// 确定按钮(重置密码)
|
||||
binding.btnNext.setOnClickListener {
|
||||
performResetPassword()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号格式校验(简单1开头的11位数字)
|
||||
*/
|
||||
private fun isPhoneNumberValid(phone: String): Boolean {
|
||||
if (TextUtils.isEmpty(phone)) return false
|
||||
val pattern = Pattern.compile("^1[0-9]{10}$")
|
||||
return pattern.matcher(phone).matches()
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送验证码
|
||||
*/
|
||||
private fun sendVerificationCode(phoneNumber: String) {
|
||||
isSendingCode = true
|
||||
binding.sendCodeBtn.isEnabled = false
|
||||
|
||||
OkHttpClientManager.postForm(
|
||||
url = "https://httpbin.org/post",
|
||||
params = mapOf("phone" to phoneNumber)
|
||||
) { result ->
|
||||
result.onSuccess {
|
||||
verifyCode = (100000 + Random.nextInt(900000)).toString()
|
||||
startCountDown()
|
||||
Toast.makeText(this, "验证码已发送(演示码:$verifyCode)", Toast.LENGTH_SHORT).show()
|
||||
}.onFailure {
|
||||
Toast.makeText(this@ForgetPasswordActivity, "发送失败,请重试", Toast.LENGTH_SHORT).show()
|
||||
resetSendButton()
|
||||
}
|
||||
isSendingCode = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始验证码按钮倒计时
|
||||
*/
|
||||
private fun startCountDown() {
|
||||
countDownTimer = object : CountDownTimer(COUNTDOWN_DURATION, COUNTDOWN_INTERVAL) {
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
val secondsRemaining = (millisUntilFinished / 1000).toInt()
|
||||
binding.sendCodeBtn.text = "${secondsRemaining}秒后重试"
|
||||
binding.sendCodeBtn.isEnabled = false
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
resetSendButton()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置发送按钮状态
|
||||
*/
|
||||
private fun resetSendButton() {
|
||||
countDownTimer?.cancel()
|
||||
countDownTimer = null
|
||||
binding.sendCodeBtn.text = "发送验证码"
|
||||
binding.sendCodeBtn.isEnabled = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行重置密码请求
|
||||
*/
|
||||
private fun performResetPassword() {
|
||||
val phoneNumber = binding.etPhoneNumber.text.toString().trim()
|
||||
val code = binding.etSmsCode.text.toString().trim()
|
||||
val newPassword = binding.etPassword.text.toString().trim()
|
||||
val confirmPassword = binding.etInviteCode.text.toString().trim()
|
||||
|
||||
// 1. 手机号校验
|
||||
if (!isPhoneNumberValid(phoneNumber)) {
|
||||
Toast.makeText(this, "手机号格式不正确", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 验证码校验
|
||||
if (TextUtils.isEmpty(code)) {
|
||||
Toast.makeText(this, "请输入验证码", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
if (verifyCode == null) {
|
||||
Toast.makeText(this, "请先获取验证码", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
if (code != verifyCode) {
|
||||
Toast.makeText(this, "验证码错误", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
// 3. 密码校验
|
||||
if (TextUtils.isEmpty(newPassword) || TextUtils.isEmpty(confirmPassword)) {
|
||||
Toast.makeText(this, "密码不能为空", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
if (newPassword.length < MIN_PASSWORD_LENGTH || newPassword.length > MAX_PASSWORD_LENGTH) {
|
||||
Toast.makeText(this, "密码长度需为${MIN_PASSWORD_LENGTH}-${MAX_PASSWORD_LENGTH}位", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
if (!newPassword.matches(Regex(".*[A-Za-z].*")) || !newPassword.matches(Regex(".*[0-9].*"))) {
|
||||
Toast.makeText(this, "密码需同时包含字母和数字", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
if (newPassword != confirmPassword) {
|
||||
Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
// 禁用确定按钮,防重复提交
|
||||
binding.btnNext.isEnabled = false
|
||||
binding.btnNext.text = "重置中..."
|
||||
|
||||
val requestJson = """
|
||||
{
|
||||
"phone":"$phoneNumber",
|
||||
"code":"$code",
|
||||
"newPassword":"$newPassword"
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
OkHttpClientManager.postJson(
|
||||
url = "https://httpbin.org/post",
|
||||
json = requestJson
|
||||
) { result ->
|
||||
result.onSuccess {
|
||||
Toast.makeText(this, "密码重置成功,请重新登录", Toast.LENGTH_LONG).show()
|
||||
finish()
|
||||
}.onFailure {
|
||||
Toast.makeText(this, "网络异常,请重试", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
binding.btnNext.isEnabled = true
|
||||
binding.btnNext.text = "确定"
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
countDownTimer?.cancel()
|
||||
countDownTimer = null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package com.example.defenseapplication.login
|
||||
import android.content.Intent
|
||||
import com.example.defenseapplication.R
|
||||
import android.os.Bundle
|
||||
import android.os.CountDownTimer
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import com.example.defenseapplication.databinding.ActivityLoginBinding
|
||||
|
||||
class LoginActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityLoginBinding
|
||||
private var currentLoginMode = LoginMode.SMS
|
||||
|
||||
enum class LoginMode { SMS, PASSWORD }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityLoginBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setupTabListeners()
|
||||
setupClickListeners()
|
||||
switchToSmsMode()
|
||||
}
|
||||
|
||||
private fun setupTabListeners() {
|
||||
binding.tvSmsLogin.setOnClickListener {
|
||||
if (currentLoginMode != LoginMode.SMS) {
|
||||
currentLoginMode = LoginMode.SMS
|
||||
switchToSmsMode()
|
||||
}
|
||||
}
|
||||
binding.tvPwdLogin.setOnClickListener {
|
||||
if (currentLoginMode != LoginMode.PASSWORD) {
|
||||
currentLoginMode = LoginMode.PASSWORD
|
||||
switchToPasswordMode()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun switchToSmsMode() {
|
||||
binding.tvSmsLogin.setTextColor(getColor(R.color.black))
|
||||
binding.tvPwdLogin.setTextColor(getColor(R.color.gray))
|
||||
|
||||
binding.smsRowLayout.visibility = View.VISIBLE
|
||||
binding.passwordRowLayout.visibility = View.GONE // 隐藏密码行容器
|
||||
|
||||
binding.registerText.visibility = View.VISIBLE
|
||||
binding.forgetText.visibility = View.GONE
|
||||
updateRegisterTextConstraints(center = true)
|
||||
|
||||
//需要正确的方法名和参数
|
||||
updateLoginButtonTopConstraint(R.id.smsRowLayout)
|
||||
}
|
||||
|
||||
private fun switchToPasswordMode() {
|
||||
binding.tvPwdLogin.setTextColor(getColor(R.color.black))
|
||||
binding.tvSmsLogin.setTextColor(getColor(R.color.gray))
|
||||
|
||||
binding.smsRowLayout.visibility = View.GONE
|
||||
//正确的属性访问
|
||||
binding.passwordRowLayout.visibility = View.VISIBLE // 显示密码行容器
|
||||
|
||||
binding.registerText.visibility = View.VISIBLE
|
||||
binding.forgetText.visibility = View.VISIBLE
|
||||
updateRegisterTextConstraints(center = false)
|
||||
|
||||
updateLoginButtonTopConstraint(R.id.passwordRowLayout)
|
||||
}
|
||||
|
||||
// 动态修改登录按钮的顶部约束
|
||||
private fun updateLoginButtonTopConstraint(topTargetId: Int) {
|
||||
val params = binding.loginBtn.layoutParams as ConstraintLayout.LayoutParams
|
||||
params.topToBottom = topTargetId
|
||||
params.topMargin = 32
|
||||
binding.loginBtn.layoutParams = params
|
||||
}
|
||||
|
||||
// 动态修改立即注册的约束(居中/左对齐)
|
||||
private fun updateRegisterTextConstraints(center: Boolean) {
|
||||
val params = binding.registerText.layoutParams as ConstraintLayout.LayoutParams
|
||||
if (center) {
|
||||
// 短信模式:居中显示
|
||||
params.startToStart = ConstraintSet.PARENT_ID
|
||||
params.endToEnd = ConstraintSet.PARENT_ID
|
||||
} else {
|
||||
// 密码模式:左对齐登录按钮
|
||||
params.startToStart = binding.loginBtn.id
|
||||
params.endToEnd = ConstraintSet.UNSET
|
||||
}
|
||||
params.topToBottom = binding.loginBtn.id
|
||||
params.topMargin = 20
|
||||
binding.registerText.layoutParams = params
|
||||
}
|
||||
|
||||
private fun setupClickListeners() {
|
||||
binding.loginBtn.setOnClickListener {
|
||||
val phone = binding.etPhone.text.toString()
|
||||
if (phone.isEmpty()) {
|
||||
Toast.makeText(this, "请输入手机号", Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
when (currentLoginMode) {
|
||||
LoginMode.SMS -> {
|
||||
val code = binding.etSmsCode.text.toString()
|
||||
if (code.isEmpty()) {
|
||||
Toast.makeText(this, "请输入验证码", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Toast.makeText(this, "验证码登录成功\n手机号:$phone\n验证码:$code", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
LoginMode.PASSWORD -> {
|
||||
val pwd = binding.etPassword.text.toString()
|
||||
if (pwd.isEmpty()) {
|
||||
Toast.makeText(this, "请输入密码", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Toast.makeText(this, "密码登录成功\n手机号:$phone\n密码:$pwd", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.sendCodeBtn.setOnClickListener {
|
||||
val phone = binding.etPhone.text.toString()
|
||||
if (phone.isEmpty()) {
|
||||
Toast.makeText(this, "请先输入手机号", Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
Toast.makeText(this, "验证码已发送至 $phone", Toast.LENGTH_SHORT).show()
|
||||
startCountDown()
|
||||
}
|
||||
|
||||
binding.registerText.setOnClickListener {
|
||||
val intent= Intent(this, RegisterActivity::class.java)
|
||||
startActivity(intent)
|
||||
Toast.makeText(this, "跳转到注册页面", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
binding.forgetText.setOnClickListener {
|
||||
val intent= Intent(this, ForgetPasswordActivity::class.java)
|
||||
startActivity(intent)
|
||||
Toast.makeText(this, "找回密码", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun startCountDown() {
|
||||
binding.sendCodeBtn.isEnabled = false
|
||||
object : CountDownTimer(60000, 1000) {
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
binding.sendCodeBtn.text = "${millisUntilFinished / 1000}秒后重试"
|
||||
}
|
||||
override fun onFinish() {
|
||||
binding.sendCodeBtn.text = "发送验证码"
|
||||
binding.sendCodeBtn.isEnabled = true
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package com.example.defenseapplication.login
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.databinding.RegisterActivityBinding
|
||||
|
||||
/**
|
||||
* 注册页面
|
||||
* 功能:收集用户信息(手机号、身份证号、密码、邀请码),
|
||||
* 进行前端格式校验,模拟注册请求并反馈结果。
|
||||
*/
|
||||
class RegisterActivity : AppCompatActivity() {
|
||||
private lateinit var binding: RegisterActivityBinding
|
||||
private var isLoading = false // 防止重复点击
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = RegisterActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setupListeners()
|
||||
//setupTextWatchers()
|
||||
}
|
||||
|
||||
private fun setupListeners() {
|
||||
// 返回按钮
|
||||
binding.backIcon.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
// 下一步按钮
|
||||
binding.btnNext.setOnClickListener {
|
||||
if (!isLoading) {
|
||||
//performRegistration()
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// /**
|
||||
// * 为输入框添加文字监听,实时清除错误提示
|
||||
// */
|
||||
// private fun setupTextWatchers() {
|
||||
// val errorClearWatcher = object : TextWatcher {
|
||||
// override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
// override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||
// override fun afterTextChanged(s: Editable?) {
|
||||
// // 当用户开始输入时,清除该字段的错误
|
||||
// when (binding.etPhoneNumber.hasFocus()) {
|
||||
// true -> binding.etPhoneNumber.error = null
|
||||
// else -> Unit
|
||||
// }
|
||||
// when (binding.etIdNumber.hasFocus()) {
|
||||
// true -> binding.etIdNumber.error = null
|
||||
// else -> Unit
|
||||
// }
|
||||
// when (binding.etPassword.hasFocus()) {
|
||||
// true -> binding.etPassword.error = null
|
||||
// else -> Unit
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// binding.etPhoneNumber.addTextChangedListener(errorClearWatcher)
|
||||
// binding.etIdNumber.addTextChangedListener(errorClearWatcher)
|
||||
// binding.etPassword.addTextChangedListener(errorClearWatcher)
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 执行注册流程:校验输入 -> 模拟网络请求
|
||||
// */
|
||||
// private fun performRegistration() {
|
||||
// val phone = binding.etPhoneNumber.text.toString().trim()
|
||||
// val idNumber = binding.etIdNumber.text.toString().trim()
|
||||
// val password = binding.etPassword.text.toString().trim()
|
||||
// val inviteCode = binding.etInviteCode.text.toString().trim()
|
||||
//
|
||||
// // 1. 校验
|
||||
// val phoneValid = validatePhone(phone)
|
||||
// val idValid = validateIdNumber(idNumber)
|
||||
// val passwordValid = validatePassword(password)
|
||||
//
|
||||
// if (!phoneValid) {
|
||||
// binding.etPhoneNumber.error = "请输入有效的11位手机号"
|
||||
// binding.etPhoneNumber.requestFocus()
|
||||
// return
|
||||
// }
|
||||
// if (!idValid) {
|
||||
// binding.etIdNumber.error = "请输入正确的身份证号"
|
||||
// binding.etIdNumber.requestFocus()
|
||||
// return
|
||||
// }
|
||||
// if (!passwordValid) {
|
||||
// binding.etPassword.error = "密码长度需为6~20位"
|
||||
// binding.etPassword.requestFocus()
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // 2. 模拟注册请求(展示加载状态)
|
||||
// isLoading = true
|
||||
// binding.btnNext.isEnabled = false
|
||||
// binding.btnNext.text = "注册中..."
|
||||
//
|
||||
// lifecycleScope.launch {
|
||||
// // 模拟网络延迟 1.5 秒
|
||||
// val registerResult = simulateRegister(phone, idNumber, password, inviteCode)
|
||||
// delay(1500)
|
||||
//
|
||||
// isLoading = false
|
||||
// binding.btnNext.isEnabled = true
|
||||
// binding.btnNext.text = "下一步"
|
||||
//
|
||||
// if (registerResult) {
|
||||
// Toast.makeText(this@RegisterActivity, "注册成功!", Toast.LENGTH_SHORT).show()
|
||||
// // 实际项目中通常跳转到登录页或主页,这里简单关闭当前页面
|
||||
// finish()
|
||||
// } else {
|
||||
// Toast.makeText(this@RegisterActivity, "注册失败,请稍后重试", Toast.LENGTH_SHORT).show()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 模拟注册请求(实际应替换为 Retrofit/OkHttp 调用)
|
||||
// */
|
||||
// private suspend fun simulateRegister(
|
||||
// phone: String,
|
||||
// idNumber: String,
|
||||
// password: String,
|
||||
// inviteCode: String
|
||||
// ): Boolean {
|
||||
// // 模拟网络请求,此处始终返回成功(实际根据后端响应决定)
|
||||
// // 您可以在这里添加真实网络请求逻辑
|
||||
// return true
|
||||
// }
|
||||
// /**
|
||||
// * 校验手机号:中国大陆手机号(简单校验1开头的11位数字,第二位3-9)
|
||||
// */
|
||||
// private fun validatePhone(phone: String): Boolean {
|
||||
// val phoneRegex = Pattern.compile("^1[3-9]\\d{9}$")
|
||||
// return phone.isNotEmpty() && phoneRegex.matcher(phone).matches()
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 校验身份证号(支持15位和18位,18位时校验最后一位校验码)
|
||||
// */
|
||||
// private fun validateIdNumber(idNumber: String): Boolean {
|
||||
// if (idNumber.isEmpty()) return false
|
||||
// // 长度校验
|
||||
// if (idNumber.length != 15 && idNumber.length != 18) return false
|
||||
//
|
||||
// // 15位全数字
|
||||
// if (idNumber.length == 15) {
|
||||
// return idNumber.all { it.isDigit() }
|
||||
// }
|
||||
//
|
||||
// // 18位:前17位为数字,最后一位为数字或大写X
|
||||
// val regex = Regex("^\\d{17}[\\dXx]$")
|
||||
// if (!regex.matches(idNumber)) return false
|
||||
//
|
||||
// // 校验最后一位校验码(可选,提升准确性)
|
||||
// return verifyIdCardChecksum(idNumber)
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 身份证最后一位校验码校验(仅18位)
|
||||
// */
|
||||
// private fun verifyIdCardChecksum(id18: String): Boolean {
|
||||
// val weights = intArrayOf(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2)
|
||||
// val checkCodes = charArrayOf('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2')
|
||||
// var sum = 0
|
||||
// for (i in 0 until 17) {
|
||||
// sum += (id18[i] - '0') * weights[i]
|
||||
// }
|
||||
// val mod = sum % 11
|
||||
// val expectedCheckCode = checkCodes[mod]
|
||||
// return id18[17].uppercaseChar() == expectedCheckCode
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 校验密码:长度6~20位
|
||||
// */
|
||||
// private fun validatePassword(password: String): Boolean {
|
||||
// return password.length in 6..20
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.example.defenseapplication.okhttp
|
||||
|
||||
class OkHttpClient {
|
||||
}
|
||||
170
app/src/main/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
30
app/src/main/res/drawable/ic_launcher_foreground.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
6
app/src/main/res/drawable/rounded_blue_bg.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/green"/>
|
||||
<corners android:radius="16dp"/>
|
||||
</shape>
|
||||
6
app/src/main/res/drawable/textinput_white_bg.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/white"/>
|
||||
<corners android:radius="10dp"/>
|
||||
</shape>
|
||||
258
app/src/main/res/layout/activity_login.xml
Normal file
@@ -0,0 +1,258 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/login_background"
|
||||
android:id="@+id/main"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- Logo 图片:水平居中 -->
|
||||
<ImageView
|
||||
android:id="@+id/logoFrame"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:src="@mipmap/loge"
|
||||
android:contentDescription="Logo"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginTop="32dp" />
|
||||
|
||||
<!-- 文字:放在图片下方,水平居中 -->
|
||||
<TextView
|
||||
android:id="@+id/logoText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="智能防御机"
|
||||
android:textSize="28sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/black"
|
||||
app:layout_constraintTop_toBottomOf="@id/logoFrame"
|
||||
app:layout_constraintStart_toStartOf="@id/logoFrame"
|
||||
app:layout_constraintEnd_toEndOf="@id/logoFrame"
|
||||
android:layout_marginTop="12dp" />
|
||||
|
||||
<!-- Tab 切换栏背景(可选下划线指示器) -->
|
||||
<View
|
||||
android:id="@+id/tabDivider"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="2dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvSmsLogin"
|
||||
app:layout_constraintStart_toStartOf="@+id/tvSmsLogin"
|
||||
app:layout_constraintEnd_toEndOf="@+id/tvPwdLogin"
|
||||
app:layout_constraintWidth_percent="0.5"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<!-- 验证码登录 Tab -->
|
||||
<TextView
|
||||
android:id="@+id/tvSmsLogin"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="58dp"
|
||||
android:gravity="center"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:text="验证码登录"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/logoText" />
|
||||
|
||||
<!-- 密码登录 Tab -->
|
||||
<TextView
|
||||
android:id="@+id/tvPwdLogin"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="密码登录"
|
||||
android:textSize="18sp"
|
||||
android:gravity="center"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:textColor="@color/gray"
|
||||
app:layout_constraintTop_toTopOf="@+id/tvSmsLogin"
|
||||
app:layout_constraintStart_toEndOf="@+id/tvSmsLogin"
|
||||
android:layout_marginStart="24dp" />
|
||||
<!-- 手机号输入行容器 -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/phoneRowLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/textinput_white_bg"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvSmsLogin"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp">
|
||||
<ImageView
|
||||
android:id="@+id/ivPhoneIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@mipmap/lg"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
<!-- 手机号输入框 -->
|
||||
<EditText
|
||||
android:id="@+id/etPhone"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:hint="请输入手机号"
|
||||
android:textColorHint="@color/gray"
|
||||
android:textColor="@android:color/black"
|
||||
android:background="@null"
|
||||
android:inputType="phone"
|
||||
android:paddingVertical="16dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivPhoneIcon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<!-- 验证码登录专用区域:图标 + 验证码输入框 + 发送按钮 -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/smsRowLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/textinput_white_bg"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/phoneRowLayout"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:visibility="visible">
|
||||
|
||||
<!-- 左侧图标 -->
|
||||
<ImageView
|
||||
android:id="@+id/ivSmsIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@mipmap/vc"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<!-- 验证码输入框(无背景) -->
|
||||
<EditText
|
||||
android:id="@+id/etSmsCode"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:hint="请输入验证码"
|
||||
android:textColorHint="@color/gray"
|
||||
android:textColor="@android:color/black"
|
||||
android:background="@null"
|
||||
android:inputType="number"
|
||||
android:paddingVertical="16dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivSmsIcon"
|
||||
app:layout_constraintEnd_toStartOf="@+id/sendCodeBtn"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<!-- 发送验证码按钮 -->
|
||||
<android.widget.Button
|
||||
android:id="@+id/sendCodeBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="发送验证码"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/white"
|
||||
android:background="@drawable/rounded_blue_bg"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:maxWidth="120dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginStart="12dp" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- 密码登录专用区域:图标 + 密码输入框 -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/passwordRowLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/textinput_white_bg"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/phoneRowLayout"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:visibility="gone"> <!-- 初始隐藏 -->
|
||||
|
||||
<!-- 左侧图标 -->
|
||||
<ImageView
|
||||
android:id="@+id/ivPasswordIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@mipmap/ma"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<!-- 密码输入框(无背景) -->
|
||||
<EditText
|
||||
android:id="@+id/etPassword"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:hint="请输入密码"
|
||||
android:textColorHint="@color/gray"
|
||||
android:textColor="@android:color/black"
|
||||
android:background="@null"
|
||||
android:inputType="textPassword"
|
||||
android:paddingVertical="16dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivPasswordIcon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<!-- 登录按钮 -->
|
||||
<android.widget.Button
|
||||
android:id="@+id/loginBtn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="登录"
|
||||
android:textSize="18sp"
|
||||
android:background="@drawable/rounded_blue_bg"
|
||||
android:textColor="@color/white"
|
||||
app:layout_constraintTop_toBottomOf="@+id/smsRowLayout"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<!-- 立即注册 -->
|
||||
<TextView
|
||||
android:id="@+id/registerText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="立即注册"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/green"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginBtn"
|
||||
app:layout_constraintStart_toStartOf="@+id/loginBtn"
|
||||
android:layout_marginTop="20dp" />
|
||||
|
||||
<!-- 忘记密码 -->
|
||||
<TextView
|
||||
android:id="@+id/forgetText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="忘记密码"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/green"
|
||||
android:padding="8dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="@+id/registerText"
|
||||
app:layout_constraintEnd_toEndOf="@+id/loginBtn" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
259
app/src/main/res/layout/forget_password_activity.xml
Normal file
@@ -0,0 +1,259 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:background="@color/login_background"
|
||||
android:id="@+id/main"
|
||||
android:padding="16dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".login.RegisterActivity">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/topContainer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp">
|
||||
<ImageView
|
||||
android:id="@+id/backIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@mipmap/back"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
<!-- 标题:找回密码 -->
|
||||
<TextView
|
||||
android:id="@+id/tvRegisterTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="找回密码"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@id/backIcon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/backIcon" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- 副标题:找回密码 -->
|
||||
<TextView
|
||||
android:id="@+id/tvRegisterSubtitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="找回密码"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="20dp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/topContainer" />
|
||||
|
||||
<!-- 手机号输入行容器 -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/phoneRowLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:background="@drawable/textinput_white_bg"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvRegisterSubtitle">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivPhoneIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@mipmap/lg"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etPhoneNumber"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="@null"
|
||||
android:hint="请输入手机号"
|
||||
android:inputType="phone"
|
||||
android:maxLength="11"
|
||||
android:paddingVertical="16dp"
|
||||
android:textColor="@android:color/black"
|
||||
android:textColorHint="@color/gray"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivPhoneIcon"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- 验证码登录专用区域:图标 + 验证码输入框 + 发送按钮 -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/smsRowLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/textinput_white_bg"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/phoneRowLayout"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:visibility="visible">
|
||||
|
||||
<!-- 左侧图标 -->
|
||||
<ImageView
|
||||
android:id="@+id/ivSmsIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@mipmap/vc"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<!-- 验证码输入框(无背景) -->
|
||||
<EditText
|
||||
android:id="@+id/etSmsCode"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:hint="请输入验证码"
|
||||
android:textColorHint="@color/gray"
|
||||
android:textColor="@android:color/black"
|
||||
android:background="@null"
|
||||
android:inputType="number"
|
||||
android:paddingVertical="16dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivSmsIcon"
|
||||
app:layout_constraintEnd_toStartOf="@+id/sendCodeBtn"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<!-- 发送验证码按钮 -->
|
||||
<android.widget.Button
|
||||
android:id="@+id/sendCodeBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="发送验证码"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/white"
|
||||
android:background="@drawable/rounded_blue_bg"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:maxWidth="120dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginStart="12dp" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- 请输入新密码 -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/passwordRowLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/textinput_white_bg"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/smsRowLayout"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<!-- 左侧图标 -->
|
||||
<ImageView
|
||||
android:id="@+id/ivPasswordIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<!-- 密码输入框(无背景) -->
|
||||
<EditText
|
||||
android:id="@+id/etPassword"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:hint="请输入新密码"
|
||||
android:textColorHint="@color/gray"
|
||||
android:textColor="@android:color/black"
|
||||
android:background="@null"
|
||||
android:inputType="text"
|
||||
android:paddingVertical="16dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivPasswordIcon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<!-- 请再次输入新密码 -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/inviteRowLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/textinput_white_bg"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/passwordRowLayout">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivInviteIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etInviteCode"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="@null"
|
||||
android:hint="请再次输入新密码"
|
||||
android:inputType="text"
|
||||
android:maxLength="10"
|
||||
android:paddingVertical="16dp"
|
||||
android:textColor="@android:color/black"
|
||||
android:textColorHint="@color/gray"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivInviteIcon"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- 确定按钮 -->
|
||||
<android.widget.Button
|
||||
android:id="@+id/btnNext"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="确定"
|
||||
android:textAllCaps="false"
|
||||
android:textSize="16sp"
|
||||
app:cornerRadius="12dp"
|
||||
android:textColor="@color/white"
|
||||
android:background="@drawable/rounded_blue_bg"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/inviteRowLayout" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
244
app/src/main/res/layout/register_activity.xml
Normal file
@@ -0,0 +1,244 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:background="@color/login_background"
|
||||
android:id="@+id/main"
|
||||
android:padding="16dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".login.RegisterActivity">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/topContainer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp">
|
||||
<ImageView
|
||||
android:id="@+id/backIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@mipmap/back"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
<!-- 标题:注册 -->
|
||||
<TextView
|
||||
android:id="@+id/tvRegisterTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="注册"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@id/backIcon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/backIcon" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- 副标题:注册用户 -->
|
||||
<TextView
|
||||
android:id="@+id/tvRegisterSubtitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="注册用户"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="20dp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/topContainer" />
|
||||
|
||||
<!-- 手机号输入行容器 -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/phoneRowLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:background="@drawable/textinput_white_bg"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvRegisterSubtitle">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivPhoneIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@mipmap/lg"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etPhoneNumber"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="@null"
|
||||
android:hint="请输入手机号"
|
||||
android:inputType="phone"
|
||||
android:maxLength="11"
|
||||
android:paddingVertical="16dp"
|
||||
android:textColor="@android:color/black"
|
||||
android:textColorHint="@color/gray"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivPhoneIcon"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- 身份证号输入框 -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/idRowLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/textinput_white_bg"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/phoneRowLayout">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivIdIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@mipmap/id_card"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etIdNumber"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="@null"
|
||||
android:hint="请输入身份证号"
|
||||
android:inputType="text"
|
||||
android:maxLength="18"
|
||||
android:paddingVertical="16dp"
|
||||
android:textColor="@android:color/black"
|
||||
android:textColorHint="@color/gray"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivIdIcon"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- 密码输入框 -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/passwordRowLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/textinput_white_bg"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/idRowLayout"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<!-- 左侧图标 -->
|
||||
<ImageView
|
||||
android:id="@+id/ivPasswordIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@mipmap/ma"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<!-- 密码输入框 -->
|
||||
<EditText
|
||||
android:id="@+id/etPassword"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:hint="请输入密码"
|
||||
android:textColorHint="@color/gray"
|
||||
android:textColor="@android:color/black"
|
||||
android:background="@null"
|
||||
android:inputType="text"
|
||||
android:paddingVertical="16dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivPasswordIcon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<!-- 邀请码输入框(非必填) -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/inviteRowLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/textinput_white_bg"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/passwordRowLayout">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivInviteIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@mipmap/ic"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etInviteCode"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="@null"
|
||||
android:hint="请输入邀请码(非必填)"
|
||||
android:inputType="text"
|
||||
android:maxLength="10"
|
||||
android:paddingVertical="16dp"
|
||||
android:textColor="@android:color/black"
|
||||
android:textColorHint="@color/gray"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivInviteIcon"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- 下一步按钮 -->
|
||||
<android.widget.Button
|
||||
android:id="@+id/btnNext"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="下一步"
|
||||
android:textAllCaps="false"
|
||||
android:textSize="16sp"
|
||||
app:cornerRadius="12dp"
|
||||
android:textColor="@color/white"
|
||||
android:background="@drawable/rounded_blue_bg"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/inviteRowLayout" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
6
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
6
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
BIN
app/src/main/res/mipmap-hdpi/back.png
Normal file
|
After Width: | Height: | Size: 527 B |
BIN
app/src/main/res/mipmap-hdpi/bg_colors.png
Normal file
|
After Width: | Height: | Size: 269 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic.png
Normal file
|
After Width: | Height: | Size: 497 B |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/id_card.png
Normal file
|
After Width: | Height: | Size: 383 B |
BIN
app/src/main/res/mipmap-hdpi/lg.png
Normal file
|
After Width: | Height: | Size: 848 B |
BIN
app/src/main/res/mipmap-hdpi/loge.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
app/src/main/res/mipmap-hdpi/loge1.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/mipmap-hdpi/ma.png
Normal file
|
After Width: | Height: | Size: 591 B |
BIN
app/src/main/res/mipmap-hdpi/vc.png
Normal file
|
After Width: | Height: | Size: 855 B |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 982 B |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
7
app/src/main/res/values-night/themes.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.DefenseApplication" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- Customize your dark theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
|
||||
</style>
|
||||
</resources>
|
||||
10
app/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
<color name="green">#09C2BD </color>
|
||||
<color name="gray">#999999</color>
|
||||
<color name="login_background">#EDF4FF</color>
|
||||
<color name="red">#E34D59</color>
|
||||
|
||||
</resources>
|
||||
3
app/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">DefenseApplication</string>
|
||||
</resources>
|
||||
9
app/src/main/res/values/themes.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.DefenseApplication" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- Customize your light theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
|
||||
</style>
|
||||
|
||||
<style name="Theme.DefenseApplication" parent="Base.Theme.DefenseApplication" />
|
||||
</resources>
|
||||
13
app/src/main/res/xml/backup_rules.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample backup rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/guide/topics/data/autobackup
|
||||
for details.
|
||||
Note: This file is ignored for devices older than API 31
|
||||
See https://developer.android.com/about/versions/12/backup-restore
|
||||
-->
|
||||
<full-backup-content>
|
||||
<!--
|
||||
<include domain="sharedpref" path="."/>
|
||||
<exclude domain="sharedpref" path="device.xml"/>
|
||||
-->
|
||||
</full-backup-content>
|
||||
19
app/src/main/res/xml/data_extraction_rules.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.example.defenseapplication
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||