parent
98e8fdbb33
commit
59f950915a
@ -0,0 +1,15 @@ |
|||||||
|
package xyz.fycz.myreader.base |
||||||
|
|
||||||
|
import android.text.TextWatcher |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2021/12/9 12:32 |
||||||
|
*/ |
||||||
|
abstract class MyTextWatcher : TextWatcher { |
||||||
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { |
||||||
|
} |
||||||
|
|
||||||
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
package xyz.fycz.myreader.model.user |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2021/12/9 10:19 |
||||||
|
*/ |
||||||
|
data class Result( |
||||||
|
val code: Int, |
||||||
|
val result: Any |
||||||
|
) |
@ -0,0 +1,70 @@ |
|||||||
|
package xyz.fycz.myreader.model.user; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/7/12 17:35 |
||||||
|
*/ |
||||||
|
public class User { |
||||||
|
private Integer userId; |
||||||
|
private String userName; |
||||||
|
private String password; |
||||||
|
private String email; |
||||||
|
|
||||||
|
public User() { |
||||||
|
} |
||||||
|
|
||||||
|
public User(String userName) { |
||||||
|
this.userName = userName; |
||||||
|
} |
||||||
|
|
||||||
|
public User(String userName, String password) { |
||||||
|
this.userName = userName; |
||||||
|
this.password = password; |
||||||
|
} |
||||||
|
|
||||||
|
public User(String userName, String password, String email) { |
||||||
|
this.userName = userName; |
||||||
|
this.password = password; |
||||||
|
this.email = email; |
||||||
|
} |
||||||
|
|
||||||
|
public User(Integer userId, String userName, String password, String email) { |
||||||
|
this.userId = userId; |
||||||
|
this.userName = userName; |
||||||
|
this.password = password; |
||||||
|
this.email = email; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public Integer getUserId() { |
||||||
|
return userId; |
||||||
|
} |
||||||
|
|
||||||
|
public String getUserName() { |
||||||
|
return userName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setUserName(String userName) { |
||||||
|
this.userName = userName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPassword() { |
||||||
|
return password; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPassword(String password) { |
||||||
|
this.password = password; |
||||||
|
} |
||||||
|
|
||||||
|
public void setUserId(Integer userId) { |
||||||
|
this.userId = userId; |
||||||
|
} |
||||||
|
|
||||||
|
public String getEmail() { |
||||||
|
return email; |
||||||
|
} |
||||||
|
|
||||||
|
public void setEmail(String email) { |
||||||
|
this.email = email; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,171 @@ |
|||||||
|
package xyz.fycz.myreader.model.user |
||||||
|
|
||||||
|
import io.reactivex.Single |
||||||
|
import io.reactivex.SingleOnSubscribe |
||||||
|
import okhttp3.MediaType |
||||||
|
import okhttp3.RequestBody |
||||||
|
import xyz.fycz.myreader.application.App |
||||||
|
import xyz.fycz.myreader.common.APPCONST |
||||||
|
import xyz.fycz.myreader.common.URLCONST |
||||||
|
import xyz.fycz.myreader.model.storage.Backup |
||||||
|
import xyz.fycz.myreader.model.storage.Restore |
||||||
|
import xyz.fycz.myreader.model.storage.Restore.restore |
||||||
|
import xyz.fycz.myreader.util.* |
||||||
|
import xyz.fycz.myreader.util.utils.FileUtils |
||||||
|
import xyz.fycz.myreader.util.utils.GSON |
||||||
|
import xyz.fycz.myreader.util.utils.OkHttpUtils |
||||||
|
import xyz.fycz.myreader.util.utils.RxUtils |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2021/12/9 10:17 |
||||||
|
*/ |
||||||
|
object UserService2 { |
||||||
|
fun login(user: User): Single<Result> { |
||||||
|
return Single.create(SingleOnSubscribe<Result> { |
||||||
|
val mediaType = MediaType.parse("application/x-www-form-urlencoded") |
||||||
|
val body = "username=${user.userName}" + |
||||||
|
"&password=${user.password}" + |
||||||
|
makeAuth() |
||||||
|
val requestBody = RequestBody.create(mediaType, body) |
||||||
|
val ret = OkHttpUtils.getHtml(URLCONST.USER_URL + "/do/login", requestBody, "UTF-8") |
||||||
|
it.onSuccess(GSON.fromJson(ret, Result::class.java)) |
||||||
|
}).compose { RxUtils.toSimpleSingle(it) } |
||||||
|
} |
||||||
|
|
||||||
|
fun register(user: User, code: String, keyc: String): Single<Result> { |
||||||
|
return Single.create(SingleOnSubscribe<Result> { |
||||||
|
val mediaType = MediaType.parse("application/x-www-form-urlencoded") |
||||||
|
val body = "username=${user.userName}" + |
||||||
|
"&password=${user.password}" + |
||||||
|
"&email=${user.email}" + |
||||||
|
"&code=${code}" + |
||||||
|
"&keyc=${keyc}" + |
||||||
|
"&key=${CyptoUtils.encode(APPCONST.KEY, APPCONST.publicKey)}" + |
||||||
|
makeAuth() |
||||||
|
val requestBody = RequestBody.create(mediaType, body) |
||||||
|
val ret = OkHttpUtils.getHtml(URLCONST.USER_URL + "/do/reg", requestBody, "UTF-8") |
||||||
|
it.onSuccess(GSON.fromJson(ret, Result::class.java)) |
||||||
|
}).compose { RxUtils.toSimpleSingle(it) } |
||||||
|
} |
||||||
|
|
||||||
|
fun bindEmail(user: User, code: String, keyc: String): Single<Result> { |
||||||
|
return Single.create(SingleOnSubscribe<Result> { |
||||||
|
val mediaType = MediaType.parse("application/x-www-form-urlencoded") |
||||||
|
val body = "username=${user.userName}" + |
||||||
|
"&email=${user.email}" + |
||||||
|
"&code=${code}" + |
||||||
|
"&keyc=${keyc}" + |
||||||
|
makeAuth() |
||||||
|
val requestBody = RequestBody.create(mediaType, body) |
||||||
|
val ret = OkHttpUtils.getHtml(URLCONST.USER_URL + "/do/bindEmail", requestBody, "UTF-8") |
||||||
|
it.onSuccess(GSON.fromJson(ret, Result::class.java)) |
||||||
|
}).compose { RxUtils.toSimpleSingle(it) } |
||||||
|
} |
||||||
|
|
||||||
|
fun resetPwd(user: User, code: String, keyc: String): Single<Result> { |
||||||
|
return Single.create(SingleOnSubscribe<Result> { |
||||||
|
val mediaType = MediaType.parse("application/x-www-form-urlencoded") |
||||||
|
val body = "email=${user.email}" + |
||||||
|
"&password=${user.password}" + |
||||||
|
"&code=${code}" + |
||||||
|
"&keyc=${keyc}" + |
||||||
|
makeAuth() |
||||||
|
val requestBody = RequestBody.create(mediaType, body) |
||||||
|
val ret = OkHttpUtils.getHtml(URLCONST.USER_URL + "/do/resetPwd", requestBody, "UTF-8") |
||||||
|
it.onSuccess(GSON.fromJson(ret, Result::class.java)) |
||||||
|
}).compose { RxUtils.toSimpleSingle(it) } |
||||||
|
} |
||||||
|
|
||||||
|
fun sendEmail(email: String, type: String, keyc: String = ""): Single<Result> { |
||||||
|
return Single.create(SingleOnSubscribe<Result> { |
||||||
|
val mediaType = MediaType.parse("application/x-www-form-urlencoded") |
||||||
|
val body = "email=${email}" + |
||||||
|
"&type=${type}" + |
||||||
|
"&keyc=${keyc}" + |
||||||
|
makeAuth() |
||||||
|
val requestBody = RequestBody.create(mediaType, body) |
||||||
|
val ret = OkHttpUtils.getHtml(URLCONST.USER_URL + "/do/sendEmail", requestBody, "UTF-8") |
||||||
|
it.onSuccess(GSON.fromJson(ret, Result::class.java)) |
||||||
|
}).compose { RxUtils.toSimpleSingle(it) } |
||||||
|
} |
||||||
|
|
||||||
|
fun webBackup(user: User): Single<Result> { |
||||||
|
return Single.create(SingleOnSubscribe<Result> { |
||||||
|
Backup.backup(App.getmContext(), APPCONST.FILE_DIR + "webBackup/", |
||||||
|
object : Backup.CallBack { |
||||||
|
override fun backupSuccess() { |
||||||
|
val inputFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup") |
||||||
|
val zipFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup.zip") |
||||||
|
//压缩文件 |
||||||
|
ZipUtils.zipFile(inputFile, zipFile) |
||||||
|
val ret = OkHttpUtils.upload( |
||||||
|
URLCONST.USER_URL + "/do/bak?" + |
||||||
|
"username=${user.userName}" + |
||||||
|
makeAuth(), |
||||||
|
zipFile.absolutePath, |
||||||
|
zipFile.name |
||||||
|
) |
||||||
|
zipFile.delete() |
||||||
|
it.onSuccess(GSON.fromJson(ret, Result::class.java)) |
||||||
|
} |
||||||
|
|
||||||
|
override fun backupError(msg: String) { |
||||||
|
it.onError(Throwable(msg)) |
||||||
|
} |
||||||
|
|
||||||
|
}) |
||||||
|
}).compose { RxUtils.toSimpleSingle(it) } |
||||||
|
} |
||||||
|
|
||||||
|
fun webRestore(user: User): Single<Result> { |
||||||
|
return Single.create(SingleOnSubscribe<Result> { |
||||||
|
val zipFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup.zip") |
||||||
|
val input = OkHttpUtils.getInputStream( |
||||||
|
URLCONST.USER_URL + "/do/ret?" + |
||||||
|
"username=${user.userName}" + |
||||||
|
makeAuth() |
||||||
|
) |
||||||
|
if (FileUtils.writeFile(input.readBytes(), zipFile)) { |
||||||
|
ZipUtils.unzipFile(zipFile.absolutePath, APPCONST.FILE_DIR) |
||||||
|
restore(APPCONST.FILE_DIR + "webBackup/", object : Restore.CallBack { |
||||||
|
override fun restoreSuccess() { |
||||||
|
zipFile.delete() |
||||||
|
it.onSuccess(Result(100, "成功从网络同步到本地")) |
||||||
|
} |
||||||
|
|
||||||
|
override fun restoreError(msg: String) { |
||||||
|
it.onError(Throwable(msg)) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
}).compose { RxUtils.toSimpleSingle(it) } |
||||||
|
} |
||||||
|
|
||||||
|
fun writeConfig(user: User) { |
||||||
|
FileUtils.write(App.getmContext(), "userConfig.fy", GSON.toJson(user)) |
||||||
|
} |
||||||
|
|
||||||
|
fun readConfig(): User? { |
||||||
|
val config = FileUtils.read(App.getmContext(), "userConfig.fy") |
||||||
|
if ("" != config) { |
||||||
|
return GSON.fromJson(config, User::class.java) |
||||||
|
} |
||||||
|
return null |
||||||
|
} |
||||||
|
|
||||||
|
fun writeUsername(username: String) { |
||||||
|
FileUtils.writeText(username, FileUtils.getFile(APPCONST.QQ_DATA_DIR + "user")) |
||||||
|
} |
||||||
|
|
||||||
|
fun readUsername(): String { |
||||||
|
return FileUtils.readText(APPCONST.QQ_DATA_DIR + "user") |
||||||
|
} |
||||||
|
|
||||||
|
private fun makeAuth(): String { |
||||||
|
return "&signal=" + AppInfoUtils.getSingInfo( |
||||||
|
App.getmContext(), |
||||||
|
App.getApplication().packageName, AppInfoUtils.SHA1 |
||||||
|
) + "&appVersion=" + App.getVersionCode() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,225 @@ |
|||||||
|
package xyz.fycz.myreader.ui.activity |
||||||
|
|
||||||
|
import android.app.Activity |
||||||
|
import android.content.Intent |
||||||
|
import android.os.Bundle |
||||||
|
import android.text.Editable |
||||||
|
import android.view.View |
||||||
|
import androidx.appcompat.widget.Toolbar |
||||||
|
import io.reactivex.SingleObserver |
||||||
|
import io.reactivex.disposables.Disposable |
||||||
|
import xyz.fycz.myreader.R |
||||||
|
import xyz.fycz.myreader.application.App |
||||||
|
import xyz.fycz.myreader.base.BaseActivity |
||||||
|
import xyz.fycz.myreader.base.BitIntentDataManager |
||||||
|
import xyz.fycz.myreader.base.MyTextWatcher |
||||||
|
import xyz.fycz.myreader.base.observer.MySingleObserver |
||||||
|
import xyz.fycz.myreader.common.APPCONST |
||||||
|
import xyz.fycz.myreader.databinding.ActivityAuthEmailBinding |
||||||
|
import xyz.fycz.myreader.model.user.Result |
||||||
|
import xyz.fycz.myreader.model.user.User |
||||||
|
import xyz.fycz.myreader.model.user.UserService2 |
||||||
|
import xyz.fycz.myreader.model.user.UserService2.bindEmail |
||||||
|
import xyz.fycz.myreader.model.user.UserService2.register |
||||||
|
import xyz.fycz.myreader.model.user.UserService2.resetPwd |
||||||
|
import xyz.fycz.myreader.model.user.UserService2.sendEmail |
||||||
|
import xyz.fycz.myreader.model.user.UserService2.writeUsername |
||||||
|
import xyz.fycz.myreader.ui.dialog.DialogCreator |
||||||
|
import xyz.fycz.myreader.ui.dialog.LoadingDialog |
||||||
|
import xyz.fycz.myreader.util.CyptoUtils |
||||||
|
import xyz.fycz.myreader.util.ToastUtils |
||||||
|
import java.util.* |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2021/12/9 15:20 |
||||||
|
*/ |
||||||
|
class AuthEmailActivity : BaseActivity(), SingleObserver<Result> { |
||||||
|
|
||||||
|
private lateinit var binding: ActivityAuthEmailBinding |
||||||
|
private var email = "" |
||||||
|
private var password = "" |
||||||
|
private var emailCode = "" |
||||||
|
private var keyc = "" |
||||||
|
private lateinit var dialog: LoadingDialog |
||||||
|
private var disp: Disposable? = null |
||||||
|
private lateinit var operator: String |
||||||
|
private var user: User? = null |
||||||
|
private var isBind: Boolean = false |
||||||
|
override fun bindView() { |
||||||
|
binding = ActivityAuthEmailBinding.inflate(layoutInflater) |
||||||
|
setContentView(binding.root) |
||||||
|
} |
||||||
|
|
||||||
|
override fun initData(savedInstanceState: Bundle?) { |
||||||
|
user = BitIntentDataManager.getInstance().getData(intent) as User? |
||||||
|
isBind = user != null |
||||||
|
operator = if (isBind) "绑定邮箱" else "重置密码" |
||||||
|
dialog = LoadingDialog(this, "正在请求") { |
||||||
|
disp?.dispose() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun setUpToolbar(toolbar: Toolbar?) { |
||||||
|
super.setUpToolbar(toolbar) |
||||||
|
setStatusBarColor(R.color.colorPrimary, true) |
||||||
|
supportActionBar?.title = operator |
||||||
|
} |
||||||
|
|
||||||
|
override fun initWidget() { |
||||||
|
binding.tvTitle.text = operator |
||||||
|
binding.btSubmit.text = operator |
||||||
|
binding.etEmail.editText?.addTextChangedListener(object : MyTextWatcher() { |
||||||
|
override fun afterTextChanged(s: Editable) { |
||||||
|
email = s.toString() |
||||||
|
if (!email.matches("^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,})$".toRegex())) { |
||||||
|
showTip("邮箱格式错误") |
||||||
|
} else { |
||||||
|
binding.tvRegisterTip.visibility = View.GONE |
||||||
|
} |
||||||
|
checkNotNone() |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
binding.etEmailCode.editText?.addTextChangedListener(object : MyTextWatcher() { |
||||||
|
override fun afterTextChanged(s: Editable) { |
||||||
|
emailCode = s.toString().trim() |
||||||
|
checkNotNone() |
||||||
|
} |
||||||
|
}) |
||||||
|
binding.etPassword.editText!!.addTextChangedListener(object : MyTextWatcher() { |
||||||
|
override fun afterTextChanged(s: Editable) { |
||||||
|
password = s.toString() |
||||||
|
if (password.length < 8 || password.length > 16) { |
||||||
|
showTip("密码必须在8-16位之间") |
||||||
|
} else if (password.matches("^\\d+$".toRegex())) { |
||||||
|
showTip("密码不能是纯数字") |
||||||
|
} else { |
||||||
|
binding.tvRegisterTip.visibility = View.GONE |
||||||
|
} |
||||||
|
checkNotNone() |
||||||
|
} |
||||||
|
}) |
||||||
|
if (!isBind) { |
||||||
|
binding.etPassword.visibility = View.VISIBLE |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun initClick() { |
||||||
|
binding.tvGetEmailCode.setOnClickListener { |
||||||
|
if (!email.matches("^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,})$".toRegex())) { |
||||||
|
ToastUtils.showWarring("请正确输入邮箱") |
||||||
|
return@setOnClickListener |
||||||
|
} |
||||||
|
dialog.show() |
||||||
|
dialog.setmMessage("正在发送") |
||||||
|
sendEmail(email, if (isBind) "bind" else "auth", keyc) |
||||||
|
.subscribe(object : MySingleObserver<Result?>() { |
||||||
|
override fun onSubscribe(d: Disposable) { |
||||||
|
addDisposable(d) |
||||||
|
disp = d |
||||||
|
} |
||||||
|
|
||||||
|
override fun onSuccess(result: Result) { |
||||||
|
if (result.code == 106) { |
||||||
|
ToastUtils.showSuccess("验证码发送成功") |
||||||
|
keyc = result.result.toString() |
||||||
|
timeDown(60) |
||||||
|
} else { |
||||||
|
ToastUtils.showWarring(result.result.toString()) |
||||||
|
} |
||||||
|
dialog.dismiss() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onError(e: Throwable) { |
||||||
|
ToastUtils.showError("验证码发送失败:${e.localizedMessage}") |
||||||
|
dialog.dismiss() |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
binding.btSubmit.setOnClickListener { |
||||||
|
if (!isBind && (password.matches("^\\d+$".toRegex()) || !password.matches("^.{8,16}$".toRegex()))) { |
||||||
|
DialogCreator.createTipDialog( |
||||||
|
this, "密码格式错误", |
||||||
|
"密码必须在8-16位之间\n密码不能是纯数字" |
||||||
|
) |
||||||
|
} else if (!email.matches("^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,})$".toRegex())) { |
||||||
|
DialogCreator.createTipDialog( |
||||||
|
this, "邮箱格式错误", |
||||||
|
"电子邮箱的正确写法为:用户名@邮箱网站.com(.cn等)" |
||||||
|
) |
||||||
|
} else if ("" == keyc) { |
||||||
|
DialogCreator.createTipDialog(this, "请先获取邮箱验证码") |
||||||
|
} else if (emailCode.length < 6) { |
||||||
|
DialogCreator.createTipDialog(this, "请输入6位邮箱验证码") |
||||||
|
} else { |
||||||
|
dialog.show() |
||||||
|
dialog.setmMessage("正在请求") |
||||||
|
if (isBind) { |
||||||
|
val user = User().apply { |
||||||
|
email = this@AuthEmailActivity.email |
||||||
|
userName = this@AuthEmailActivity.user?.userName |
||||||
|
} |
||||||
|
bindEmail(user, emailCode, keyc) |
||||||
|
.subscribe(this) |
||||||
|
} else { |
||||||
|
val user = User().apply { |
||||||
|
email = this@AuthEmailActivity.email |
||||||
|
password = CyptoUtils.encode(APPCONST.KEY, this@AuthEmailActivity.password) |
||||||
|
} |
||||||
|
resetPwd(user, emailCode, keyc) |
||||||
|
.subscribe(this) |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fun showTip(tip: String?) { |
||||||
|
binding.tvRegisterTip.visibility = View.VISIBLE |
||||||
|
binding.tvRegisterTip.text = tip |
||||||
|
} |
||||||
|
|
||||||
|
private fun timeDown(time: Int) { |
||||||
|
if (time == 0) { |
||||||
|
binding.tvGetEmailCode.text = getString(R.string.re_get_email_code, "") |
||||||
|
binding.tvGetEmailCode.isEnabled = true |
||||||
|
} else { |
||||||
|
binding.tvGetEmailCode.isEnabled = false |
||||||
|
val timeStr = "($time)" |
||||||
|
binding.tvGetEmailCode.text = getString(R.string.re_get_email_code, timeStr) |
||||||
|
App.getHandler().postDelayed({ timeDown(time - 1) }, 1000) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fun checkNotNone() { |
||||||
|
binding.btSubmit.isEnabled = "" != email && "" != emailCode && (isBind || "" != password) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onDestroy() { |
||||||
|
dialog.dismiss() |
||||||
|
super.onDestroy() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onSubscribe(d: Disposable) { |
||||||
|
addDisposable(d) |
||||||
|
disp = d |
||||||
|
} |
||||||
|
|
||||||
|
override fun onSuccess(result: Result) { |
||||||
|
if (result.code < 200) { |
||||||
|
ToastUtils.showSuccess(result.result.toString()) |
||||||
|
setResult(Activity.RESULT_OK) |
||||||
|
finish() |
||||||
|
} else { |
||||||
|
ToastUtils.showWarring(result.result.toString()) |
||||||
|
} |
||||||
|
dialog.dismiss() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onError(e: Throwable) { |
||||||
|
ToastUtils.showError("失败:${e.localizedMessage}") |
||||||
|
dialog.dismiss() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
|
<item android:color="@color/textSecondary" android:state_enabled="false" /> |
||||||
|
<item android:color="@color/sys_color"/> |
||||||
|
</selector> |
Before Width: | Height: | Size: 134 KiB |
@ -0,0 +1,125 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<LinearLayout 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:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:fitsSystemWindows="true" |
||||||
|
android:orientation="vertical"> |
||||||
|
|
||||||
|
<include layout="@layout/toolbar" /> |
||||||
|
|
||||||
|
|
||||||
|
<!--添加标题和输入框--> |
||||||
|
<LinearLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_margin="10dp" |
||||||
|
android:orientation="vertical" |
||||||
|
android:padding="10dp"> |
||||||
|
|
||||||
|
<!--标题--> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/tv_title" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:text="@string/text_register" |
||||||
|
android:textAlignment="center" |
||||||
|
android:textColor="@color/textPrimary" |
||||||
|
android:textSize="@dimen/text_senior_size" /> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/tv_register_tip" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_marginTop="10dp" |
||||||
|
android:text="" |
||||||
|
android:textColor="@color/textError" |
||||||
|
android:visibility="gone" /> |
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout |
||||||
|
android:id="@+id/et_email" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:drawablePadding="10dp" |
||||||
|
app:counterEnabled="true" |
||||||
|
app:counterMaxLength="100"> |
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:hint="@string/et_email" |
||||||
|
android:inputType="text" /> |
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout> |
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout |
||||||
|
android:id="@+id/et_password" |
||||||
|
android:visibility="gone" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:drawablePadding="10dp" |
||||||
|
app:counterEnabled="true" |
||||||
|
app:counterMaxLength="16" |
||||||
|
app:passwordToggleEnabled="true" |
||||||
|
app:passwordToggleTintMode="src_in"> |
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:hint="@string/et_new_password_tip" |
||||||
|
android:inputType="textPassword" /> |
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:orientation="horizontal"> |
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout |
||||||
|
android:id="@+id/et_email_code" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_weight="1" |
||||||
|
android:drawablePadding="10dp" |
||||||
|
app:counterEnabled="true" |
||||||
|
app:counterMaxLength="6"> |
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:hint="@string/et_email_captcha" |
||||||
|
android:inputType="text" /> |
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/tv_get_email_code" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:layout_weight="2.5" |
||||||
|
android:gravity="center" |
||||||
|
android:text="@string/get_email_code" |
||||||
|
android:textColor="@color/selector_get_emali_code" |
||||||
|
android:textSize="@dimen/text_small_size" /> |
||||||
|
|
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<!--登录按钮--> |
||||||
|
<Button |
||||||
|
android:id="@+id/bt_submit" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="50dp" |
||||||
|
android:layout_marginTop="10dp" |
||||||
|
android:background="@drawable/login_btn_selector" |
||||||
|
android:enabled="false" |
||||||
|
android:text="@string/text_register" |
||||||
|
android:textAlignment="center" |
||||||
|
android:textColor="#ffffff" |
||||||
|
android:textSize="@dimen/text_large_size" /> |
||||||
|
|
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -1,241 +1,133 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
xmlns:app="http://schemas.android.com/apk/res-auto" |
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||||
|
xmlns:tools="http://schemas.android.com/tools" |
||||||
android:layout_width="match_parent" |
android:layout_width="match_parent" |
||||||
android:layout_height="match_parent" |
android:layout_height="match_parent" |
||||||
|
android:background="@color/colorBackground" |
||||||
android:fitsSystemWindows="true" |
android:fitsSystemWindows="true" |
||||||
android:orientation="vertical"> |
android:orientation="vertical"> |
||||||
|
|
||||||
<include layout="@layout/toolbar" /> |
<include layout="@layout/toolbar" /> |
||||||
|
|
||||||
<RelativeLayout |
<!--添加标题和输入框--> |
||||||
|
<LinearLayout |
||||||
android:layout_width="match_parent" |
android:layout_width="match_parent" |
||||||
android:layout_height="match_parent"> |
android:layout_height="wrap_content" |
||||||
<!--背景图片--> |
android:layout_margin="10dp" |
||||||
<ImageView |
android:orientation="vertical" |
||||||
android:layout_width="match_parent" |
android:padding="10dp"> |
||||||
android:layout_height="match_parent" |
|
||||||
android:scaleType="fitXY" |
|
||||||
app:srcCompat="@drawable/bg_login" /> |
|
||||||
<!--添加虚化层--> |
|
||||||
<io.alterac.blurkit.BlurLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="match_parent" |
|
||||||
app:blk_blurRadius="5" |
|
||||||
app:blk_fps="0" /> |
|
||||||
|
|
||||||
<!-- 猫头鹰--> |
|
||||||
<!-- <RelativeLayout--> |
|
||||||
<!-- android:layout_width="300dp"--> |
|
||||||
<!-- android:layout_height="200dp"--> |
|
||||||
<!-- android:layout_centerHorizontal="true"--> |
|
||||||
<!-- android:layout_alignTop="@+id/bg"--> |
|
||||||
<!-- android:layout_marginTop="-75dp">--> |
|
||||||
|
|
||||||
<!-- <!–头像–>--> |
|
||||||
<!-- <ImageView--> |
|
||||||
<!-- android:id="@+id/iv_head"--> |
|
||||||
<!-- android:layout_width="wrap_content"--> |
|
||||||
<!-- android:layout_height="wrap_content"--> |
|
||||||
<!-- android:src="@drawable/owl_head"--> |
|
||||||
<!-- android:layout_centerHorizontal="true"--> |
|
||||||
<!-- />--> |
|
||||||
|
|
||||||
<!-- <!–手掌–>--> |
|
||||||
<!-- <ImageView--> |
|
||||||
<!-- android:id="@+id/iv_left_hand"--> |
|
||||||
<!-- android:layout_width="50dp"--> |
|
||||||
<!-- android:layout_height="60dp"--> |
|
||||||
<!-- android:src="@drawable/icon_hand"--> |
|
||||||
<!-- android:layout_alignParentLeft="true"--> |
|
||||||
<!-- android:layout_alignBottom="@+id/iv_head"--> |
|
||||||
<!-- android:layout_marginBottom="-25dp"--> |
|
||||||
<!-- android:layout_marginLeft="10dp"/>--> |
|
||||||
<!-- <ImageView--> |
|
||||||
<!-- android:id="@+id/iv_right_hand"--> |
|
||||||
<!-- android:layout_width="50dp"--> |
|
||||||
<!-- android:layout_height="60dp"--> |
|
||||||
<!-- android:src="@drawable/icon_hand"--> |
|
||||||
<!-- android:layout_alignParentRight="true"--> |
|
||||||
<!-- android:layout_alignBottom="@+id/iv_head"--> |
|
||||||
<!-- android:layout_marginBottom="-25dp"--> |
|
||||||
<!-- android:layout_marginRight="10dp"/>--> |
|
||||||
|
|
||||||
<!-- <!–翅膀–>--> |
|
||||||
<!-- <ImageView--> |
|
||||||
<!-- android:id="@+id/iv_left_arm"--> |
|
||||||
<!-- android:layout_width="65dp"--> |
|
||||||
<!-- android:layout_height="40dp"--> |
|
||||||
<!-- android:src="@drawable/arm_left"--> |
|
||||||
<!-- android:layout_below="@+id/iv_head"--> |
|
||||||
<!-- android:layout_alignParentLeft="true"--> |
|
||||||
<!-- android:layout_marginLeft="20dp"/>--> |
|
||||||
|
|
||||||
<!-- <ImageView--> |
|
||||||
<!-- android:id="@+id/iv_right_arm"--> |
|
||||||
<!-- android:layout_width="65dp"--> |
|
||||||
<!-- android:layout_height="40dp"--> |
|
||||||
<!-- android:src="@drawable/arm_right"--> |
|
||||||
<!-- android:layout_below="@+id/iv_head"--> |
|
||||||
<!-- android:layout_alignParentRight="true"--> |
|
||||||
<!-- android:layout_marginRight="20dp"/>--> |
|
||||||
<!-- </RelativeLayout>--> |
|
||||||
|
|
||||||
<View |
|
||||||
android:id="@+id/bg" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="280dp" |
|
||||||
android:layout_centerInParent="true" |
|
||||||
android:layout_marginLeft="20dp" |
|
||||||
android:layout_marginRight="20dp" |
|
||||||
android:background="@drawable/input_bg_shape" /> |
|
||||||
|
|
||||||
<io.alterac.blurkit.BlurLayout |
<!--标题--> |
||||||
|
<TextView |
||||||
android:layout_width="match_parent" |
android:layout_width="match_parent" |
||||||
android:layout_height="280dp" |
android:layout_height="wrap_content" |
||||||
android:layout_centerInParent="true" |
android:text="@string/text_login" |
||||||
android:layout_marginLeft="20dp" |
android:textAlignment="center" |
||||||
android:layout_marginRight="20dp" |
android:textColor="@color/textPrimary" |
||||||
app:blk_blurRadius="20" |
android:textSize="@dimen/text_senior_size" /> |
||||||
app:blk_fps="0" /> |
|
||||||
|
<com.google.android.material.textfield.TextInputLayout |
||||||
<!--添加标题和输入框--> |
android:id="@+id/et_user" |
||||||
<LinearLayout |
|
||||||
android:layout_width="match_parent" |
android:layout_width="match_parent" |
||||||
android:layout_height="wrap_content" |
android:layout_height="wrap_content" |
||||||
android:layout_centerInParent="true" |
android:layout_marginTop="20dp" |
||||||
android:layout_marginLeft="20dp" |
android:drawablePadding="10dp" |
||||||
android:layout_marginRight="20dp" |
app:counterEnabled="true" |
||||||
android:orientation="vertical" |
app:counterMaxLength="14"> |
||||||
android:padding="20dp"> |
|
||||||
|
|
||||||
<!--标题--> |
<com.google.android.material.textfield.TextInputEditText |
||||||
<TextView |
|
||||||
android:layout_width="match_parent" |
android:layout_width="match_parent" |
||||||
android:layout_height="wrap_content" |
android:layout_height="wrap_content" |
||||||
android:text="@string/text_login" |
|
||||||
android:textAlignment="center" |
|
||||||
android:textColor="@color/textSecondary" |
|
||||||
android:textSize="20dp" /> |
|
||||||
|
|
||||||
<!--添加输入框--> |
|
||||||
<!--<EditText |
|
||||||
android:id="@+id/et_user" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="50dp" |
|
||||||
android:background="@drawable/editview_shape" |
|
||||||
android:drawableStart="@drawable/iconfont_user" |
|
||||||
android:drawablePadding="10dp" |
|
||||||
android:hint="@string/et_account_tip" |
android:hint="@string/et_account_tip" |
||||||
android:inputType="text" |
android:inputType="text" /> |
||||||
android:maxLines="1" |
|
||||||
android:paddingStart="10dp" |
|
||||||
android:textSize="18dp" />--> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout |
</com.google.android.material.textfield.TextInputLayout> |
||||||
android:id="@+id/et_user" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginTop="20dp" |
|
||||||
android:drawablePadding="10dp" |
|
||||||
app:counterEnabled="true" |
|
||||||
app:counterMaxLength="14"> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText |
<com.google.android.material.textfield.TextInputLayout |
||||||
android:layout_width="match_parent" |
android:id="@+id/et_password" |
||||||
android:layout_height="wrap_content" |
android:layout_width="match_parent" |
||||||
android:hint="@string/et_account_tip" |
android:layout_height="wrap_content" |
||||||
android:inputType="text"/> |
android:drawablePadding="10dp" |
||||||
|
app:counterEnabled="true" |
||||||
|
app:counterMaxLength="16" |
||||||
|
app:passwordToggleEnabled="true" |
||||||
|
app:passwordToggleTintMode="src_in"> |
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout> |
<com.google.android.material.textfield.TextInputEditText |
||||||
<!--<EditText |
android:layout_width="match_parent" |
||||||
android:id="@+id/et_password" |
android:layout_height="wrap_content" |
||||||
style="@style/EditTextStyle" |
|
||||||
android:background="@drawable/editview_shape" |
|
||||||
android:drawableStart="@drawable/iconfont_password" |
|
||||||
android:hint="@string/et_password_tip" |
android:hint="@string/et_password_tip" |
||||||
android:inputType="textPassword" |
android:inputType="textPassword" /> |
||||||
android:textSize="18dp" />--> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout |
</com.google.android.material.textfield.TextInputLayout> |
||||||
android:id="@+id/et_password" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:drawablePadding="10dp" |
|
||||||
app:counterEnabled="true" |
|
||||||
app:counterMaxLength="16" |
|
||||||
app:passwordToggleEnabled="true" |
|
||||||
app:passwordToggleTintMode="src_in"> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText |
<LinearLayout |
||||||
android:layout_width="match_parent" |
android:layout_width="match_parent" |
||||||
android:layout_height="wrap_content" |
android:layout_height="wrap_content" |
||||||
android:hint="@string/et_password_tip" |
android:orientation="horizontal"> |
||||||
android:inputType="textPassword"/> |
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout> |
<com.google.android.material.textfield.TextInputLayout |
||||||
<LinearLayout |
android:id="@+id/et_captcha" |
||||||
android:layout_width="match_parent" |
android:layout_width="match_parent" |
||||||
android:layout_height="wrap_content" |
android:layout_height="wrap_content" |
||||||
android:orientation="horizontal"> |
android:layout_weight="1" |
||||||
|
android:drawablePadding="10dp" |
||||||
|
app:counterEnabled="true" |
||||||
|
app:counterMaxLength="4"> |
||||||
|
|
||||||
<!--<EditText |
<com.google.android.material.textfield.TextInputEditText |
||||||
android:id="@+id/et_captcha" |
|
||||||
style="@style/EditTextStyle" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_weight="1" |
|
||||||
android:background="@drawable/editview_shape" |
|
||||||
android:hint="@string/et_rp_captcha" |
|
||||||
android:inputType="text" |
|
||||||
android:textSize="18dp" />--> |
|
||||||
<com.google.android.material.textfield.TextInputLayout |
|
||||||
android:id="@+id/et_captcha" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_weight="1" |
|
||||||
android:drawablePadding="10dp" |
|
||||||
app:counterEnabled="true" |
|
||||||
app:counterMaxLength="4"> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:hint="@string/et_rp_captcha" |
|
||||||
android:inputType="text"/> |
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout> |
|
||||||
|
|
||||||
<ImageView |
|
||||||
android:id="@+id/iv_captcha" |
|
||||||
android:layout_width="match_parent" |
android:layout_width="match_parent" |
||||||
android:layout_height="wrap_content" |
android:layout_height="wrap_content" |
||||||
android:layout_weight="3" |
android:hint="@string/et_rp_captcha" |
||||||
android:layout_gravity="center_vertical" |
android:inputType="text" /> |
||||||
android:paddingStart="7dp" /> |
|
||||||
|
</com.google.android.material.textfield.TextInputLayout> |
||||||
</LinearLayout> |
|
||||||
<!--登录按钮--> |
<ImageView |
||||||
<Button |
android:id="@+id/iv_captcha" |
||||||
android:id="@+id/bt_login" |
|
||||||
android:layout_width="match_parent" |
android:layout_width="match_parent" |
||||||
android:layout_height="50dp" |
android:layout_height="wrap_content" |
||||||
android:layout_marginTop="20dp" |
android:layout_gravity="center_vertical" |
||||||
android:background="@drawable/login_btn_selector" |
android:layout_weight="2" |
||||||
android:enabled="false" |
android:paddingStart="7dp" |
||||||
android:text="@string/text_login" |
tools:ignore="RtlSymmetry" /> |
||||||
android:textAlignment="center" |
|
||||||
android:textColor="@color/textPrimaryInverted" |
</LinearLayout> |
||||||
android:textSize="25dp" /> |
<!--登录按钮--> |
||||||
|
<Button |
||||||
|
android:id="@+id/bt_login" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="45dp" |
||||||
|
android:layout_marginTop="20dp" |
||||||
|
android:background="@drawable/login_btn_selector" |
||||||
|
android:enabled="false" |
||||||
|
android:text="@string/text_login" |
||||||
|
android:textAlignment="center" |
||||||
|
android:textColor="@color/textPrimaryInverted" |
||||||
|
android:textSize="@dimen/text_large_size" /> |
||||||
|
|
||||||
|
<RelativeLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
|
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_marginTop="10dp"> |
||||||
|
|
||||||
<TextView |
<TextView |
||||||
android:id="@+id/tv_register" |
android:id="@+id/tv_register" |
||||||
android:layout_width="wrap_content" |
android:layout_width="wrap_content" |
||||||
android:layout_height="wrap_content" |
android:layout_height="wrap_content" |
||||||
android:layout_marginTop="10dp" |
|
||||||
android:text="@string/tv_register" |
android:text="@string/tv_register" |
||||||
android:textColor="@color/colorAccent" /> |
android:textColor="@color/colorAccent" /> |
||||||
</LinearLayout> |
|
||||||
</RelativeLayout> |
|
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/tv_forgot_pwd" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_alignParentEnd="true" |
||||||
|
android:text="@string/tv_forget_pwd" |
||||||
|
android:textColor="@color/colorAccent" /> |
||||||
|
</RelativeLayout> |
||||||
|
|
||||||
|
</LinearLayout> |
||||||
</LinearLayout> |
</LinearLayout> |
@ -1,3 +1,3 @@ |
|||||||
#Fri Jun 18 21:45:31 CST 2021 |
#Fri Jun 18 21:45:31 CST 2021 |
||||||
VERSION_CODE=226 |
VERSION_CODE=227 |
||||||
NEED_CREATE_RELEASE=false |
NEED_CREATE_RELEASE=false |
||||||
|
Loading…
Reference in new issue