Browse Source
初始化OxFace登录Android项目
初始化OxFace登录Android项目
- 添加基础项目结构和配置文件 - 实现简洁的Material Design登录界面 - 包含用户名和密码输入功能 - 支持界面滚动适配不同屏幕尺寸 - 使用绿色主题色 #009874 - 配置Gradle构建系统和依赖管理main
commit
2b9336a09e
25 changed files with 914 additions and 0 deletions
-
146.gitignore
-
41app/build.gradle
-
21app/proguard-rules.pro
-
26app/src/main/AndroidManifest.xml
-
79app/src/main/java/com/example/oxfacelogin/MainActivity.java
-
11app/src/main/res/drawable/ic_launcher_background.xml
-
15app/src/main/res/drawable/ic_launcher_foreground.xml
-
10app/src/main/res/drawable/ic_lock.xml
-
10app/src/main/res/drawable/ic_login_logo.xml
-
10app/src/main/res/drawable/ic_person.xml
-
153app/src/main/res/layout/activity_main.xml
-
5app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
-
5app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
-
16app/src/main/res/values-night/themes.xml
-
31app/src/main/res/values/colors.xml
-
5app/src/main/res/values/dimens.xml
-
14app/src/main/res/values/strings.xml
-
34app/src/main/res/values/themes.xml
-
12app/src/main/res/xml/backup_rules.xml
-
19app/src/main/res/xml/data_extraction_rules.xml
-
16build.gradle
-
28gradle.properties
-
5gradle/wrapper/gradle-wrapper.properties
-
185gradlew
-
17settings.gradle
@ -0,0 +1,146 @@ |
|||||
|
# Built application files |
||||
|
*.apk |
||||
|
*.aar |
||||
|
*.ap_ |
||||
|
*.aab |
||||
|
|
||||
|
# Files for the ART/Dalvik VM |
||||
|
*.dex |
||||
|
|
||||
|
# Java class files |
||||
|
*.class |
||||
|
|
||||
|
# Generated files |
||||
|
bin/ |
||||
|
gen/ |
||||
|
out/ |
||||
|
# Uncomment the following line in case you need and you don't have the release build type files in your app |
||||
|
# release/ |
||||
|
|
||||
|
# Gradle files |
||||
|
.gradle/ |
||||
|
build/ |
||||
|
|
||||
|
# Local configuration file (sdk path, etc) |
||||
|
local.properties |
||||
|
|
||||
|
# Proguard folder generated by Eclipse |
||||
|
proguard/ |
||||
|
|
||||
|
# Log Files |
||||
|
*.log |
||||
|
|
||||
|
# Android Studio Navigation editor temp files |
||||
|
.navigation/ |
||||
|
|
||||
|
# Android Studio captures folder |
||||
|
captures/ |
||||
|
|
||||
|
# IntelliJ |
||||
|
*.iml |
||||
|
.idea/workspace.xml |
||||
|
.idea/tasks.xml |
||||
|
.idea/gradle.xml |
||||
|
.idea/assetWizardSettings.xml |
||||
|
.idea/dictionaries |
||||
|
.idea/libraries |
||||
|
# Android Studio 3 in .gitignore file. |
||||
|
.idea/caches |
||||
|
.idea/modules.xml |
||||
|
# Comment next line if keeping position of elements in Navigation Editor is relevant for you |
||||
|
.idea/navEditor.xml |
||||
|
|
||||
|
# Keystore files |
||||
|
# Uncomment the following lines if you do not want to check your keystore files in. |
||||
|
#*.jks |
||||
|
#*.keystore |
||||
|
|
||||
|
# External native build folder generated in Android Studio 2.2 and later |
||||
|
.externalNativeBuild |
||||
|
.cxx/ |
||||
|
|
||||
|
# Google Services (e.g. APIs or Firebase) |
||||
|
# google-services.json |
||||
|
|
||||
|
# Freeline |
||||
|
freeline.py |
||||
|
freeline/ |
||||
|
freeline_project_description.json |
||||
|
|
||||
|
# fastlane |
||||
|
fastlane/report.xml |
||||
|
fastlane/Preview.html |
||||
|
fastlane/screenshots |
||||
|
fastlane/test_output |
||||
|
fastlane/readme.md |
||||
|
|
||||
|
# Version control |
||||
|
vcs.xml |
||||
|
|
||||
|
# lint |
||||
|
lint/intermediates/ |
||||
|
lint/generated/ |
||||
|
lint/outputs/ |
||||
|
lint/tmp/ |
||||
|
# lint/reports/ |
||||
|
|
||||
|
# Android Profiling |
||||
|
*.hprof |
||||
|
|
||||
|
# IDEs |
||||
|
*~ |
||||
|
*.swp |
||||
|
*.swo |
||||
|
|
||||
|
# OS generated files |
||||
|
.DS_Store |
||||
|
.DS_Store? |
||||
|
._* |
||||
|
.Spotlight-V100 |
||||
|
.Trashes |
||||
|
ehthumbs.db |
||||
|
Thumbs.db |
||||
|
|
||||
|
# Gradle Wrapper |
||||
|
# Uncomment the following line if you want to exclude gradle wrapper |
||||
|
# gradle/wrapper/gradle-wrapper.jar |
||||
|
|
||||
|
# Local Gradle daemon address |
||||
|
.gradle/daemon/ |
||||
|
|
||||
|
# NDK |
||||
|
obj/ |
||||
|
|
||||
|
# Backup files |
||||
|
*~ |
||||
|
|
||||
|
# Temporary files |
||||
|
*.tmp |
||||
|
*.temp |
||||
|
|
||||
|
# Package Files |
||||
|
*.jar |
||||
|
*.war |
||||
|
*.ear |
||||
|
|
||||
|
# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) |
||||
|
hs_err_pid* |
||||
|
|
||||
|
# Crashlytics generated file |
||||
|
crashlytics-build.properties |
||||
|
|
||||
|
# Fabric plugin |
||||
|
com_crashlytics_export_strings.xml |
||||
|
crashlytics.properties |
||||
|
fabric.properties |
||||
|
|
||||
|
# Editor-based Rest Client |
||||
|
.idea/httpRequests |
||||
|
|
||||
|
# Android Profiling |
||||
|
*.hprof |
||||
|
|
||||
|
# Test output |
||||
|
test-results/ |
||||
|
test-reports/ |
||||
|
coverage-results/ |
@ -0,0 +1,41 @@ |
|||||
|
plugins { |
||||
|
id 'com.android.application' |
||||
|
} |
||||
|
|
||||
|
android { |
||||
|
namespace 'com.example.oxfacelogin' |
||||
|
compileSdk 35 |
||||
|
buildToolsVersion "35.0.0" |
||||
|
|
||||
|
defaultConfig { |
||||
|
applicationId "com.example.oxfacelogin" |
||||
|
minSdk 21 |
||||
|
targetSdk 35 |
||||
|
versionCode 1 |
||||
|
versionName "1.0" |
||||
|
|
||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" |
||||
|
} |
||||
|
|
||||
|
buildTypes { |
||||
|
release { |
||||
|
minifyEnabled false |
||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
compileOptions { |
||||
|
sourceCompatibility JavaVersion.VERSION_1_8 |
||||
|
targetCompatibility JavaVersion.VERSION_1_8 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
dependencies { |
||||
|
implementation 'androidx.appcompat:appcompat:1.6.1' |
||||
|
implementation 'com.google.android.material:material:1.10.0' |
||||
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' |
||||
|
|
||||
|
testImplementation 'junit:junit:4.13.2' |
||||
|
androidTestImplementation 'androidx.test.ext:junit:1.1.5' |
||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
# Add project specific ProGuard rules here. |
||||
|
# You can control the set of applied configuration files using the |
||||
|
# proguardFiles setting in build.gradle. |
||||
|
# |
||||
|
# For more details, see |
||||
|
# http://developer.android.com/guide/developing/tools/proguard.html |
||||
|
|
||||
|
# If your project uses WebView with JS, uncomment the following |
||||
|
# and specify the fully qualified class name to the JavaScript interface |
||||
|
# class: |
||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { |
||||
|
# public *; |
||||
|
#} |
||||
|
|
||||
|
# Uncomment this to preserve the line number information for |
||||
|
# debugging stack traces. |
||||
|
#-keepattributes SourceFile,LineNumberTable |
||||
|
|
||||
|
# If you keep the line number information, uncomment this to |
||||
|
# hide the original source file name. |
||||
|
#-renamesourcefileattribute SourceFile |
@ -0,0 +1,26 @@ |
|||||
|
<?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.OxFaceLogin" |
||||
|
tools:targetApi="31"> |
||||
|
<activity |
||||
|
android:name=".MainActivity" |
||||
|
android:exported="true" |
||||
|
android:theme="@style/Theme.OxFaceLogin"> |
||||
|
<intent-filter> |
||||
|
<action android:name="android.intent.action.MAIN" /> |
||||
|
<category android:name="android.intent.category.LAUNCHER" /> |
||||
|
</intent-filter> |
||||
|
</activity> |
||||
|
</application> |
||||
|
|
||||
|
</manifest> |
@ -0,0 +1,79 @@ |
|||||
|
package com.example.oxfacelogin; |
||||
|
|
||||
|
import androidx.appcompat.app.AppCompatActivity; |
||||
|
import android.os.Bundle; |
||||
|
import android.view.View; |
||||
|
import android.widget.Button; |
||||
|
import android.widget.EditText; |
||||
|
import android.widget.Toast; |
||||
|
|
||||
|
public class MainActivity extends AppCompatActivity { |
||||
|
|
||||
|
private EditText editTextUsername; |
||||
|
private EditText editTextPassword; |
||||
|
private Button buttonLogin; |
||||
|
|
||||
|
@Override |
||||
|
protected void onCreate(Bundle savedInstanceState) { |
||||
|
super.onCreate(savedInstanceState); |
||||
|
setContentView(R.layout.activity_main); |
||||
|
|
||||
|
// 初始化视图组件 |
||||
|
initViews(); |
||||
|
|
||||
|
// 设置登录按钮点击事件 |
||||
|
setupLoginButton(); |
||||
|
} |
||||
|
|
||||
|
private void initViews() { |
||||
|
editTextUsername = findViewById(R.id.editTextUsername); |
||||
|
editTextPassword = findViewById(R.id.editTextPassword); |
||||
|
buttonLogin = findViewById(R.id.buttonLogin); |
||||
|
} |
||||
|
|
||||
|
private void setupLoginButton() { |
||||
|
buttonLogin.setOnClickListener(new View.OnClickListener() { |
||||
|
@Override |
||||
|
public void onClick(View v) { |
||||
|
String username = editTextUsername.getText().toString().trim(); |
||||
|
String password = editTextPassword.getText().toString().trim(); |
||||
|
|
||||
|
if (validateInput(username, password)) { |
||||
|
performLogin(username, password); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private boolean validateInput(String username, String password) { |
||||
|
if (username.isEmpty()) { |
||||
|
editTextUsername.setError("请输入用户名"); |
||||
|
editTextUsername.requestFocus(); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (password.isEmpty()) { |
||||
|
editTextPassword.setError("请输入密码"); |
||||
|
editTextPassword.requestFocus(); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (password.length() < 6) { |
||||
|
editTextPassword.setError("密码长度至少6位"); |
||||
|
editTextPassword.requestFocus(); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
private void performLogin(String username, String password) { |
||||
|
// 这里可以添加实际的登录逻辑 |
||||
|
// 目前只是显示一个简单的提示 |
||||
|
if (username.equals("admin") && password.equals("123456")) { |
||||
|
Toast.makeText(this, "登录成功!欢迎 " + username, Toast.LENGTH_SHORT).show(); |
||||
|
} else { |
||||
|
Toast.makeText(this, "用户名或密码错误", Toast.LENGTH_SHORT).show(); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
<?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="@color/primary_color" |
||||
|
android:pathData="M0,0h108v108h-108z" /> |
||||
|
<path android:fillColor="@color/primary_light_color" |
||||
|
android:pathData="M9,0h90v108h-90z" /> |
||||
|
</vector> |
@ -0,0 +1,15 @@ |
|||||
|
<?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"> |
||||
|
<group android:scaleX="2.61" |
||||
|
android:scaleY="2.61" |
||||
|
android:translateX="22.68" |
||||
|
android:translateY="22.68"> |
||||
|
<path |
||||
|
android:fillColor="@android:color/white" |
||||
|
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/> |
||||
|
</group> |
||||
|
</vector> |
@ -0,0 +1,10 @@ |
|||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
|
android:width="24dp" |
||||
|
android:height="24dp" |
||||
|
android:viewportWidth="24" |
||||
|
android:viewportHeight="24" |
||||
|
android:tint="@color/secondary_text_color"> |
||||
|
<path |
||||
|
android:fillColor="@android:color/white" |
||||
|
android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z"/> |
||||
|
</vector> |
@ -0,0 +1,10 @@ |
|||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
|
android:width="100dp" |
||||
|
android:height="100dp" |
||||
|
android:viewportWidth="24" |
||||
|
android:viewportHeight="24" |
||||
|
android:tint="@color/primary_color"> |
||||
|
<path |
||||
|
android:fillColor="@android:color/white" |
||||
|
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/> |
||||
|
</vector> |
@ -0,0 +1,10 @@ |
|||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
|
android:width="24dp" |
||||
|
android:height="24dp" |
||||
|
android:viewportWidth="24" |
||||
|
android:viewportHeight="24" |
||||
|
android:tint="@color/secondary_text_color"> |
||||
|
<path |
||||
|
android:fillColor="@android:color/white" |
||||
|
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/> |
||||
|
</vector> |
@ -0,0 +1,153 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<ScrollView 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:background="@color/background_color" |
||||
|
android:fillViewport="true"> |
||||
|
|
||||
|
<androidx.constraintlayout.widget.ConstraintLayout |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:minHeight="@dimen/min_screen_height" |
||||
|
tools:context=".MainActivity"> |
||||
|
|
||||
|
<!-- 应用Logo --> |
||||
|
<ImageView |
||||
|
android:id="@+id/imageViewLogo" |
||||
|
android:layout_width="100dp" |
||||
|
android:layout_height="100dp" |
||||
|
android:layout_marginTop="40dp" |
||||
|
android:src="@drawable/ic_login_logo" |
||||
|
android:contentDescription="@string/app_logo" |
||||
|
app:layout_constraintEnd_toEndOf="parent" |
||||
|
app:layout_constraintStart_toStartOf="parent" |
||||
|
app:layout_constraintTop_toTopOf="parent" /> |
||||
|
|
||||
|
<!-- 应用标题 --> |
||||
|
<TextView |
||||
|
android:id="@+id/textViewTitle" |
||||
|
android:layout_width="wrap_content" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_marginTop="20dp" |
||||
|
android:text="@string/app_name" |
||||
|
android:textSize="24sp" |
||||
|
android:textStyle="bold" |
||||
|
android:textColor="@color/primary_text_color" |
||||
|
app:layout_constraintEnd_toEndOf="parent" |
||||
|
app:layout_constraintStart_toStartOf="parent" |
||||
|
app:layout_constraintTop_toBottomOf="@+id/imageViewLogo" /> |
||||
|
|
||||
|
<!-- 登录卡片容器 --> |
||||
|
<androidx.cardview.widget.CardView |
||||
|
android:layout_width="0dp" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_marginStart="32dp" |
||||
|
android:layout_marginTop="40dp" |
||||
|
android:layout_marginEnd="32dp" |
||||
|
android:layout_marginBottom="32dp" |
||||
|
app:cardCornerRadius="16dp" |
||||
|
app:cardElevation="8dp" |
||||
|
app:cardBackgroundColor="@color/card_background" |
||||
|
app:layout_constraintEnd_toEndOf="parent" |
||||
|
app:layout_constraintStart_toStartOf="parent" |
||||
|
app:layout_constraintTop_toBottomOf="@+id/textViewTitle" |
||||
|
app:layout_constraintBottom_toBottomOf="parent"> |
||||
|
|
||||
|
<LinearLayout |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:orientation="vertical" |
||||
|
android:padding="32dp"> |
||||
|
|
||||
|
<!-- 登录卡片内的Logo --> |
||||
|
<ImageView |
||||
|
android:id="@+id/imageViewLoginLogo" |
||||
|
android:layout_width="80dp" |
||||
|
android:layout_height="80dp" |
||||
|
android:layout_gravity="center" |
||||
|
android:layout_marginBottom="24dp" |
||||
|
android:src="@drawable/ic_login_logo" |
||||
|
android:contentDescription="@string/login_logo" /> |
||||
|
|
||||
|
<!-- 用户名输入框 --> |
||||
|
<com.google.android.material.textfield.TextInputLayout |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_marginBottom="16dp" |
||||
|
android:hint="@string/hint_username" |
||||
|
app:startIconDrawable="@drawable/ic_person" |
||||
|
app:boxStrokeColor="@color/primary_color" |
||||
|
app:hintTextColor="@color/primary_color" |
||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"> |
||||
|
|
||||
|
<com.google.android.material.textfield.TextInputEditText |
||||
|
android:id="@+id/editTextUsername" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:inputType="text" |
||||
|
android:maxLines="1" |
||||
|
android:textColor="@color/primary_text_color" |
||||
|
android:textSize="16sp" /> |
||||
|
|
||||
|
</com.google.android.material.textfield.TextInputLayout> |
||||
|
|
||||
|
<!-- 密码输入框 --> |
||||
|
<com.google.android.material.textfield.TextInputLayout |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_marginBottom="24dp" |
||||
|
android:hint="@string/hint_password" |
||||
|
app:startIconDrawable="@drawable/ic_lock" |
||||
|
app:endIconMode="password_toggle" |
||||
|
app:boxStrokeColor="@color/primary_color" |
||||
|
app:hintTextColor="@color/primary_color" |
||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"> |
||||
|
|
||||
|
<com.google.android.material.textfield.TextInputEditText |
||||
|
android:id="@+id/editTextPassword" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:inputType="textPassword" |
||||
|
android:maxLines="1" |
||||
|
android:textColor="@color/primary_text_color" |
||||
|
android:textSize="16sp" /> |
||||
|
|
||||
|
</com.google.android.material.textfield.TextInputLayout> |
||||
|
|
||||
|
<!-- 登录按钮 --> |
||||
|
<com.google.android.material.button.MaterialButton |
||||
|
android:id="@+id/buttonLogin" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="56dp" |
||||
|
android:text="@string/login_button" |
||||
|
android:textSize="16sp" |
||||
|
android:textStyle="bold" |
||||
|
android:textColor="@android:color/white" |
||||
|
app:backgroundTint="@color/primary_color" |
||||
|
app:cornerRadius="28dp" |
||||
|
app:elevation="4dp" /> |
||||
|
|
||||
|
<!-- 忘记密码链接 --> |
||||
|
<TextView |
||||
|
android:id="@+id/textViewForgotPassword" |
||||
|
android:layout_width="wrap_content" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_gravity="center" |
||||
|
android:layout_marginTop="16dp" |
||||
|
android:text="@string/forgot_password" |
||||
|
android:textColor="@color/secondary_text_color" |
||||
|
android:textSize="14sp" |
||||
|
android:padding="8dp" |
||||
|
android:background="?attr/selectableItemBackgroundBorderless" |
||||
|
android:clickable="true" |
||||
|
android:focusable="true" /> |
||||
|
|
||||
|
</LinearLayout> |
||||
|
|
||||
|
</androidx.cardview.widget.CardView> |
||||
|
|
||||
|
</androidx.constraintlayout.widget.ConstraintLayout> |
||||
|
|
||||
|
</ScrollView> |
@ -0,0 +1,5 @@ |
|||||
|
<?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" /> |
||||
|
</adaptive-icon> |
@ -0,0 +1,5 @@ |
|||||
|
<?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" /> |
||||
|
</adaptive-icon> |
@ -0,0 +1,16 @@ |
|||||
|
<resources xmlns:tools="http://schemas.android.com/tools"> |
||||
|
<!-- Base application theme. --> |
||||
|
<style name="Theme.OxFaceLogin" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> |
||||
|
<!-- Primary brand color. --> |
||||
|
<item name="colorPrimary">@color/primary_color</item> |
||||
|
<item name="colorPrimaryVariant">@color/primary_dark_color</item> |
||||
|
<item name="colorOnPrimary">@color/black</item> |
||||
|
<!-- Secondary brand color. --> |
||||
|
<item name="colorSecondary">@color/teal_200</item> |
||||
|
<item name="colorSecondaryVariant">@color/teal_200</item> |
||||
|
<item name="colorOnSecondary">@color/black</item> |
||||
|
<!-- Status bar color. --> |
||||
|
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> |
||||
|
<!-- Customize your theme here. --> |
||||
|
</style> |
||||
|
</resources> |
@ -0,0 +1,31 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<resources> |
||||
|
<!-- 主题色 --> |
||||
|
<color name="primary_color">#009874</color> |
||||
|
<color name="primary_dark_color">#007A5E</color> |
||||
|
<color name="primary_light_color">#B2E0D8</color> |
||||
|
|
||||
|
<!-- 强调色 --> |
||||
|
<color name="accent_color">#FF5722</color> |
||||
|
|
||||
|
<!-- 背景色 --> |
||||
|
<color name="background_color">#F5F5F5</color> |
||||
|
<color name="card_background">#FFFFFF</color> |
||||
|
|
||||
|
<!-- 文字颜色 --> |
||||
|
<color name="primary_text_color">#212121</color> |
||||
|
<color name="secondary_text_color">#757575</color> |
||||
|
|
||||
|
<!-- 其他颜色 --> |
||||
|
<color name="divider_color">#BDBDBD</color> |
||||
|
<color name="error_color">#F44336</color> |
||||
|
|
||||
|
<!-- 系统颜色 --> |
||||
|
<color name="purple_200">#FFBB86FC</color> |
||||
|
<color name="purple_500">#FF6200EE</color> |
||||
|
<color name="purple_700">#FF3700B3</color> |
||||
|
<color name="teal_200">#FF03DAC5</color> |
||||
|
<color name="teal_700">#FF018786</color> |
||||
|
<color name="black">#FF000000</color> |
||||
|
<color name="white">#FFFFFFFF</color> |
||||
|
</resources> |
@ -0,0 +1,5 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<resources> |
||||
|
<!-- 最小屏幕高度,确保内容在小屏幕上也能正确显示 --> |
||||
|
<dimen name="min_screen_height">600dp</dimen> |
||||
|
</resources> |
@ -0,0 +1,14 @@ |
|||||
|
<resources> |
||||
|
<string name="app_name">OxFace登录</string> |
||||
|
<string name="app_logo">应用图标</string> |
||||
|
<string name="login_logo">登录图标</string> |
||||
|
<string name="hint_username">用户名</string> |
||||
|
<string name="hint_password">密码</string> |
||||
|
<string name="login_button">登录</string> |
||||
|
<string name="forgot_password">忘记密码?</string> |
||||
|
<string name="login_success">登录成功!</string> |
||||
|
<string name="login_failed">用户名或密码错误</string> |
||||
|
<string name="empty_username">请输入用户名</string> |
||||
|
<string name="empty_password">请输入密码</string> |
||||
|
<string name="password_too_short">密码长度至少6位</string> |
||||
|
</resources> |
@ -0,0 +1,34 @@ |
|||||
|
<resources xmlns:tools="http://schemas.android.com/tools"> |
||||
|
<!-- Base application theme. --> |
||||
|
<style name="Theme.OxFaceLogin" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> |
||||
|
<!-- Primary brand color. --> |
||||
|
<item name="colorPrimary">@color/primary_color</item> |
||||
|
<item name="colorPrimaryVariant">@color/primary_dark_color</item> |
||||
|
<item name="colorOnPrimary">@color/white</item> |
||||
|
<!-- Secondary brand color. --> |
||||
|
<item name="colorSecondary">@color/accent_color</item> |
||||
|
<item name="colorSecondaryVariant">@color/accent_color</item> |
||||
|
<item name="colorOnSecondary">@color/white</item> |
||||
|
<!-- Status bar color. --> |
||||
|
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> |
||||
|
<!-- Customize your theme here. --> |
||||
|
<item name="android:windowBackground">@color/background_color</item> |
||||
|
</style> |
||||
|
|
||||
|
<!-- 登录按钮样式 --> |
||||
|
<style name="LoginButtonStyle" parent="Widget.MaterialComponents.Button"> |
||||
|
<item name="android:layout_width">match_parent</item> |
||||
|
<item name="android:layout_height">56dp</item> |
||||
|
<item name="android:textSize">16sp</item> |
||||
|
<item name="android:textStyle">bold</item> |
||||
|
<item name="backgroundTint">@color/primary_color</item> |
||||
|
<item name="cornerRadius">28dp</item> |
||||
|
</style> |
||||
|
|
||||
|
<!-- 输入框样式 --> |
||||
|
<style name="InputLayoutStyle" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox"> |
||||
|
<item name="boxStrokeColor">@color/primary_color</item> |
||||
|
<item name="hintTextColor">@color/primary_color</item> |
||||
|
<item name="android:layout_marginBottom">16dp</item> |
||||
|
</style> |
||||
|
</resources> |
@ -0,0 +1,12 @@ |
|||||
|
<?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 that API 23 even if they have backups enabled. |
||||
|
--> |
||||
|
<full-backup-content> |
||||
|
<!-- |
||||
|
<include domain="sharedpref" path="."/> |
||||
|
<exclude domain="sharedpref" path="device.xml"/> |
||||
|
--> |
||||
|
</full-backup-content> |
@ -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,16 @@ |
|||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules. |
||||
|
buildscript { |
||||
|
repositories { |
||||
|
google() |
||||
|
mavenCentral() |
||||
|
} |
||||
|
dependencies { |
||||
|
classpath 'com.android.tools.build:gradle:8.7.2' |
||||
|
// NOTE: Do not place your application dependencies here; they belong |
||||
|
// in the individual module build.gradle files |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
task clean(type: Delete) { |
||||
|
delete rootProject.buildDir |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
# Project-wide Gradle settings. |
||||
|
# IDE (e.g. Android Studio) users: |
||||
|
# Gradle settings configured through the IDE *will override* |
||||
|
# any settings specified in this file. |
||||
|
# For more details on how to configure your build environment visit |
||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html |
||||
|
# Specifies the JVM arguments used for the daemon process. |
||||
|
# The setting is particularly useful for tweaking memory settings. |
||||
|
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 |
||||
|
# When configured, Gradle will run in incubating parallel mode. |
||||
|
# This option should only be used with decoupled projects. More details, visit |
||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects |
||||
|
# org.gradle.parallel=true |
||||
|
# AndroidX package structure to make it clearer which packages are bundled with the |
||||
|
# Android operating system, and which are packaged with your app's APK |
||||
|
# https://developer.android.com/topic/libraries/support-library/androidx-rn |
||||
|
android.useAndroidX=true |
||||
|
# Kotlin code style for this project: "official" or "obsolete": |
||||
|
kotlin.code.style=official |
||||
|
# Enables namespacing of each library's R class so that its R class includes only the |
||||
|
# resources declared in the library itself and none from the library's dependencies, |
||||
|
# thereby reducing the size of the R class for that library |
||||
|
android.nonTransitiveRClass=true |
||||
|
|
||||
|
# Disable offline mode for build |
||||
|
org.gradle.offline=false |
||||
|
# Android SDK path |
||||
|
android.sdk.path=/Users/zmt/Library/Android/sdk |
@ -0,0 +1,5 @@ |
|||||
|
distributionBase=GRADLE_USER_HOME |
||||
|
distributionPath=wrapper/dists |
||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0-bin.zip |
||||
|
zipStoreBase=GRADLE_USER_HOME |
||||
|
zipStorePath=wrapper/dists |
@ -0,0 +1,185 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# |
||||
|
# Copyright 2015 the original author or authors. |
||||
|
# |
||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
# you may not use this file except in compliance with the License. |
||||
|
# You may obtain a copy of the License at |
||||
|
# |
||||
|
# https://www.apache.org/licenses/LICENSE-2.0 |
||||
|
# |
||||
|
# Unless required by applicable law or agreed to in writing, software |
||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
# See the License for the specific language governing permissions and |
||||
|
# limitations under the License. |
||||
|
# |
||||
|
|
||||
|
############################################################################## |
||||
|
## |
||||
|
## Gradle start up script for UN*X |
||||
|
## |
||||
|
############################################################################## |
||||
|
|
||||
|
# Attempt to set APP_HOME |
||||
|
# Resolve links: $0 may be a link |
||||
|
PRG="$0" |
||||
|
# Need this for relative symlinks. |
||||
|
while [ -h "$PRG" ] ; do |
||||
|
ls=`ls -ld "$PRG"` |
||||
|
link=`expr "$ls" : '.*-> \(.*\)$'` |
||||
|
if expr "$link" : '/.*' > /dev/null; then |
||||
|
PRG="$link" |
||||
|
else |
||||
|
PRG=`dirname "$PRG"`"/$link" |
||||
|
fi |
||||
|
done |
||||
|
SAVED="`pwd`" |
||||
|
cd "`dirname \"$PRG\"`/" >/dev/null |
||||
|
APP_HOME="`pwd -P`" |
||||
|
cd "$SAVED" >/dev/null |
||||
|
|
||||
|
APP_NAME="Gradle" |
||||
|
APP_BASE_NAME=`basename "$0"` |
||||
|
|
||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' |
||||
|
|
||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value. |
||||
|
MAX_FD="maximum" |
||||
|
|
||||
|
warn () { |
||||
|
echo "$*" |
||||
|
} |
||||
|
|
||||
|
die () { |
||||
|
echo |
||||
|
echo "$*" |
||||
|
echo |
||||
|
exit 1 |
||||
|
} |
||||
|
|
||||
|
# OS specific support (must be 'true' or 'false'). |
||||
|
cygwin=false |
||||
|
msys=false |
||||
|
darwin=false |
||||
|
nonstop=false |
||||
|
case "`uname`" in |
||||
|
CYGWIN* ) |
||||
|
cygwin=true |
||||
|
;; |
||||
|
Darwin* ) |
||||
|
darwin=true |
||||
|
;; |
||||
|
MINGW* ) |
||||
|
msys=true |
||||
|
;; |
||||
|
NONSTOP* ) |
||||
|
nonstop=true |
||||
|
;; |
||||
|
esac |
||||
|
|
||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar |
||||
|
|
||||
|
|
||||
|
# Determine the Java command to use to start the JVM. |
||||
|
if [ -n "$JAVA_HOME" ] ; then |
||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then |
||||
|
# IBM's JDK on AIX uses strange locations for the executables |
||||
|
JAVACMD="$JAVA_HOME/jre/sh/java" |
||||
|
else |
||||
|
JAVACMD="$JAVA_HOME/bin/java" |
||||
|
fi |
||||
|
if [ ! -x "$JAVACMD" ] ; then |
||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME |
||||
|
|
||||
|
Please set the JAVA_HOME variable in your environment to match the |
||||
|
location of your Java installation." |
||||
|
fi |
||||
|
else |
||||
|
JAVACMD="java" |
||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
||||
|
|
||||
|
Please set the JAVA_HOME variable in your environment to match the |
||||
|
location of your Java installation." |
||||
|
fi |
||||
|
|
||||
|
# Increase the maximum file descriptors if we can. |
||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then |
||||
|
MAX_FD_LIMIT=`ulimit -H -n` |
||||
|
if [ $? -eq 0 ] ; then |
||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then |
||||
|
MAX_FD="$MAX_FD_LIMIT" |
||||
|
fi |
||||
|
ulimit -n $MAX_FD |
||||
|
if [ $? -ne 0 ] ; then |
||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD" |
||||
|
fi |
||||
|
else |
||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
# For Darwin, add options to specify how the application appears in the dock |
||||
|
if [ "$darwin" = "true" ]; then |
||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" |
||||
|
fi |
||||
|
|
||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java |
||||
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then |
||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"` |
||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` |
||||
|
|
||||
|
JAVACMD=`cygpath --unix "$JAVACMD"` |
||||
|
|
||||
|
# We build the pattern for arguments to be converted via cygpath |
||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` |
||||
|
SEP="" |
||||
|
for dir in $ROOTDIRSRAW ; do |
||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir" |
||||
|
SEP="|" |
||||
|
done |
||||
|
OURCYGPATTERN="(^($ROOTDIRS))" |
||||
|
# Add a user-defined pattern to the cygpath arguments |
||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then |
||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" |
||||
|
fi |
||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh |
||||
|
i=0 |
||||
|
for arg in "$@" ; do |
||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` |
||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option |
||||
|
|
||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition |
||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` |
||||
|
else |
||||
|
eval `echo args$i`="\"$arg\"" |
||||
|
fi |
||||
|
i=`expr $i + 1` |
||||
|
done |
||||
|
case $i in |
||||
|
0) set -- ;; |
||||
|
1) set -- "$args0" ;; |
||||
|
2) set -- "$args0" "$args1" ;; |
||||
|
3) set -- "$args0" "$args1" "$args2" ;; |
||||
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;; |
||||
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; |
||||
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; |
||||
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; |
||||
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; |
||||
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; |
||||
|
esac |
||||
|
fi |
||||
|
|
||||
|
# Escape application args |
||||
|
save () { |
||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done |
||||
|
echo " " |
||||
|
} |
||||
|
APP_ARGS=`save "$@"` |
||||
|
|
||||
|
# Collect all arguments for the java command |
||||
|
set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" |
||||
|
|
||||
|
exec "$JAVACMD" "$@" |
@ -0,0 +1,17 @@ |
|||||
|
pluginManagement { |
||||
|
repositories { |
||||
|
google() |
||||
|
mavenCentral() |
||||
|
gradlePluginPortal() |
||||
|
} |
||||
|
} |
||||
|
dependencyResolutionManagement { |
||||
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) |
||||
|
repositories { |
||||
|
google() |
||||
|
mavenCentral() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
rootProject.name = "OxFaceLogin" |
||||
|
include ':app' |
Write
Preview
Loading…
Cancel
Save
Reference in new issue