commit
10fc7bd870
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,15 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
@ -0,0 +1,3 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
@ -0,0 +1 @@
|
||||
My Application
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="11" />
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetDropDown">
|
||||
<targetSelectedWithDropDown>
|
||||
<Target>
|
||||
<type value="QUICK_BOOT_TARGET" />
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="VIRTUAL_DEVICE_PATH" />
|
||||
<value value="C:\Users\20922\.android\avd\Pixel_6_Pro_API_33.avd" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</targetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2025-09-29T07:20:17.026786700Z" />
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="GRADLE" />
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
||||
/build
|
||||
Binary file not shown.
@ -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 @@
|
||||
package com.example.myapplication;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
assertEquals("com.example.myapplication", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,155 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-feature
|
||||
android:glEsVersion="0x00020000"
|
||||
android:required="true" />
|
||||
|
||||
<!-- 网络权限 -->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
|
||||
<!-- 高德地图SDK核心权限 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<!-- <uses-permission android:name="android.permission.WRITE_SETTINGS" /> 注释掉:此权限仅系统应用可用 -->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
|
||||
<!-- 高德地图导航相关权限 -->
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
|
||||
|
||||
<!-- 课程提醒相关权限 -->
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
||||
|
||||
<!-- 笔记图片相关权限 -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
|
||||
<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:supportsRtl="true"
|
||||
android:theme="@style/Theme.MyApplication"
|
||||
android:hardwareAccelerated="true"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:targetApi="31">
|
||||
|
||||
<!-- 高德地图API Key -->
|
||||
<meta-data
|
||||
android:name="com.amap.api.v2.apikey"
|
||||
android:value="0c0a6f3a57e257c8bf0d9c8202110a37" />
|
||||
|
||||
<!-- 高德地图服务配置 -->
|
||||
<service android:name="com.amap.api.location.APSService"></service>
|
||||
|
||||
<activity
|
||||
android:name=".HomeActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="false"
|
||||
android:hardwareAccelerated="true"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden" />
|
||||
|
||||
<activity
|
||||
android:name=".LocationDetailsActivity"
|
||||
android:exported="false" />
|
||||
|
||||
<!-- 教务系统登录WebView -->
|
||||
<activity
|
||||
android:name=".WebViewActivity"
|
||||
android:exported="false"
|
||||
android:label="教务系统登录"
|
||||
android:hardwareAccelerated="true"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden" />
|
||||
|
||||
<!-- 教务系统课表导入 -->
|
||||
<activity
|
||||
android:name=".EducationImportActivity"
|
||||
android:exported="false"
|
||||
android:label="教务系统课表导入"
|
||||
android:hardwareAccelerated="true"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden" />
|
||||
|
||||
<!-- 课程提醒全屏弹窗 -->
|
||||
<activity
|
||||
android:name=".ReminderAlertActivity"
|
||||
android:exported="false"
|
||||
android:theme="@style/Theme.AppCompat.Dialog.Alert"
|
||||
android:excludeFromRecents="true"
|
||||
android:finishOnTaskLaunch="true" />
|
||||
|
||||
<!-- 课程提醒弹窗(微信样式) -->
|
||||
<activity
|
||||
android:name=".CourseReminderActivity"
|
||||
android:exported="false"
|
||||
android:theme="@style/ReminderDialogTheme"
|
||||
android:excludeFromRecents="true"
|
||||
android:showWhenLocked="true"
|
||||
android:turnScreenOn="true"
|
||||
android:launchMode="singleTop" />
|
||||
|
||||
<!-- 全屏笔记编辑器 -->
|
||||
<activity
|
||||
android:name=".NoteEditorActivity"
|
||||
android:exported="false"
|
||||
android:label="编辑笔记"
|
||||
android:hardwareAccelerated="true"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden" />
|
||||
|
||||
<!-- 笔记阅读模式 -->
|
||||
<activity
|
||||
android:name=".NoteReaderActivity"
|
||||
android:exported="false"
|
||||
android:label="阅读笔记"
|
||||
android:hardwareAccelerated="true"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden" />
|
||||
|
||||
<!-- FileProvider for sharing files -->
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
<!-- 课程提醒接收器 -->
|
||||
<receiver
|
||||
android:name=".CourseReminderReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
|
||||
<receiver
|
||||
android:name=".ReminderReceiver"
|
||||
android:exported="false" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,158 @@
|
||||
package com.example.myapplication;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.EditText;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GradeAdapter extends RecyclerView.Adapter<GradeAdapter.GradeViewHolder> {
|
||||
|
||||
private List<WebViewActivity.GradeItem> gradeItems;
|
||||
public interface OnItemUpdatedListener { void onScoreUpdated(); }
|
||||
private OnItemUpdatedListener onItemUpdatedListener;
|
||||
|
||||
public GradeAdapter() {
|
||||
this.gradeItems = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void updateData(List<WebViewActivity.GradeItem> newItems) {
|
||||
this.gradeItems.clear();
|
||||
this.gradeItems.addAll(newItems);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setOnItemUpdatedListener(OnItemUpdatedListener listener) {
|
||||
this.onItemUpdatedListener = listener;
|
||||
}
|
||||
|
||||
public List<WebViewActivity.GradeItem> getItems() { return gradeItems; }
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public GradeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_grade, parent, false);
|
||||
return new GradeViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull GradeViewHolder holder, int position) {
|
||||
WebViewActivity.GradeItem item = gradeItems.get(position);
|
||||
|
||||
// 课程名称作为主标题
|
||||
String courseName = item.courseName != null && !item.courseName.isEmpty() ? item.courseName : "未知课程";
|
||||
holder.tvCourseName.setText(courseName);
|
||||
|
||||
// 课程编号
|
||||
String courseCode = item.courseCode != null && !item.courseCode.isEmpty() ? item.courseCode : "未知";
|
||||
holder.tvCourseCode.setText("编号: " + courseCode);
|
||||
|
||||
// 学分信息
|
||||
holder.tvCredit.setText("学分: " + (item.credit != null ? item.credit : "未知"));
|
||||
|
||||
// 成绩信息/输入切换
|
||||
boolean hasScore = item.score != null && !item.score.isEmpty();
|
||||
if (hasScore) {
|
||||
holder.tvScore.setVisibility(View.VISIBLE);
|
||||
holder.etScoreInput.setVisibility(View.GONE);
|
||||
holder.tvScore.setText("成绩: " + item.score);
|
||||
} else {
|
||||
holder.tvScore.setVisibility(View.GONE);
|
||||
holder.etScoreInput.setVisibility(View.VISIBLE);
|
||||
// 避免旧监听残留
|
||||
Object oldWatcher = holder.etScoreInput.getTag();
|
||||
if (oldWatcher instanceof TextWatcher) {
|
||||
holder.etScoreInput.removeTextChangedListener((TextWatcher) oldWatcher);
|
||||
}
|
||||
holder.etScoreInput.setText(item.score != null ? item.score : "");
|
||||
holder.etScoreInput.setHint("请输入成绩");
|
||||
|
||||
// 监听输入并计算绩点
|
||||
TextWatcher watcher = new TextWatcher() {
|
||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
@Override public void afterTextChanged(Editable s) {
|
||||
String text = s.toString().trim();
|
||||
item.score = text;
|
||||
String gpa = computeGpaFromScore(text);
|
||||
item.gpa = gpa;
|
||||
holder.tvGpa.setText("绩点: " + (gpa != null && !gpa.isEmpty() ? gpa : "0"));
|
||||
if (onItemUpdatedListener != null) onItemUpdatedListener.onScoreUpdated();
|
||||
}
|
||||
};
|
||||
holder.etScoreInput.addTextChangedListener(watcher);
|
||||
holder.etScoreInput.setTag(watcher);
|
||||
}
|
||||
|
||||
// 绩点信息
|
||||
holder.tvGpa.setText("绩点: " + (item.gpa != null && !item.gpa.isEmpty() ? item.gpa : "未知"));
|
||||
|
||||
// 学年/建议修读学年
|
||||
holder.tvYear.setText((hasScore ? "学年: " : "建议修读学年: ") + (item.year != null && !item.year.isEmpty() ? item.year : "未知"));
|
||||
|
||||
// 课程性质信息
|
||||
holder.tvStatus.setText("课程性质: " + (item.status != null ? item.status : "未知"));
|
||||
|
||||
// 学期/建议修读学期
|
||||
holder.tvTerm.setText((hasScore ? "学期: " : "建议修读学期: ") + (item.term != null && !item.term.isEmpty() ? item.term : "未知"));
|
||||
}
|
||||
|
||||
private String computeGpaFromScore(String scoreText) {
|
||||
if (scoreText == null || scoreText.isEmpty()) return "";
|
||||
try {
|
||||
int score = Integer.parseInt(scoreText);
|
||||
if (score >= 90) return "4.0";
|
||||
if (score >= 85) return "3.7";
|
||||
if (score >= 82) return "3.3";
|
||||
if (score >= 78) return "3.0";
|
||||
if (score >= 75) return "2.7";
|
||||
if (score >= 72) return "2.3";
|
||||
if (score >= 68) return "2.0";
|
||||
if (score >= 66) return "1.7";
|
||||
if (score >= 64) return "1.5";
|
||||
if (score >= 60) return "1.0";
|
||||
return "0";
|
||||
} catch (NumberFormatException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return gradeItems.size();
|
||||
}
|
||||
|
||||
static class GradeViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView tvCourseName;
|
||||
TextView tvCourseCode;
|
||||
TextView tvCredit;
|
||||
TextView tvScore;
|
||||
EditText etScoreInput;
|
||||
TextView tvGpa;
|
||||
TextView tvTerm;
|
||||
TextView tvYear;
|
||||
TextView tvStatus;
|
||||
|
||||
public GradeViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
tvCourseName = itemView.findViewById(R.id.tv_course_name);
|
||||
tvCourseCode = itemView.findViewById(R.id.tv_course_code);
|
||||
tvCredit = itemView.findViewById(R.id.tv_credit);
|
||||
tvScore = itemView.findViewById(R.id.tv_score);
|
||||
etScoreInput = itemView.findViewById(R.id.et_score_input);
|
||||
tvGpa = itemView.findViewById(R.id.tv_gpa);
|
||||
tvTerm = itemView.findViewById(R.id.tv_term);
|
||||
tvYear = itemView.findViewById(R.id.tv_year);
|
||||
tvStatus = itemView.findViewById(R.id.tv_status);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package com.example.myapplication;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.cardview.widget.CardView;
|
||||
|
||||
public class HomeActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_home);
|
||||
|
||||
// 获取四个功能卡片
|
||||
CardView cardTimetable = findViewById(R.id.card_timetable);
|
||||
CardView cardNotes = findViewById(R.id.card_notes);
|
||||
CardView cardGrades = findViewById(R.id.card_grades);
|
||||
CardView cardCampus = findViewById(R.id.card_campus);
|
||||
|
||||
// 课表按钮点击事件
|
||||
cardTimetable.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(HomeActivity.this, MainActivity.class);
|
||||
intent.putExtra("fragment", "timetable");
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
// 笔记按钮点击事件
|
||||
cardNotes.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(HomeActivity.this, MainActivity.class);
|
||||
intent.putExtra("fragment", "notes");
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
// 成绩按钮点击事件
|
||||
cardGrades.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(HomeActivity.this, MainActivity.class);
|
||||
intent.putExtra("fragment", "grades");
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
// 校园导航按钮点击事件
|
||||
cardCampus.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(HomeActivity.this, MainActivity.class);
|
||||
intent.putExtra("fragment", "campus");
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.example.myapplication;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
try {
|
||||
// Configure window for better OpenGL rendering
|
||||
Window window = getWindow();
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
|
||||
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
// 从Intent获取要显示的页面
|
||||
String fragmentType = getIntent().getStringExtra("fragment");
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
Fragment fragment = null;
|
||||
|
||||
if ("notes".equals(fragmentType)) {
|
||||
fragment = new NotesFragment();
|
||||
} else if ("grades".equals(fragmentType)) {
|
||||
fragment = new GradesFragment();
|
||||
} else if ("campus".equals(fragmentType)) {
|
||||
fragment = new CampusNavFragmentSimplified();
|
||||
} else {
|
||||
// 默认显示课表页面
|
||||
fragment = new TimetableFragment();
|
||||
}
|
||||
|
||||
getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(R.id.fragment_container, fragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(this, "应用初始化失败", Toast.LENGTH_LONG).show();
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// 返回主页面
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
package com.example.myapplication;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Note implements Serializable {
|
||||
private String id;
|
||||
private String title; // 笔记标题
|
||||
private String content; // 笔记内容
|
||||
private String courseId; // 关联的课程ID
|
||||
private String courseName; // 关联的课程名称
|
||||
private long createTime; // 创建时间
|
||||
private long modifyTime; // 修改时间
|
||||
private List<String> imagePaths; // 图片路径列表
|
||||
|
||||
public Note() {
|
||||
this.id = String.valueOf(System.currentTimeMillis());
|
||||
this.createTime = System.currentTimeMillis();
|
||||
this.modifyTime = System.currentTimeMillis();
|
||||
this.imagePaths = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Note(String title, String content) {
|
||||
this();
|
||||
this.title = title;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public Note(String title, String content, String courseId, String courseName) {
|
||||
this(title, content);
|
||||
this.courseId = courseId;
|
||||
this.courseName = courseName;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getId() { return id; }
|
||||
public void setId(String id) { this.id = id; }
|
||||
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
this.modifyTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public String getContent() { return content; }
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
this.modifyTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public String getCourseId() { return courseId; }
|
||||
public void setCourseId(String courseId) {
|
||||
this.courseId = courseId;
|
||||
this.modifyTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public String getCourseName() { return courseName; }
|
||||
public void setCourseName(String courseName) {
|
||||
this.courseName = courseName;
|
||||
this.modifyTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public long getCreateTime() { return createTime; }
|
||||
public void setCreateTime(long createTime) { this.createTime = createTime; }
|
||||
|
||||
public long getModifyTime() { return modifyTime; }
|
||||
public void setModifyTime(long modifyTime) { this.modifyTime = modifyTime; }
|
||||
|
||||
public List<String> getImagePaths() { return imagePaths; }
|
||||
public void setImagePaths(List<String> imagePaths) {
|
||||
this.imagePaths = imagePaths != null ? imagePaths : new ArrayList<>();
|
||||
this.modifyTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void addImagePath(String imagePath) {
|
||||
if (this.imagePaths == null) {
|
||||
this.imagePaths = new ArrayList<>();
|
||||
}
|
||||
this.imagePaths.add(imagePath);
|
||||
this.modifyTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void removeImagePath(String imagePath) {
|
||||
if (this.imagePaths != null) {
|
||||
this.imagePaths.remove(imagePath);
|
||||
this.modifyTime = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title + (courseName != null ? " (" + courseName + ")" : "");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,368 @@
|
||||
package com.example.myapplication;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NotesFragment extends Fragment {
|
||||
|
||||
private RecyclerView rvNotes;
|
||||
private FloatingActionButton fabAddNote;
|
||||
private Spinner spinnerCourseFilter;
|
||||
private LinearLayout layoutEmpty;
|
||||
private com.google.android.material.textfield.TextInputLayout tilNoteSearch;
|
||||
private android.widget.EditText etNoteSearch;
|
||||
|
||||
private DataManager dataManager;
|
||||
private List<Note> allNotes;
|
||||
private List<Note> filteredNotes;
|
||||
private List<Course> courses;
|
||||
private NotesAdapter notesAdapter;
|
||||
|
||||
private String selectedCourseId = "";
|
||||
private String searchQuery = "";
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_notes, container, false);
|
||||
|
||||
initViews(view);
|
||||
setupData();
|
||||
setupListeners();
|
||||
setupRecyclerView();
|
||||
setupCourseFilter();
|
||||
loadNotes();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void initViews(View view) {
|
||||
rvNotes = view.findViewById(R.id.rv_notes);
|
||||
fabAddNote = view.findViewById(R.id.fab_add_note);
|
||||
spinnerCourseFilter = view.findViewById(R.id.spinner_course_filter);
|
||||
layoutEmpty = view.findViewById(R.id.layout_empty);
|
||||
tilNoteSearch = view.findViewById(R.id.til_note_search);
|
||||
etNoteSearch = view.findViewById(R.id.et_note_search);
|
||||
}
|
||||
|
||||
private void setupData() {
|
||||
dataManager = new DataManager(getContext());
|
||||
allNotes = new ArrayList<>();
|
||||
filteredNotes = new ArrayList<>();
|
||||
courses = dataManager.getCourses();
|
||||
}
|
||||
|
||||
private void setupListeners() {
|
||||
fabAddNote.setOnClickListener(v -> {
|
||||
android.content.Intent intent = new android.content.Intent(getContext(), NoteEditorActivity.class);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
if (tilNoteSearch != null) {
|
||||
tilNoteSearch.setEndIconOnClickListener(v -> filterNotes());
|
||||
}
|
||||
if (etNoteSearch != null) {
|
||||
etNoteSearch.addTextChangedListener(new android.text.TextWatcher() {
|
||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
searchQuery = s.toString().trim();
|
||||
filterNotes();
|
||||
}
|
||||
@Override public void afterTextChanged(android.text.Editable s) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void setupRecyclerView() {
|
||||
notesAdapter = new NotesAdapter(getContext(), filteredNotes);
|
||||
notesAdapter.setOnNoteClickListener(new NotesAdapter.OnNoteClickListener() {
|
||||
@Override
|
||||
public void onNoteClick(Note note) {
|
||||
// 打开阅读模式
|
||||
android.content.Intent intent = new android.content.Intent(getContext(), NoteReaderActivity.class);
|
||||
intent.putExtra(NoteReaderActivity.EXTRA_NOTE_ID, note.getId());
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNoteLongClick(Note note) {
|
||||
showNoteOptions(note);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEditClick(Note note) {
|
||||
// 打开编辑模式
|
||||
android.content.Intent intent = new android.content.Intent(getContext(), NoteEditorActivity.class);
|
||||
intent.putExtra(NoteEditorActivity.EXTRA_NOTE_ID, note.getId());
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleteClick(Note note) {
|
||||
deleteNote(note);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResetOtherItems() {
|
||||
// 重置所有滑动状态
|
||||
notesAdapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
rvNotes.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
rvNotes.setAdapter(notesAdapter);
|
||||
}
|
||||
|
||||
private void setupCourseFilter() {
|
||||
List<String> courseNames = new ArrayList<>();
|
||||
courseNames.add("全部课程");
|
||||
|
||||
List<String> courseIds = new ArrayList<>();
|
||||
courseIds.add("");
|
||||
|
||||
for (Course course : courses) {
|
||||
courseNames.add(course.getName());
|
||||
courseIds.add(course.getId());
|
||||
}
|
||||
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(),
|
||||
android.R.layout.simple_spinner_item, courseNames);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinnerCourseFilter.setAdapter(adapter);
|
||||
|
||||
spinnerCourseFilter.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
selectedCourseId = courseIds.get(position);
|
||||
filterNotes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadNotes() {
|
||||
allNotes = dataManager.getNotes();
|
||||
filterNotes();
|
||||
}
|
||||
|
||||
private void filterNotes() {
|
||||
filteredNotes.clear();
|
||||
String q = searchQuery == null ? "" : searchQuery.toLowerCase();
|
||||
for (Note note : allNotes) {
|
||||
boolean courseOk = selectedCourseId.isEmpty() || (note.getCourseId() != null && note.getCourseId().equals(selectedCourseId));
|
||||
if (!courseOk) continue;
|
||||
if (q.isEmpty()) {
|
||||
filteredNotes.add(note);
|
||||
} else {
|
||||
String title = note.getTitle() == null ? "" : note.getTitle().toLowerCase();
|
||||
String content = note.getContent() == null ? "" : note.getContent().toLowerCase();
|
||||
String course = note.getCourseName() == null ? "" : note.getCourseName().toLowerCase();
|
||||
if (title.contains(q) || content.contains(q) || course.contains(q)) {
|
||||
filteredNotes.add(note);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 按修改时间倒序
|
||||
java.util.Collections.sort(filteredNotes, (a, b) -> Long.compare(b.getModifyTime(), a.getModifyTime()));
|
||||
notesAdapter.updateNotes(filteredNotes);
|
||||
updateEmptyView();
|
||||
}
|
||||
|
||||
private void updateEmptyView() {
|
||||
if (filteredNotes.isEmpty()) {
|
||||
rvNotes.setVisibility(View.GONE);
|
||||
layoutEmpty.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
rvNotes.setVisibility(View.VISIBLE);
|
||||
layoutEmpty.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void showAddNoteDialog(Note editNote) {
|
||||
View dialogView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_add_note, null);
|
||||
|
||||
TextView tvDialogTitle = dialogView.findViewById(R.id.tv_dialog_title);
|
||||
EditText etNoteTitle = dialogView.findViewById(R.id.et_note_title);
|
||||
EditText etNoteContent = dialogView.findViewById(R.id.et_note_content);
|
||||
Spinner spinnerCourse = dialogView.findViewById(R.id.spinner_course);
|
||||
|
||||
// 设置标题
|
||||
tvDialogTitle.setText(editNote == null ? "添加笔记" : "编辑笔记");
|
||||
|
||||
// 设置课程选择器
|
||||
List<String> courseOptions = new ArrayList<>();
|
||||
courseOptions.add("无关联课程");
|
||||
|
||||
List<String> courseIdOptions = new ArrayList<>();
|
||||
courseIdOptions.add("");
|
||||
|
||||
for (Course course : courses) {
|
||||
courseOptions.add(course.getName());
|
||||
courseIdOptions.add(course.getId());
|
||||
}
|
||||
|
||||
ArrayAdapter<String> courseAdapter = new ArrayAdapter<>(getContext(),
|
||||
android.R.layout.simple_spinner_item, courseOptions);
|
||||
courseAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinnerCourse.setAdapter(courseAdapter);
|
||||
|
||||
// 如果是编辑模式,填充现有数据
|
||||
if (editNote != null) {
|
||||
etNoteTitle.setText(editNote.getTitle());
|
||||
etNoteContent.setText(editNote.getContent());
|
||||
|
||||
// 设置课程选择
|
||||
if (editNote.getCourseId() != null) {
|
||||
for (int i = 0; i < courseIdOptions.size(); i++) {
|
||||
if (courseIdOptions.get(i).equals(editNote.getCourseId())) {
|
||||
spinnerCourse.setSelection(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AlertDialog dialog = new AlertDialog.Builder(getContext())
|
||||
.setView(dialogView)
|
||||
.create();
|
||||
|
||||
dialogView.findViewById(R.id.btn_cancel).setOnClickListener(v -> dialog.dismiss());
|
||||
|
||||
dialogView.findViewById(R.id.btn_save).setOnClickListener(v -> {
|
||||
String title = etNoteTitle.getText().toString().trim();
|
||||
String content = etNoteContent.getText().toString().trim();
|
||||
|
||||
if (title.isEmpty()) {
|
||||
Toast.makeText(getContext(), "请输入笔记标题", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (content.isEmpty()) {
|
||||
Toast.makeText(getContext(), "请输入笔记内容", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
String selectedCourseId = courseIdOptions.get(spinnerCourse.getSelectedItemPosition());
|
||||
String selectedCourseName = "";
|
||||
if (!selectedCourseId.isEmpty()) {
|
||||
selectedCourseName = courseOptions.get(spinnerCourse.getSelectedItemPosition());
|
||||
}
|
||||
|
||||
if (editNote == null) {
|
||||
// 添加新笔记
|
||||
Note newNote = new Note(title, content, selectedCourseId, selectedCourseName);
|
||||
dataManager.addNote(newNote);
|
||||
allNotes.add(newNote);
|
||||
Toast.makeText(getContext(), "笔记添加成功", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
// 编辑现有笔记
|
||||
editNote.setTitle(title);
|
||||
editNote.setContent(content);
|
||||
editNote.setCourseId(selectedCourseId);
|
||||
editNote.setCourseName(selectedCourseName);
|
||||
dataManager.saveNotes(allNotes);
|
||||
Toast.makeText(getContext(), "笔记修改成功", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
filterNotes();
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void deleteNote(Note note) {
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setTitle("删除笔记")
|
||||
.setMessage("确定要删除笔记《" + note.getTitle() + "》吗?")
|
||||
.setPositiveButton("删除", (dialog, which) -> {
|
||||
dataManager.deleteNote(note.getId());
|
||||
// 删除图片文件
|
||||
if (note.getImagePaths() != null) {
|
||||
for (String imagePath : note.getImagePaths()) {
|
||||
try {
|
||||
java.io.File file = new java.io.File(imagePath);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
allNotes.remove(note);
|
||||
filterNotes();
|
||||
Toast.makeText(getContext(), "笔记已删除", Toast.LENGTH_SHORT).show();
|
||||
})
|
||||
.setNegativeButton("取消", null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void showNoteDetails(Note note) {
|
||||
String details = note.getContent();
|
||||
String title = note.getTitle();
|
||||
if (note.getCourseName() != null && !note.getCourseName().isEmpty()) {
|
||||
title += " (" + note.getCourseName() + ")";
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setTitle(title)
|
||||
.setMessage(details)
|
||||
.setPositiveButton("确定", null)
|
||||
.setNeutralButton("编辑", (dialog, which) -> showAddNoteDialog(note))
|
||||
.show();
|
||||
}
|
||||
|
||||
private void showNoteOptions(Note note) {
|
||||
String[] options = {"查看详情", "编辑笔记", "删除笔记"};
|
||||
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setTitle(note.getTitle())
|
||||
.setItems(options, (dialog, which) -> {
|
||||
switch (which) {
|
||||
case 0:
|
||||
showNoteDetails(note);
|
||||
break;
|
||||
case 1:
|
||||
showAddNoteDialog(note);
|
||||
break;
|
||||
case 2:
|
||||
deleteNote(note);
|
||||
break;
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
// 重新加载课程数据(可能有新增的课程)
|
||||
courses = dataManager.getCourses();
|
||||
setupCourseFilter();
|
||||
// 返回时刷新笔记列表
|
||||
loadNotes();
|
||||
// 重置所有滑动状态
|
||||
if (notesAdapter != null) {
|
||||
notesAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
package com.example.myapplication;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class ReminderAlertActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||
setShowWhenLocked(true);
|
||||
setTurnScreenOn(true);
|
||||
}
|
||||
|
||||
getWindow().addFlags(
|
||||
android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
||||
| android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
|
||||
| android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
|
||||
| android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
|
||||
);
|
||||
|
||||
setFinishOnTouchOutside(false);
|
||||
|
||||
String courseName = getIntent().getStringExtra(ReminderReceiver.EXTRA_COURSE_NAME);
|
||||
String location = getIntent().getStringExtra(ReminderReceiver.EXTRA_COURSE_LOCATION);
|
||||
String teacher = getIntent().getStringExtra(ReminderReceiver.EXTRA_COURSE_TEACHER);
|
||||
|
||||
StringBuilder message = new StringBuilder();
|
||||
if (location != null && !location.isEmpty()) {
|
||||
message.append("上课地点:").append(location);
|
||||
}
|
||||
if (teacher != null && !teacher.isEmpty()) {
|
||||
if (message.length() > 0) {
|
||||
message.append("\n");
|
||||
}
|
||||
message.append("任课教师:").append(teacher);
|
||||
}
|
||||
if (message.length() > 0) {
|
||||
message.append("\n");
|
||||
}
|
||||
message.append("请准时到达教室,祝您上课顺利!");
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(courseName == null || courseName.isEmpty() ? "上课提醒" : "上课提醒:" + courseName)
|
||||
.setMessage(message.toString())
|
||||
.setCancelable(false)
|
||||
.setPositiveButton("知道了", (dialog, which) -> finish())
|
||||
.setNegativeButton("稍后提醒", (dialog, which) -> {
|
||||
// 五分钟后再次提醒
|
||||
Course course = findCourseById(getIntent().getStringExtra(ReminderReceiver.EXTRA_COURSE_ID));
|
||||
if (course != null) {
|
||||
ReminderScheduler.scheduleReminderInMinutes(this, course, 5);
|
||||
}
|
||||
finish();
|
||||
})
|
||||
.setOnCancelListener(dialog -> finish())
|
||||
.show();
|
||||
}
|
||||
|
||||
private Course findCourseById(String courseId) {
|
||||
if (courseId == null || courseId.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
DataManager dataManager = new DataManager(this);
|
||||
for (Course course : dataManager.getCourses()) {
|
||||
if (course != null && courseId.equals(course.getId())) {
|
||||
return course;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,265 @@
|
||||
package com.example.myapplication;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 简单地图视图组件
|
||||
* 在高德地图完全集成前提供基础的地图可视化功能
|
||||
*/
|
||||
public class SimpleMapView extends View {
|
||||
|
||||
private Paint paintBackground;
|
||||
private Paint paintGrid;
|
||||
private Paint paintCurrentLocation;
|
||||
private Paint paintDestination;
|
||||
private Paint paintPath;
|
||||
private Paint paintText;
|
||||
|
||||
private List<LocationPoint> locations;
|
||||
private LocationPoint currentLocation;
|
||||
private LocationPoint destination;
|
||||
|
||||
private float centerX = 400f;
|
||||
private float centerY = 400f;
|
||||
private float scale = 100000f; // 地图缩放比例
|
||||
|
||||
public interface OnLocationClickListener {
|
||||
void onLocationClicked(LocationPoint point);
|
||||
}
|
||||
|
||||
private OnLocationClickListener onLocationClickListener;
|
||||
|
||||
public SimpleMapView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public SimpleMapView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
initPaints();
|
||||
initData();
|
||||
}
|
||||
|
||||
private void initPaints() {
|
||||
paintBackground = new Paint();
|
||||
paintBackground.setColor(getResources().getColor(R.color.accent_green_bg, null));
|
||||
paintBackground.setStyle(Paint.Style.FILL);
|
||||
|
||||
paintGrid = new Paint();
|
||||
paintGrid.setColor(getResources().getColor(R.color.divider, null));
|
||||
paintGrid.setStrokeWidth(1);
|
||||
paintGrid.setAlpha(100);
|
||||
|
||||
paintCurrentLocation = new Paint();
|
||||
paintCurrentLocation.setColor(getResources().getColor(R.color.primary, null));
|
||||
paintCurrentLocation.setStyle(Paint.Style.FILL);
|
||||
|
||||
paintDestination = new Paint();
|
||||
paintDestination.setColor(getResources().getColor(R.color.error, null));
|
||||
paintDestination.setStyle(Paint.Style.FILL);
|
||||
|
||||
paintPath = new Paint();
|
||||
paintPath.setColor(getResources().getColor(R.color.accent_orange_dark, null));
|
||||
paintPath.setStrokeWidth(6);
|
||||
paintPath.setStyle(Paint.Style.STROKE);
|
||||
|
||||
paintText = new Paint();
|
||||
paintText.setColor(Color.BLACK);
|
||||
paintText.setTextSize(24);
|
||||
paintText.setAntiAlias(true);
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
locations = new ArrayList<>();
|
||||
|
||||
// 添加一些示例位置点(使用相对坐标)
|
||||
locations.add(new LocationPoint("图书馆", 0, 100, "📚"));
|
||||
locations.add(new LocationPoint("第一食堂", 150, 50, "🍽️"));
|
||||
locations.add(new LocationPoint("第二食堂", -100, 80, "🍽️"));
|
||||
locations.add(new LocationPoint("教学楼A", 80, -50, "🏫"));
|
||||
locations.add(new LocationPoint("教学楼B", 120, -80, "🏫"));
|
||||
locations.add(new LocationPoint("实验楼", -80, -100, "🔬"));
|
||||
locations.add(new LocationPoint("体育馆", -150, 20, "🏃"));
|
||||
locations.add(new LocationPoint("宿舍区", 50, 150, "🏠"));
|
||||
|
||||
// 设置默认当前位置
|
||||
currentLocation = new LocationPoint("校门口", 0, 0, "📍");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
|
||||
// 绘制背景
|
||||
canvas.drawRect(0, 0, width, height, paintBackground);
|
||||
|
||||
// 绘制网格
|
||||
drawGrid(canvas, width, height);
|
||||
|
||||
// 绘制路径
|
||||
if (currentLocation != null && destination != null) {
|
||||
drawPath(canvas);
|
||||
}
|
||||
|
||||
// 绘制位置点
|
||||
for (LocationPoint point : locations) {
|
||||
drawLocationPoint(canvas, point, paintCurrentLocation);
|
||||
}
|
||||
|
||||
// 绘制当前位置
|
||||
if (currentLocation != null) {
|
||||
drawLocationPoint(canvas, currentLocation, paintCurrentLocation);
|
||||
}
|
||||
|
||||
// 绘制目标位置
|
||||
if (destination != null) {
|
||||
drawLocationPoint(canvas, destination, paintDestination);
|
||||
}
|
||||
|
||||
// 绘制图例
|
||||
drawLegend(canvas, width, height);
|
||||
}
|
||||
|
||||
private void drawGrid(Canvas canvas, int width, int height) {
|
||||
int gridSize = 50;
|
||||
|
||||
// 垂直线
|
||||
for (int x = 0; x < width; x += gridSize) {
|
||||
canvas.drawLine(x, 0, x, height, paintGrid);
|
||||
}
|
||||
|
||||
// 水平线
|
||||
for (int y = 0; y < height; y += gridSize) {
|
||||
canvas.drawLine(0, y, width, y, paintGrid);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawLocationPoint(Canvas canvas, LocationPoint point, Paint paint) {
|
||||
float screenX = centerX + point.x;
|
||||
float screenY = centerY - point.y; // Y轴翻转
|
||||
|
||||
// 绘制圆点
|
||||
canvas.drawCircle(screenX, screenY, 15, paint);
|
||||
|
||||
// 绘制标签
|
||||
String label = point.icon + " " + point.name;
|
||||
canvas.drawText(label, screenX - 50, screenY - 25, paintText);
|
||||
}
|
||||
|
||||
private void drawPath(Canvas canvas) {
|
||||
if (currentLocation == null || destination == null) return;
|
||||
|
||||
float startX = centerX + currentLocation.x;
|
||||
float startY = centerY - currentLocation.y;
|
||||
float endX = centerX + destination.x;
|
||||
float endY = centerY - destination.y;
|
||||
|
||||
canvas.drawLine(startX, startY, endX, endY, paintPath);
|
||||
}
|
||||
|
||||
private void drawLegend(Canvas canvas, int width, int height) {
|
||||
int legendX = 20;
|
||||
int legendY = height - 120;
|
||||
|
||||
// 绘制图例背景
|
||||
RectF legendRect = new RectF(legendX - 10, legendY - 10, legendX + 200, legendY + 80);
|
||||
Paint legendBg = new Paint();
|
||||
legendBg.setColor(Color.WHITE);
|
||||
legendBg.setAlpha(200);
|
||||
canvas.drawRect(legendRect, legendBg);
|
||||
|
||||
// 绘制图例内容
|
||||
canvas.drawText("📍 当前位置", legendX, legendY, paintText);
|
||||
canvas.drawText("🎯 目标位置", legendX, legendY + 25, paintText);
|
||||
canvas.drawText("📚🍽️🏫 校园位置", legendX, legendY + 50, paintText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
float touchX = event.getX();
|
||||
float touchY = event.getY();
|
||||
|
||||
// 检查是否点击了某个位置点
|
||||
LocationPoint clickedPoint = findClickedLocation(touchX, touchY);
|
||||
if (clickedPoint != null && onLocationClickListener != null) {
|
||||
onLocationClickListener.onLocationClicked(clickedPoint);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
private LocationPoint findClickedLocation(float touchX, float touchY) {
|
||||
for (LocationPoint point : locations) {
|
||||
float screenX = centerX + point.x;
|
||||
float screenY = centerY - point.y;
|
||||
|
||||
float distance = (float) Math.sqrt(
|
||||
Math.pow(touchX - screenX, 2) + Math.pow(touchY - screenY, 2)
|
||||
);
|
||||
|
||||
if (distance <= 30) { // 点击范围
|
||||
return point;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setCurrentLocation(String name, float x, float y) {
|
||||
currentLocation = new LocationPoint(name, x, y, "📍");
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setDestination(String name, float x, float y) {
|
||||
destination = new LocationPoint(name, x, y, "🎯");
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setOnLocationClickListener(OnLocationClickListener listener) {
|
||||
this.onLocationClickListener = listener;
|
||||
}
|
||||
|
||||
public void addLocation(String name, float x, float y, String icon) {
|
||||
locations.add(new LocationPoint(name, x, y, icon));
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void clearDestination() {
|
||||
destination = null;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 位置点数据类
|
||||
*/
|
||||
public static class LocationPoint {
|
||||
public String name;
|
||||
public float x, y;
|
||||
public String icon;
|
||||
|
||||
public LocationPoint(String name, float x, float y, String icon) {
|
||||
this.name = name;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.icon = icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@ -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>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="#80000000" />
|
||||
<size
|
||||
android:width="48dp"
|
||||
android:height="48dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="#EEEEEE" />
|
||||
</shape>
|
||||
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<size android:width="56dp" android:height="56dp" />
|
||||
<solid android:color="@color/error" />
|
||||
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
|
||||
</shape>
|
||||
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<size android:width="56dp" android:height="56dp" />
|
||||
<solid android:color="@color/primary" />
|
||||
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
|
||||
</shape>
|
||||
|
||||
|
||||
@ -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>
|
||||
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M19.14,12.94c0.04,-0.31 0.06,-0.63 0.06,-0.94s-0.02,-0.63 -0.06,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.4 0.12,-0.61l-1.92,-3.32c-0.11,-0.21 -0.36,-0.3 -0.58,-0.22l-2.39,0.96c-0.5,-0.38 -1.04,-0.7 -1.64,-0.94L14.5,2.5c-0.02,-0.23 -0.22,-0.41 -0.45,-0.41h-3.1c-0.23,0 -0.43,0.18 -0.45,0.41L10,4.33c-0.59,0.24 -1.14,0.56 -1.64,0.94L5.97,4.31c-0.22,-0.09 -0.47,0.01 -0.58,0.22L3.47,7.85c-0.11,0.21 -0.06,0.47 0.12,0.61l2.03,1.58c-0.04,0.31 -0.06,0.63 -0.06,0.94s0.02,0.63 0.06,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.4 -0.12,0.61l1.92,3.32c0.11,0.21 0.36,0.3 0.58,0.22l2.39,-0.96c0.5,0.38 1.04,0.7 1.64,0.94l0.5,1.83c0.02,0.23 0.22,0.41 0.45,0.41h3.1c0.23,0 0.43,-0.18 0.45,-0.41l0.5,-1.83c0.59,-0.24 1.14,-0.56 1.64,-0.94l2.39,0.96c0.22,0.09 0.47,-0.01 0.58,-0.22l1.92,-3.32c0.11,-0.21 0.06,-0.47 -0.12,-0.61l-2.03,-1.58zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/>
|
||||
</vector>
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#4CAF50" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/white" />
|
||||
<corners android:radius="16dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#E0E0E0" />
|
||||
</shape>
|
||||
@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background_secondary">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_url"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="输入教务系统网址"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_go"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="前往"
|
||||
android:textSize="14sp"
|
||||
android:backgroundTint="@color/button_secondary"
|
||||
android:textColor="@color/text_white"
|
||||
android:padding="8dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="3dp"
|
||||
android:max="100"
|
||||
android:progress="0"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_start_import"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="我已在课表页,开始导入"
|
||||
android:textSize="16sp"
|
||||
android:backgroundTint="@color/button_primary"
|
||||
android:textColor="@color/text_white"
|
||||
android:padding="12dp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_locate_timetable"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="自动定位课表"
|
||||
android:textSize="14sp"
|
||||
android:backgroundTint="@color/button_secondary"
|
||||
android:textColor="@color/text_white"
|
||||
android:padding="10dp"/>
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="8dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@ -0,0 +1,283 @@
|
||||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background_primary"
|
||||
android:padding="20dp">
|
||||
|
||||
<!-- 标题区域 -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="校园助手"
|
||||
android:textSize="28sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary"
|
||||
android:gravity="start"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginBottom="6dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="一站式校园生活"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:layout_marginBottom="18dp" />
|
||||
|
||||
<!-- 功能按钮网格 -->
|
||||
<GridLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:columnCount="2"
|
||||
android:rowCount="2"
|
||||
android:alignmentMode="alignMargins"
|
||||
android:columnOrderPreserved="false"
|
||||
android:useDefaultMargins="true">
|
||||
|
||||
<!-- 课表按钮 -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_timetable"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_row="0"
|
||||
android:layout_column="0"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp"
|
||||
app:strokeWidth="1dp"
|
||||
app:strokeColor="@color/border_light"
|
||||
android:clickable="true"
|
||||
android:foreground="?android:attr/selectableItemBackground">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="18dp">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:background="@drawable/bg_circle"
|
||||
android:backgroundTint="@color/primary_bg">
|
||||
<ImageView
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_gravity="center"
|
||||
android:tint="@color/primary_dark"
|
||||
android:src="@android:drawable/ic_menu_month" />
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="课程表"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="查看今日课程安排"
|
||||
android:textSize="13sp"
|
||||
android:textColor="@color/text_secondary" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- 笔记按钮 -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_notes"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_row="0"
|
||||
android:layout_column="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp"
|
||||
app:strokeWidth="1dp"
|
||||
app:strokeColor="@color/border_light"
|
||||
android:clickable="true"
|
||||
android:foreground="?android:attr/selectableItemBackground">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="18dp">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:background="@drawable/bg_circle"
|
||||
android:backgroundTint="@color/accent_green_bg">
|
||||
<ImageView
|
||||
android:layout_width="26dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_gravity="center"
|
||||
android:tint="@color/accent_green_dark"
|
||||
android:src="@android:drawable/ic_menu_edit" />
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="课程笔记"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="记录课堂灵感与作业"
|
||||
android:textSize="13sp"
|
||||
android:textColor="@color/text_secondary" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- 成绩按钮 -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_grades"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_row="1"
|
||||
android:layout_column="0"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp"
|
||||
app:strokeWidth="1dp"
|
||||
app:strokeColor="@color/border_light"
|
||||
android:clickable="true"
|
||||
android:foreground="?android:attr/selectableItemBackground">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="18dp">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:background="@drawable/bg_circle"
|
||||
android:backgroundTint="@color/accent_orange_bg">
|
||||
<ImageView
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_gravity="center"
|
||||
android:tint="@color/accent_orange_dark"
|
||||
android:src="@android:drawable/ic_menu_sort_by_size" />
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="成绩查询"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="导入并统计GPA"
|
||||
android:textSize="13sp"
|
||||
android:textColor="@color/text_secondary" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- 校园导航按钮 -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_campus"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_row="1"
|
||||
android:layout_column="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp"
|
||||
app:strokeWidth="1dp"
|
||||
app:strokeColor="@color/border_light"
|
||||
android:clickable="true"
|
||||
android:foreground="?android:attr/selectableItemBackground">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="18dp">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:background="@drawable/bg_circle"
|
||||
android:backgroundTint="@color/accent_purple_bg">
|
||||
<ImageView
|
||||
android:layout_width="26dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_gravity="center"
|
||||
android:tint="@color/accent_purple_dark"
|
||||
android:src="@android:drawable/ic_menu_mylocation" />
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="校园导航"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="找地点与路线指引"
|
||||
android:textSize="13sp"
|
||||
android:textColor="@color/text_secondary" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</GridLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
|
||||
@ -0,0 +1,129 @@
|
||||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- 顶部栏 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn_close"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="←"
|
||||
android:textSize="22sp"
|
||||
android:padding="4dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="编辑笔记"
|
||||
android:textStyle="bold"
|
||||
android:textSize="18sp"
|
||||
android:gravity="center" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 标题 -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="标题"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
app:boxBackgroundMode="outline">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- 关联课程 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="课程:"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner_course"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 内容 - 使用WebView实现富文本编辑 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webview_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<!-- 工具栏 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp"
|
||||
android:background="@color/background_secondary">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_insert_image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="插入图片"
|
||||
android:textColor="@color/primary"
|
||||
app:strokeColor="@color/primary"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end"
|
||||
android:layout_marginTop="12dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="取消" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_save"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="保存"
|
||||
android:layout_marginStart="12dp" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -0,0 +1,26 @@
|
||||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Light"
|
||||
app:titleTextColor="@color/text_primary"
|
||||
app:subtitleTextColor="@color/text_secondary"
|
||||
app:navigationIconTint="@color/text_primary"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 标题栏 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp"
|
||||
android:backgroundTint="@color/primary">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="教务系统登录"
|
||||
android:textSize="18sp"
|
||||
android:textColor="@color/text_white"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_close"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="关闭"
|
||||
android:textColor="@color/text_white"
|
||||
android:background="@android:color/transparent" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- WebView -->
|
||||
<WebView
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<!-- 解析状态显示 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_parsing_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp"
|
||||
android:background="@color/primary_light"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_parsing_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="正在解析数据..."
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/primary"
|
||||
android:gravity="center" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_parsing_count"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="已解析: 0 条数据"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="4dp" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_parsing"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 底部操作栏 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp"
|
||||
android:background="@color/background_secondary">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_navigate_to_grades"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="跳转到学业页面"
|
||||
android:textSize="12sp"
|
||||
android:padding="8dp"
|
||||
android:layout_marginEnd="4dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_parse_data"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="解析当前页面"
|
||||
android:textSize="12sp"
|
||||
android:padding="8dp"
|
||||
android:layout_marginStart="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -0,0 +1,224 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="24dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/add_course"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:hint="@string/course_name">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_course_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_error_course_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/error"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:hint="@string/course_teacher">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_course_teacher"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_error_course_teacher"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/error"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:hint="@string/course_location">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_course_location"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_error_course_location"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/error"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/week_day"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner_day_of_week"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/course_time_slot"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner_time_slot"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="周次范围"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="第"
|
||||
android:textSize="16sp"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner_start_week"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="周 至 第"
|
||||
android:textSize="16sp"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner_end_week"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="周"
|
||||
android:textSize="16sp"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginStart="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_reminder_settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="设置提醒"
|
||||
android:textSize="15sp"
|
||||
android:backgroundTint="@color/button_secondary"
|
||||
android:textColor="@color/text_white"
|
||||
android:padding="10dp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_reminder_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="未设置提醒"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end"
|
||||
android:layout_marginTop="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cancel"
|
||||
android:textSize="14sp"
|
||||
android:backgroundTint="@color/button_secondary"
|
||||
android:textColor="@color/text_white"
|
||||
android:padding="8dp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_save"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/save"
|
||||
android:textSize="14sp"
|
||||
android:backgroundTint="@color/button_primary"
|
||||
android:textColor="@color/text_white"
|
||||
android:padding="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="24dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_dialog_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/add_grade"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:hint="@string/grade_subject">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_subject"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text"
|
||||
android:maxLines="1" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:hint="@string/grade_score">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_score"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="numberDecimal"
|
||||
android:maxLines="1" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:hint="学分">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_credit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="numberDecimal"
|
||||
android:maxLines="1" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="学期"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner_semester"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="考试类型"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner_exam_type"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end"
|
||||
android:layout_marginTop="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cancel"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginEnd="8dp"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_save"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/save"
|
||||
android:textSize="16sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="24dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_dialog_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/add_note"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:hint="@string/note_title">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_note_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text"
|
||||
android:maxLines="1" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/link_to_course"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner_course"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:hint="@string/note_content">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_note_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
android:lines="6"
|
||||
android:gravity="top|start"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end"
|
||||
android:layout_marginTop="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cancel"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginEnd="8dp"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_save"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/save"
|
||||
android:textSize="16sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="教务系统导入"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- 学号输入 -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:hint="学号">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_student_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_error_student_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/error"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- 姓名输入 -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:hint="姓名">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_student_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPersonName" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_error_student_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/error"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- 验证码输入 -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:hint="验证码">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_verification_code"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_error_verification_code"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/error"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- 按钮 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_cancel_import"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="取消"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginEnd="8dp"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_confirm_import"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="确认导入"
|
||||
android:textSize="16sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout 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">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingTop="16dp">
|
||||
|
||||
<!-- 标题栏和筛选 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/notes_title"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_add_note"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@android:drawable/ic_input_add"
|
||||
android:backgroundTint="@color/primary"
|
||||
app:tint="@color/text_white"
|
||||
android:contentDescription="@string/add_note" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 课程筛选 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="筛选课程:"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner_course_filter"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 搜索笔记 -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_note_search"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="搜索笔记"
|
||||
app:startIconDrawable="@android:drawable/ic_menu_search"
|
||||
app:endIconMode="clear_text"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
app:boxBackgroundMode="outline"
|
||||
app:boxCornerRadiusTopStart="12dp"
|
||||
app:boxCornerRadiusTopEnd="12dp"
|
||||
app:boxCornerRadiusBottomStart="12dp"
|
||||
app:boxCornerRadiusBottomEnd="12dp"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_note_search"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:maxLines="1"
|
||||
android:imeOptions="actionSearch" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- 笔记列表 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_notes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<!-- 空状态提示 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="暂无笔记"
|
||||
android:textSize="18sp"
|
||||
android:textColor="@color/text_secondary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="点击右上角 + 号添加笔记"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:layout_marginTop="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
@ -0,0 +1,179 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:background="@color/background_secondary">
|
||||
|
||||
<!-- 课表管理标题 -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/timetable_title"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<!-- 标题栏:三个操作按钮等宽、样式统一 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_import_courses"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/import_from_education"
|
||||
android:textSize="14sp"
|
||||
android:backgroundTint="@color/button_secondary"
|
||||
android:textColor="@color/text_white"
|
||||
android:padding="8dp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_refresh"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="刷新"
|
||||
android:textSize="14sp"
|
||||
android:backgroundTint="@color/button_secondary"
|
||||
android:textColor="@color/text_white"
|
||||
android:padding="8dp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_clear_all"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="清空"
|
||||
android:textSize="14sp"
|
||||
android:backgroundTint="@color/button_danger"
|
||||
android:textColor="@color/text_white"
|
||||
android:padding="8dp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_add_course"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@android:drawable/ic_menu_add"
|
||||
android:backgroundTint="@color/button_secondary"
|
||||
android:tint="@color/text_white"
|
||||
android:contentDescription="@string/add_course" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 周视图切换 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_prev_week"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/prev_week"
|
||||
android:textSize="14sp"
|
||||
android:backgroundTint="@color/button_secondary"
|
||||
android:textColor="@color/text_white"
|
||||
android:padding="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_current_week"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/current_week"
|
||||
android:textAlignment="center"
|
||||
android:textSize="18sp"
|
||||
android:layout_margin="8dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_next_week"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/next_week"
|
||||
android:textSize="14sp"
|
||||
android:backgroundTint="@color/button_secondary"
|
||||
android:textColor="@color/text_white"
|
||||
android:padding="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 课表容器(包含星期标题和课程内容,同步滚动) -->
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/horizontal_scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:fillViewport="true"
|
||||
android:scrollbars="none">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 周标题行(周一~周日) -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_week_header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_time_header"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:textStyle="bold"
|
||||
android:text="" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/week_days_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 课表网格与课程块 -->
|
||||
<ScrollView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fillViewport="false"
|
||||
android:contentDescription="@string/timetable_scroll_description"
|
||||
tools:ignore="NestedScrolling">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/timetable_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp"
|
||||
android:background="@color/background_card"
|
||||
android:layout_margin="4dp"
|
||||
android:elevation="2dp">
|
||||
|
||||
<!-- 课程名称作为主标题 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_course_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="课程名称"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<!-- 课程信息行 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<!-- 课程编号 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_course_code"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="编号: 课程编号"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/text_secondary" />
|
||||
|
||||
<!-- 学分 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_credit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="学分: 学分"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/text_secondary" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 成绩信息行 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="4dp">
|
||||
|
||||
<!-- 成绩 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_score"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="成绩: 94"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/grade_good"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- 成绩输入(当成绩为空时显示) -->
|
||||
<EditText
|
||||
android:id="@+id/et_score_input"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:inputType="number"
|
||||
android:hint="请输入成绩"
|
||||
android:maxLength="3"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- 绩点 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_gpa"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="绩点: 4.0"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/grade_excellent"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 课程性质信息 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="课程性质: 必修课"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:layout_marginTop="4dp" />
|
||||
|
||||
<!-- 学年和学期信息 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="4dp">
|
||||
|
||||
<!-- 学年 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_year"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="学年: 2023-2024"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/text_secondary" />
|
||||
|
||||
<!-- 学期 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_term"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="学期: 1"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/text_secondary" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<!-- 左滑操作按钮(置于背景层,垂直堆叠圆形按钮) -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_swipe_actions"
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_vertical|end"
|
||||
android:background="@color/background_secondary"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btn_edit"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:src="@android:drawable/ic_menu_edit"
|
||||
android:tint="@color/text_white"
|
||||
android:background="@drawable/bg_circle_primary"
|
||||
android:backgroundTint="@null"
|
||||
android:contentDescription="编辑" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btn_delete"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:src="@android:drawable/ic_menu_delete"
|
||||
android:tint="@color/text_white"
|
||||
android:background="@drawable/bg_circle_danger"
|
||||
android:backgroundTint="@null"
|
||||
android:contentDescription="删除" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 主内容(置于前景层) -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="4dp"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_note_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="笔记标题"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_course_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="高等数学"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/text_white"
|
||||
android:background="@color/accent_green_light"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:layout_marginStart="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_note_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="笔记内容预览..."
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:layout_marginTop="8dp"
|
||||
android:maxLines="3"
|
||||
android:ellipsize="end" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_modify_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="修改时间"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/text_secondary" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</FrameLayout>
|
||||
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/nav_timetable"
|
||||
android:title="课表"
|
||||
android:icon="@mipmap/ic_launcher" />
|
||||
<item
|
||||
android:id="@+id/nav_notes"
|
||||
android:title="笔记"
|
||||
android:icon="@mipmap/ic_launcher" />
|
||||
<item
|
||||
android:id="@+id/nav_grades"
|
||||
android:title="成绩"
|
||||
android:icon="@mipmap/ic_launcher" />
|
||||
<item
|
||||
android:id="@+id/nav_campus"
|
||||
android:title="导航"
|
||||
android:icon="@mipmap/ic_launcher" />
|
||||
</menu>
|
||||
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<!-- 阅读界面不再提供编辑/删除按钮,菜单留空 -->
|
||||
</menu>
|
||||
|
||||
@ -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,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>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue