diff --git a/Coffeestore/.gitignore b/Coffeestore/.gitignore
new file mode 100644
index 0000000..aa724b7
--- /dev/null
+++ b/Coffeestore/.gitignore
@@ -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
diff --git a/Coffeestore/android b/Coffeestore/android
new file mode 160000
index 0000000..759ef60
--- /dev/null
+++ b/Coffeestore/android
@@ -0,0 +1 @@
+Subproject commit 759ef60a4e1e9b83ba8e8486677ea7c01a1928cb
diff --git a/Coffeestore/app/.gitignore b/Coffeestore/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/Coffeestore/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/Coffeestore/app/build.gradle b/Coffeestore/app/build.gradle
new file mode 100644
index 0000000..1c48638
--- /dev/null
+++ b/Coffeestore/app/build.gradle
@@ -0,0 +1,42 @@
+plugins {
+ id 'com.android.application'
+}
+
+android {
+
+
+ compileSdkVersion 33
+
+ defaultConfig {
+ applicationId "com.example.test"
+ minSdkVersion 16
+ targetSdkVersion 33
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+
+}
+
+dependencies {
+
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
+ testImplementation 'junit:junit:4.+'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+}
\ No newline at end of file
diff --git a/Coffeestore/app/debug/app-debug.apk b/Coffeestore/app/debug/app-debug.apk
new file mode 100644
index 0000000..2f6a5f5
Binary files /dev/null and b/Coffeestore/app/debug/app-debug.apk differ
diff --git a/Coffeestore/app/debug/output.json b/Coffeestore/app/debug/output.json
new file mode 100644
index 0000000..f20a39f
--- /dev/null
+++ b/Coffeestore/app/debug/output.json
@@ -0,0 +1 @@
+[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-debug.apk","fullName":"debug","baseName":"debug"},"path":"app-debug.apk","properties":{}}]
\ No newline at end of file
diff --git a/Coffeestore/app/proguard-rules.pro b/Coffeestore/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/Coffeestore/app/proguard-rules.pro
@@ -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
\ No newline at end of file
diff --git a/Coffeestore/app/src/androidTest/java/com/example/storage/ApplicationTest.java b/Coffeestore/app/src/androidTest/java/com/example/storage/ApplicationTest.java
new file mode 100644
index 0000000..02bd23e
--- /dev/null
+++ b/Coffeestore/app/src/androidTest/java/com/example/storage/ApplicationTest.java
@@ -0,0 +1,12 @@
+package com.example.storage;
+
+import android.app.Application;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/AndroidManifest.xml b/Coffeestore/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f197877
--- /dev/null
+++ b/Coffeestore/app/src/main/AndroidManifest.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/java/AndroidManifest.xml b/Coffeestore/app/src/main/java/AndroidManifest.xml
new file mode 100644
index 0000000..c083928
--- /dev/null
+++ b/Coffeestore/app/src/main/java/AndroidManifest.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/java/com/example/storage/Code.java b/Coffeestore/app/src/main/java/com/example/storage/Code.java
new file mode 100644
index 0000000..41d472a
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/Code.java
@@ -0,0 +1,148 @@
+package com.example.storage;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+
+import java.util.Random;
+
+/**
+ *
+ */
+
+public class Code {
+ /**
+ * 随机数数组
+ * 去除了易混淆的 数字 0 和 字母 o O
+ * 数字 1 和 字母 i I l L
+ * 数字 6 和 字母 b
+ * 数字 9 和 字母 q
+ * 字母 c C 和 G
+ * 字母 t (经常和随机线混在一起看不清)
+ */
+ private static final char[] CHARS = {
+ '2', '3', '4', '5', '7', '8',
+ 'a', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm',
+ 'n', 'p', 'r', 's', 'u', 'v', 'w', 'x', 'y', 'z',
+ 'A', 'B', 'D', 'E', 'F', 'H', 'J', 'K', 'M',
+ 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
+ };
+
+ private static Code bmpCode;
+
+ public static Code getInstance() {
+ if(bmpCode == null)
+ bmpCode = new Code();
+ return bmpCode;
+ }
+
+ //default settings
+ //验证码默认随机数的个数
+ private static final int DEFAULT_CODE_LENGTH = 4;
+ //默认字体大小
+ private static final int DEFAULT_FONT_SIZE = 25;
+ //默认线条的条数
+ private static final int DEFAULT_LINE_NUMBER = 5;
+ //padding值
+ private static final int BASE_PADDING_LEFT = 10, RANGE_PADDING_LEFT = 15, BASE_PADDING_TOP = 15, RANGE_PADDING_TOP = 20;
+ //验证码的默认宽高
+ private static final int DEFAULT_WIDTH = 100, DEFAULT_HEIGHT = 40;
+
+ //settings decided by the layout xml
+ //canvas width and height
+ private int width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT;
+
+ //random word space and pading_top
+ private int base_padding_left = BASE_PADDING_LEFT, range_padding_left = RANGE_PADDING_LEFT,
+ base_padding_top = BASE_PADDING_TOP, range_padding_top = RANGE_PADDING_TOP;
+
+ //number of chars, lines; font size
+ private int codeLength = DEFAULT_CODE_LENGTH, line_number = DEFAULT_LINE_NUMBER, font_size = DEFAULT_FONT_SIZE;
+
+ //variables
+ private String code;
+ private int padding_left, padding_top;
+ private Random random = new Random();
+ //验证码图片
+ public Bitmap createBitmap() {
+ padding_left = 0;
+
+ Bitmap bp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(bp);
+
+ code = createCode();
+
+ c.drawColor(Color.WHITE);
+ Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setTextSize(font_size);
+ //画验证码
+ for (int i = 0; i < code.length(); i++) {
+ randomTextStyle(paint);
+ randomPadding();
+ c.drawText(code.charAt(i) + "", padding_left, padding_top, paint);
+ }
+ //画线条
+ for (int i = 0; i < line_number; i++) {
+ drawLine(c, paint);
+ }
+
+// c.save( Canvas.ALL_SAVE_FLAG );//保存
+ c.save();//保存
+ c.restore();//
+ return bp;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ //生成验证码
+ private String createCode() {
+ StringBuilder buffer = new StringBuilder();
+ for (int i = 0; i < codeLength; i++) {
+ buffer.append(CHARS[random.nextInt(CHARS.length)]);
+ }
+ return buffer.toString();
+ }
+ //画干扰线
+ private void drawLine(Canvas canvas, Paint paint) {
+ int color = randomColor();
+ int startX = random.nextInt(width);
+ int startY = random.nextInt(height);
+ int stopX = random.nextInt(width);
+ int stopY = random.nextInt(height);
+ paint.setStrokeWidth(1);
+ paint.setColor(color);
+ canvas.drawLine(startX, startY, stopX, stopY, paint);
+ }
+ //生成随机颜色
+ private int randomColor() {
+ return randomColor(1);
+ }
+
+ private int randomColor(int rate) {
+ int red = random.nextInt(256) / rate;
+ int green = random.nextInt(256) / rate;
+ int blue = random.nextInt(256) / rate;
+ return Color.rgb(red, green, blue);
+ }
+ //随机生成文字样式,颜色,粗细,倾斜度
+ private void randomTextStyle(Paint paint) {
+ int color = randomColor();
+ paint.setColor(color);
+ paint.setFakeBoldText(random.nextBoolean()); //true为粗体,false为非粗体
+ float skewX = random.nextInt(11) / 10;
+ skewX = random.nextBoolean() ? skewX : -skewX;
+ paint.setTextSkewX(skewX); //float类型参数,负数表示右斜,整数左斜
+ //paint.setUnderlineText(true); //true为下划线,false为非下划线
+ //paint.setStrikeThruText(true); //true为删除线,false为非删除线
+ }
+ //随机生成padding值
+ private void randomPadding() {
+ padding_left += base_padding_left + random.nextInt(range_padding_left);
+ padding_top = base_padding_top + random.nextInt(range_padding_top);
+ }
+}
+
diff --git a/Coffeestore/app/src/main/java/com/example/storage/DBOpenHelper.java b/Coffeestore/app/src/main/java/com/example/storage/DBOpenHelper.java
new file mode 100644
index 0000000..41ee580
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/DBOpenHelper.java
@@ -0,0 +1,85 @@
+package com.example.storage;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+import java.util.ArrayList;
+/**
+ *
+ */
+
+public class DBOpenHelper extends SQLiteOpenHelper {
+ /**
+ * 声明一个AndroidSDK自带的数据库变量db
+ */
+ private SQLiteDatabase db;
+
+ /**
+ * 写一个这个类的构造函数,参数为上下文context,所谓上下文就是这个类所在包的路径
+ * 指明上下文,数据库名,工厂默认空值,版本号默认从1开始
+ * super(context,"db_test",null,1);
+ * 把数据库设置成可写入状态,除非内存已满,那时候会自动设置为只读模式
+ * 不过,以现如今的内存容量,估计一辈子也见不到几次内存占满的状态
+ * db = getReadableDatabase();
+ */
+ public DBOpenHelper(Context context){
+ super(context,"db_test",null,1);
+ db = getReadableDatabase();
+ }
+
+ /**
+ * 重写两个必须要重写的方法,因为class DBOpenHelper extends SQLiteOpenHelper
+ * 而这两个方法是 abstract 类 SQLiteOpenHelper 中声明的 abstract 方法
+ * 所以必须在子类 DBOpenHelper 中重写 abstract 方法
+ * 想想也是,为啥规定这么死必须重写?
+ * 因为,一个数据库表,首先是要被创建的,然后免不了是要进行增删改操作的
+ * 所以就有onCreate()、onUpgrade()两个方法
+ * @param db
+ */
+ @Override
+ public void onCreate(SQLiteDatabase db){
+ db.execSQL("CREATE TABLE IF NOT EXISTS user(" +
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
+ "name TEXT," +
+ "password TEXT)");
+ }
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
+ db.execSQL("DROP TABLE IF EXISTS user");
+ onCreate(db);
+ }
+ /**
+ * 接下来写自定义的增删改查方法
+ * add()
+ * delete()
+ * update()
+ * getAllData()
+ */
+ public void add(String name,String password){
+ db.execSQL("INSERT INTO user (name,password) VALUES(?,?)",new Object[]{name,password});
+ }
+ public void delete(String name,String password){
+ db.execSQL("DELETE FROM user WHERE name = AND password ="+name+password);
+ }
+ public void updata(String password){
+ db.execSQL("UPDATE user SET password = ?",new Object[]{password});
+ }
+
+ /**
+ * @return
+ */
+ public ArrayList getAllData(){
+
+ ArrayList list = new ArrayList();
+ Cursor cursor = db.query("user",null,null,null,null,null,"name DESC");
+ while(cursor.moveToNext()){
+ @SuppressLint("Range") String name = cursor.getString(cursor.getColumnIndex("name"));
+ @SuppressLint("Range") String password = cursor.getString(cursor.getColumnIndex("password"));
+ list.add(new User(name,password));
+ }
+ return list;
+ }
+}
diff --git a/Coffeestore/app/src/main/java/com/example/storage/LoginActivity.java b/Coffeestore/app/src/main/java/com/example/storage/LoginActivity.java
new file mode 100644
index 0000000..b9d2795
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/LoginActivity.java
@@ -0,0 +1,117 @@
+package com.example.storage;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import java.util.ArrayList;
+
+public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
+ /**
+ * 声明自己写的 DBOpenHelper 对象
+ * DBOpenHelper(extends SQLiteOpenHelper) 主要用来
+ * 创建数据表
+ * 然后再进行数据表的增、删、改、查操作
+ */
+ private DBOpenHelper mDBOpenHelper;
+ private TextView mTvLoginactivityRegister;
+ private RelativeLayout mRlLoginactivityTop;
+ private EditText mEtLoginactivityUsername;
+ private EditText mEtLoginactivityPassword;
+ private LinearLayout mLlLoginactivityTwo;
+ private Button mBtLoginactivityLogin;
+
+ /**
+ * 创建 Activity 时先来重写 onCreate() 方法
+ * 保存实例状态
+ * super.onCreate(savedInstanceState);
+ * 设置视图内容的配置文件
+ * setContentView(R.layout.activity_login);
+ * 上面这行代码真正实现了把视图层 View 也就是 layout 的内容放到 Activity 中进行显示
+ * 初始化视图中的控件对象 initView()
+ * 实例化 DBOpenHelper,待会进行登录验证的时候要用来进行数据查询
+ * mDBOpenHelper = new DBOpenHelper(this);
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_login);
+
+ initView();
+
+ mDBOpenHelper = new DBOpenHelper(this);
+ }
+
+ /**
+ * onCreae()中大的布局已经摆放好了,接下来就该把layout里的东西
+ * 声明、实例化对象然后有行为的赋予其行为
+ * 这样就可以把视图层View也就是layout 与 控制层 Java 结合起来了
+ */
+ private void initView() {
+ // 初始化控件
+ mBtLoginactivityLogin = findViewById(R.id.bt_loginactivity_login);
+ mTvLoginactivityRegister = findViewById(R.id.tv_loginactivity_register);
+ mRlLoginactivityTop = findViewById(R.id.rl_loginactivity_top);
+ mEtLoginactivityUsername = findViewById(R.id.et_loginactivity_username);
+ mEtLoginactivityPassword = findViewById(R.id.et_loginactivity_password);
+ mLlLoginactivityTwo = findViewById(R.id.ll_loginactivity_two);
+
+ // 设置点击事件监听器
+ mBtLoginactivityLogin.setOnClickListener(this);
+ mTvLoginactivityRegister.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ // 跳转到注册界面
+ case R.id.tv_loginactivity_register:
+ startActivity(new Intent(this, RegisterActivity.class));
+ finish();
+ break;
+ /**
+ * 登录验证:
+ *
+ */
+ case R.id.bt_loginactivity_login:
+ String name = mEtLoginactivityUsername.getText().toString().trim();
+ String password = mEtLoginactivityPassword.getText().toString().trim();
+ if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(password)) {
+ ArrayList data = mDBOpenHelper.getAllData();
+ boolean match = false;
+ for (int i = 0; i < data.size(); i++) {
+ User user = data.get(i);
+ if (name.equals(user.getName()) && password.equals(user.getPassword())) {
+ match = true;
+ break;
+ } else {
+ match = false;
+ }
+ }
+ if (match) {
+ Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
+ Intent intent = new Intent(this, ShoppingCartActivity.class);
+ startActivity(intent);
+ finish();//销毁此Activity
+ } else {
+ Toast.makeText(this, "用户名或密码不正确,请重新输入", Toast.LENGTH_SHORT).show();
+ }
+ } else {
+ Toast.makeText(this, "请输入你的用户名或密码", Toast.LENGTH_SHORT).show();
+ }
+ break;
+ }
+ }
+}
+
+
+
diff --git a/Coffeestore/app/src/main/java/com/example/storage/MainApplication.java b/Coffeestore/app/src/main/java/com/example/storage/MainApplication.java
new file mode 100644
index 0000000..6ced314
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/MainApplication.java
@@ -0,0 +1,40 @@
+package com.example.storage;
+
+import java.util.HashMap;
+
+import android.app.Application;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.util.Log;
+
+
+public class MainApplication extends Application {
+ private final static String TAG = "MainApplication";
+ // 声明一个当前应用的静态实例
+ private static MainApplication mApp;
+ // 声明一个公共的图标映射对象,可当作全局变量使用
+ public HashMap mIconMap = new HashMap();
+
+ // 利用单例模式获取当前应用的唯一实例
+ public static MainApplication getInstance() {
+ return mApp;
+ }
+
+
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ // 在打开应用时对静态的应用实例赋值
+ mApp = this;
+ Log.d(TAG, "onCreate");
+ }
+
+ @Override
+ public void onTerminate() {
+ Log.d(TAG, "onTerminate");
+ super.onTerminate();
+ }
+
+
+}
diff --git a/Coffeestore/app/src/main/java/com/example/storage/RegisterActivity.java b/Coffeestore/app/src/main/java/com/example/storage/RegisterActivity.java
new file mode 100644
index 0000000..2a88347
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/RegisterActivity.java
@@ -0,0 +1,102 @@
+package com.example.storage;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.Toast;
+
+public class RegisterActivity extends AppCompatActivity implements View.OnClickListener {
+
+ private String realCode;
+ private DBOpenHelper mDBOpenHelper;
+ private Button mBtRegisteractivityRegister;
+ private RelativeLayout mRlRegisteractivityTop;
+ private ImageView mIvRegisteractivityBack;
+ private LinearLayout mLlRegisteractivityBody;
+ private EditText mEtRegisteractivityUsername;
+ private EditText mEtRegisteractivityPassword1;
+ private EditText mEtRegisteractivityPassword2;
+ private EditText mEtRegisteractivityPhonecodes;
+ private ImageView mIvRegisteractivityShowcode;
+ private RelativeLayout mRlRegisteractivityBottom;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_register);
+
+ initView();
+
+ mDBOpenHelper = new DBOpenHelper(this);
+
+ //将验证码用图片的形式显示出来
+ mIvRegisteractivityShowcode.setImageBitmap(Code.getInstance().createBitmap());
+ realCode = Code.getInstance().getCode().toLowerCase();
+ }
+
+ private void initView(){
+ mBtRegisteractivityRegister = findViewById(R.id.bt_registeractivity_register);
+ mRlRegisteractivityTop = findViewById(R.id.rl_registeractivity_top);
+ mIvRegisteractivityBack = findViewById(R.id.iv_registeractivity_back);
+ mLlRegisteractivityBody = findViewById(R.id.ll_registeractivity_body);
+ mEtRegisteractivityUsername = findViewById(R.id.et_registeractivity_username);
+ mEtRegisteractivityPassword1 = findViewById(R.id.et_registeractivity_password1);
+ mEtRegisteractivityPassword2 = findViewById(R.id.et_registeractivity_password2);
+ mEtRegisteractivityPhonecodes = findViewById(R.id.et_registeractivity_phoneCodes);
+ mIvRegisteractivityShowcode = findViewById(R.id.iv_registeractivity_showCode);
+ mRlRegisteractivityBottom = findViewById(R.id.rl_registeractivity_bottom);
+
+ /**
+ * 注册页面能点击的就三个地方
+ * top处返回箭头、刷新验证码图片、注册按钮
+ */
+ mIvRegisteractivityBack.setOnClickListener(this);
+ mIvRegisteractivityShowcode.setOnClickListener(this);
+ mBtRegisteractivityRegister.setOnClickListener(this);
+ }
+
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.iv_registeractivity_back: //返回登录页面
+ Intent intent1 = new Intent(this, LoginActivity.class);
+ startActivity(intent1);
+ finish();
+ break;
+ case R.id.iv_registeractivity_showCode: //改变随机验证码的生成
+ mIvRegisteractivityShowcode.setImageBitmap(Code.getInstance().createBitmap());
+ realCode = Code.getInstance().getCode().toLowerCase();
+ break;
+ case R.id.bt_registeractivity_register: //注册按钮
+ //获取用户输入的用户名、密码、验证码
+ String username = mEtRegisteractivityUsername.getText().toString().trim();
+ String password = mEtRegisteractivityPassword2.getText().toString().trim();
+ String phoneCode = mEtRegisteractivityPhonecodes.getText().toString().toLowerCase();
+ //注册验证
+ if (!TextUtils.isEmpty(username) && !TextUtils.isEmpty(password) && !TextUtils.isEmpty(phoneCode) ) {
+ if (phoneCode.equals(realCode)) {
+ //将用户名和密码加入到数据库中
+ mDBOpenHelper.add(username, password);
+ Intent intent2 = new Intent(this, LoginActivity.class);
+ startActivity(intent2);
+ finish();
+ Toast.makeText(this, "验证通过,注册成功", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(this, "验证码错误,注册失败", Toast.LENGTH_SHORT).show();
+ }
+ }else {
+ Toast.makeText(this, "未完善信息,注册失败", Toast.LENGTH_SHORT).show();
+ }
+ break;
+ }
+ }
+}
+
diff --git a/Coffeestore/app/src/main/java/com/example/storage/ShoppingCartActivity.java b/Coffeestore/app/src/main/java/com/example/storage/ShoppingCartActivity.java
new file mode 100644
index 0000000..f06ffc1
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/ShoppingCartActivity.java
@@ -0,0 +1,382 @@
+package com.example.storage;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.Environment;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.Gravity;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup.LayoutParams;
+import android.view.Window;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.storage.bean.CartInfo;
+import com.example.storage.bean.GoodsInfo;
+import com.example.storage.database.CartDBHelper;
+import com.example.storage.database.GoodsDBHelper;
+import com.example.storage.util.FileUtil;
+import com.example.storage.util.SharedUtil;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+
+
+@SuppressLint("SetTextI18n")
+public class ShoppingCartActivity extends Activity implements OnClickListener {
+ private final static String TAG = "ShoppingCartActivity";
+ private ImageView iv_menu;
+ private TextView tv_count;
+ private TextView tv_total_price;
+ private LinearLayout ll_content;
+ private LinearLayout ll_cart;
+ private LinearLayout ll_empty;
+ private int mCount; // 购物车中的商品数量
+ private GoodsDBHelper mGoodsHelper; // 声明一个商品数据库的帮助器对象
+ private CartDBHelper mCartHelper; // 声明一个购物车数据库的帮助器对象
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.activity_shopping_cart);
+ iv_menu = findViewById(R.id.iv_menu);
+ TextView tv_title = findViewById(R.id.tv_title);
+ tv_count = findViewById(R.id.tv_count);
+ tv_total_price = findViewById(R.id.tv_total_price);
+ ll_content = findViewById(R.id.ll_content);
+ ll_cart = findViewById(R.id.ll_cart);
+ ll_empty = findViewById(R.id.ll_empty);
+ iv_menu.setOnClickListener(this);
+ findViewById(R.id.btn_shopping_channel).setOnClickListener(this);
+ findViewById(R.id.btn_settle).setOnClickListener(this);
+ findViewById(R.id.btn_shopping_grzx).setOnClickListener(this);
+ iv_menu.setVisibility(View.VISIBLE);
+ tv_title.setText("盲盒咖啡店");
+ }
+
+ // 显示购物车图标中的商品数量
+ private void showCount(int count) {
+ mCount = count;
+ tv_count.setText("" + mCount);
+ if (mCount == 0) {
+ ll_content.setVisibility(View.GONE);
+ ll_cart.removeAllViews();
+ ll_empty.setVisibility(View.VISIBLE);
+ } else {
+ ll_content.setVisibility(View.VISIBLE);
+ ll_empty.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v.getId() == R.id.iv_menu) { // 点击了菜单图标
+ openOptionsMenu();
+ } else if (v.getId() == R.id.btn_shopping_channel) { // 点击了“商场”按钮
+ // 跳转到商场页面
+ Intent intent = new Intent(this, ShoppingChannelActivity.class);
+ startActivity(intent);
+ } else if (v.getId() == R.id.btn_settle) { // 点击了“结算”按钮
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("结算商品");
+ builder.setMessage("支付成功!");
+ builder.setPositiveButton("好的", null);
+ builder.create().show();
+ }
+ else if (v.getId() == R.id.btn_shopping_grzx) {
+ // 跳转到个人中心页面
+ Intent intent = new Intent(this, UserActivity.class);
+ startActivity(intent);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // 从menu_cart.xml中构建菜单界面布局
+ getMenuInflater().inflate(R.menu.menu_cart, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ if (id == R.id.menu_shopping) { // 点击了菜单项“去商场购物”
+ // 跳转到商场页面
+ Intent intent = new Intent(this, ShoppingChannelActivity.class);
+ startActivity(intent);
+ } else if (id == R.id.menu_clear) { // 点击了菜单项“清空购物车”
+ // 清空购物车数据库
+ mCartHelper.deleteAll();
+ ll_cart.removeAllViews();
+ // 把最新的商品数量写入共享参数
+ SharedUtil.getIntance(this).writeShared("count", "0");
+ // 显示最新的商品数量
+ showCount(0);
+ mCartGoods.clear();
+ mGoodsMap.clear();
+ Toast.makeText(this, "购物车已清空", Toast.LENGTH_SHORT).show();
+ } else if (id == R.id.menu_return) { // 点击了菜单项“返回”
+ finish();
+ }
+ return true;
+ }
+
+ // 声明一个根据视图编号查找商品信息的映射
+ private HashMap mCartGoods = new HashMap();
+ // 声明一个触发上下文菜单的视图对象
+ private View mContextView;
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+ // 保存该商品行的视图,以便删除商品时一块从列表移除该行
+ mContextView = v;
+ // 从menu_goods.xml中构建菜单界面布局
+ getMenuInflater().inflate(R.menu.menu_goods, menu);
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ CartInfo info = mCartGoods.get(mContextView.getId());
+ int id = item.getItemId();
+ if (id == R.id.menu_detail) { // 点击了菜单项“查看商品详情”
+ // 跳转到查看商品详情页面
+ goDetail(info.goods_id);
+ } else if (id == R.id.menu_delete) { // 点击了菜单项“从购物车删除”
+ long goods_id = info.goods_id;
+ // 从购物车删除商品的数据库操作
+ mCartHelper.delete("goods_id=" + goods_id);
+ // 从购物车列表中删除该商品行
+ ll_cart.removeView(mContextView);
+ // 更新购物车中的商品数量
+ int left_count = mCount - info.count;
+ for (int i = 0; i < mCartArray.size(); i++) {
+ if (goods_id == mCartArray.get(i).goods_id) {
+ left_count = mCount - mCartArray.get(i).count;
+ mCartArray.remove(i);
+ break;
+ }
+ }
+ // 把最新的商品数量写入共享参数
+ SharedUtil.getIntance(this).writeShared("count", "" + left_count);
+ // 显示最新的商品数量
+ showCount(left_count);
+ Toast.makeText(this, "已从购物车删除" + mGoodsMap.get(goods_id).name, Toast.LENGTH_SHORT).show();
+ mGoodsMap.remove(goods_id);
+ refreshTotalPrice();
+ }
+ return true;
+ }
+
+ // 跳转到商品详情页面
+ private void goDetail(long rowid) {
+ Intent intent = new Intent(this, ShoppingDetailActivity.class);
+ intent.putExtra("goods_id", rowid);
+ startActivity(intent);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 获取共享参数保存的购物车中的商品数量
+ mCount = Integer.parseInt(SharedUtil.getIntance(this).readShared("count", "0"));
+ showCount(mCount);
+ // 获取商品数据库的帮助器对象
+ mGoodsHelper = GoodsDBHelper.getInstance(this, 1);
+ // 打开商品数据库的写连接
+ mGoodsHelper.openWriteLink();
+ // 获取购物车数据库的帮助器对象
+ mCartHelper = CartDBHelper.getInstance(this, 1);
+ // 打开购物车数据库的写连接
+ mCartHelper.openWriteLink();
+ // 模拟从网络下载商品图片
+ downloadGoods();
+ // 展示购物车中的商品列表
+ showCart();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 关闭商品数据库的数据库连接
+ mGoodsHelper.closeLink();
+ // 关闭购物车数据库的数据库连接
+ mCartHelper.closeLink();
+ }
+
+ // 声明一个起始的视图编号
+ private int mBeginViewId = 0x7F24FFF0;
+ // 声明一个购物车中的商品信息队列
+ private ArrayList mCartArray = new ArrayList();
+ // 声明一个根据商品编号查找商品信息的映射
+ private HashMap mGoodsMap = new HashMap();
+
+ // 展示购物车中的商品列表
+ private void showCart() {
+ // 查询购物车数据库中所有的商品记录
+ mCartArray = mCartHelper.query("1=1");
+ Log.d(TAG, "mCartArray.size()=" + mCartArray.size());
+ if (mCartArray == null || mCartArray.size() <= 0) {
+ return;
+ }
+ // 移除线性视图ll_cart下面的所有子视图
+ ll_cart.removeAllViews();
+ // 创建一个标题行的线性视图ll_row
+ LinearLayout ll_row = newLinearLayout(LinearLayout.HORIZONTAL, LayoutParams.WRAP_CONTENT);
+ ll_row.addView(newTextView(0, 2, Gravity.CENTER, "图片", Color.BLACK, 15));
+ ll_row.addView(newTextView(0, 3, Gravity.CENTER, "名称", Color.BLACK, 15));
+ ll_row.addView(newTextView(0, 1, Gravity.CENTER, "数量", Color.BLACK, 15));
+ ll_row.addView(newTextView(0, 1, Gravity.CENTER, "单价", Color.BLACK, 15));
+ ll_row.addView(newTextView(0, 1, Gravity.CENTER, "总价", Color.BLACK, 15));
+ // 把标题行添加到购物车列表
+ ll_cart.addView(ll_row);
+ for (int i = 0; i < mCartArray.size(); i++) {
+ final CartInfo info = mCartArray.get(i);
+ // 根据商品编号查询商品数据库中的商品记录
+ GoodsInfo goods = mGoodsHelper.queryById(info.goods_id);
+ Log.d(TAG, "name=" + goods.name + ",price=" + goods.price + ",desc=" + goods.desc);
+ mGoodsMap.put(info.goods_id, goods);
+ // 创建该商品行的水平线性视图,从左到右依次为商品小图、商品名称与描述、商品数量、商品单价、商品总价。
+ ll_row = newLinearLayout(LinearLayout.HORIZONTAL, LayoutParams.WRAP_CONTENT);
+ // 设置该线性视图的编号
+ ll_row.setId(mBeginViewId + i);
+ // 添加商品小图
+ ImageView iv_thumb = new ImageView(this);
+ LinearLayout.LayoutParams iv_params = new LinearLayout.LayoutParams(
+ 0, LayoutParams.WRAP_CONTENT, 2);
+ iv_thumb.setLayoutParams(iv_params);
+ iv_thumb.setScaleType(ScaleType.FIT_CENTER);
+ iv_thumb.setImageBitmap(MainApplication.getInstance().mIconMap.get(info.goods_id));
+ ll_row.addView(iv_thumb);
+ // 添加商品名称与描述
+ LinearLayout ll_name = new LinearLayout(this);
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ 0, LayoutParams.MATCH_PARENT, 3);
+ ll_name.setLayoutParams(params);
+ ll_name.setOrientation(LinearLayout.VERTICAL);
+ ll_name.addView(newTextView(-3, 1, Gravity.LEFT, goods.name, Color.BLACK, 17));
+ ll_name.addView(newTextView(-3, 1, Gravity.LEFT, goods.desc, Color.GRAY, 12));
+ ll_row.addView(ll_name);
+ // 添加商品数量、单价和总价
+ ll_row.addView(newTextView(1, 1, Gravity.CENTER, "" + info.count, Color.BLACK, 17));
+ ll_row.addView(newTextView(1, 1, Gravity.RIGHT, "" + (int) goods.price, Color.BLACK, 15));
+ ll_row.addView(newTextView(1, 1, Gravity.RIGHT, "" + (int) (info.count * goods.price), Color.RED, 17));
+ // 给商品行添加点击事件
+ ll_row.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ goDetail(info.goods_id);
+ }
+ });
+ // 给商品行注册上下文菜单,为防止重复注册,这里先注销再注册
+ unregisterForContextMenu(ll_row);
+ registerForContextMenu(ll_row);
+ mCartGoods.put(ll_row.getId(), info);
+ // 往购物车列表添加该商品行
+ ll_cart.addView(ll_row);
+ }
+ // 重新计算购物车中的商品总金额
+ refreshTotalPrice();
+ }
+
+ // 重新计算购物车中的商品总金额
+ private void refreshTotalPrice() {
+ int total_price = 0;
+ for (CartInfo info : mCartArray) {
+ GoodsInfo goods = mGoodsMap.get(info.goods_id);
+ total_price += goods.price * info.count;
+ }
+ tv_total_price.setText("" + total_price);
+ }
+
+ // 创建一个线性视图的框架
+ private LinearLayout newLinearLayout(int orientation, int height) {
+ LinearLayout ll_new = new LinearLayout(this);
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, height);
+ ll_new.setLayoutParams(params);
+ ll_new.setOrientation(orientation);
+ ll_new.setBackgroundColor(Color.WHITE);
+ return ll_new;
+ }
+
+ // 创建一个文本视图的模板
+ private TextView newTextView(int height, float weight, int gravity, String text, int textColor, int textSize) {
+ TextView tv_new = new TextView(this);
+ if (height == -3) { // 垂直排列
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, 0, weight);
+ tv_new.setLayoutParams(params);
+ } else { // 水平排列
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ 0, (height == 0) ? LayoutParams.WRAP_CONTENT : LayoutParams.MATCH_PARENT, weight);
+ tv_new.setLayoutParams(params);
+ }
+ tv_new.setText(text);
+ tv_new.setTextColor(textColor);
+ tv_new.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
+ tv_new.setGravity(Gravity.CENTER | gravity);
+ return tv_new;
+ }
+
+ private String mFirst = "true"; // 是否首次打开
+ // 模拟网络数据,初始化数据库中的商品信息
+ private void downloadGoods() {
+ // 获取共享参数保存的是否首次打开参数
+ mFirst = SharedUtil.getIntance(this).readShared("first", "true");
+ // 获取当前App的私有存储路径
+ String path = MainApplication.getInstance().getExternalFilesDir(
+ Environment.DIRECTORY_DOWNLOADS).toString() + "/";
+ if (mFirst.equals("true")) { // 如果是首次打开
+ ArrayList goodsList = GoodsInfo.getDefaultList();
+ for (int i = 0; i < goodsList.size(); i++) {
+ GoodsInfo info = goodsList.get(i);
+ // 往商品数据库插入一条该商品的记录
+ long rowid = mGoodsHelper.insert(info);
+ info.rowid = rowid;
+ // 往全局内存写入商品小图
+ Bitmap thumb = BitmapFactory.decodeResource(getResources(), info.thumb);
+ MainApplication.getInstance().mIconMap.put(rowid, thumb);
+ String thumb_path = path + rowid + "_s.jpg";
+ FileUtil.saveImage(thumb_path, thumb);
+ info.thumb_path = thumb_path; // 往SD卡保存商品大图
+ Bitmap pic = BitmapFactory.decodeResource(getResources(), info.pic);
+ String pic_path = path + rowid + ".jpg";
+ FileUtil.saveImage(pic_path, pic);
+ pic.recycle();
+ info.pic_path = pic_path;
+ // 更新商品数据库中该商品记录的图片路径
+ mGoodsHelper.update(info);
+ }
+ } else { // 不是首次打开
+ // 查询商品数据库中所有商品记录
+ ArrayList goodsArray = mGoodsHelper.query("1=1");
+ for (int i = 0; i < goodsArray.size(); i++) {
+ GoodsInfo info = goodsArray.get(i);
+ // 从指定路径读取图片文件的位图数据
+ Bitmap thumb = BitmapFactory.decodeFile(info.thumb_path);
+ // 把该位图对象保存到应用实例的全局变量中
+ MainApplication.getInstance().mIconMap.put(info.rowid, thumb);
+ }
+ }
+ // 把是否首次打开写入共享参数
+ SharedUtil.getIntance(this).writeShared("first", "false");
+ }
+
+}
diff --git a/Coffeestore/app/src/main/java/com/example/storage/ShoppingChannelActivity.java b/Coffeestore/app/src/main/java/com/example/storage/ShoppingChannelActivity.java
new file mode 100644
index 0000000..b2dbe68
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/ShoppingChannelActivity.java
@@ -0,0 +1,203 @@
+package com.example.storage;
+
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.example.storage.bean.CartInfo;
+import com.example.storage.bean.GoodsInfo;
+import com.example.storage.database.CartDBHelper;
+import com.example.storage.database.GoodsDBHelper;
+import com.example.storage.util.DateUtil;
+import com.example.storage.util.SharedUtil;
+import com.example.storage.util.Utils;
+
+import java.util.ArrayList;
+
+
+@SuppressLint("SetTextI18n")
+public class ShoppingChannelActivity extends AppCompatActivity implements OnClickListener {
+ private TextView tv_count;
+ private LinearLayout ll_channel;
+ private int mCount; // 购物车中的商品数量
+ private GoodsDBHelper mGoodsHelper; // 声明一个商品数据库的帮助器对象
+ private CartDBHelper mCartHelper; // 声明一个购物车数据库的帮助器对象
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_shopping_channel);
+ TextView tv_title = findViewById(R.id.tv_title);
+ tv_count = findViewById(R.id.tv_count);
+ ll_channel = findViewById(R.id.ll_channel);
+ findViewById(R.id.iv_cart).setOnClickListener(this);
+ tv_title.setText("盲盒咖啡店");
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v.getId() == R.id.iv_cart) { // 点击了购物车图标
+ // 跳转到购物车页面
+ Intent intent = new Intent(this, ShoppingCartActivity.class);
+ startActivity(intent);
+ }
+ }
+
+ // 把指定编号的商品添加到购物车
+ private void addToCart(long goods_id) {
+ mCount++;
+ tv_count.setText("" + mCount);
+ // 把购物车中的商品数量写入共享参数
+ SharedUtil.getIntance(this).writeShared("count", "" + mCount);
+ // 根据商品编号查询购物车数据库中的商品记录
+ CartInfo info = mCartHelper.queryByGoodsId(goods_id);
+ if (info != null) { // 购物车已存在该商品记录
+ info.count++; // 该商品的数量加一
+ info.update_time = DateUtil.getNowDateTime("");
+ // 更新购物车数据库中的商品记录信息
+ mCartHelper.update(info);
+ } else { // 购物车不存在该商品记录
+ info = new CartInfo();
+ info.goods_id = goods_id;
+ info.count = 1;
+ info.update_time = DateUtil.getNowDateTime("");
+ // 往购物车数据库中添加一条新的商品记录
+ mCartHelper.insert(info);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 获取共享参数保存的购物车中的商品数量
+ mCount = Integer.parseInt(SharedUtil.getIntance(this).readShared("count", "0"));
+ tv_count.setText("" + mCount);
+ // 获取商品数据库的帮助器对象
+ mGoodsHelper = GoodsDBHelper.getInstance(this, 1);
+ // 打开商品数据库的读连接
+ mGoodsHelper.openReadLink();
+ // 获取购物车数据库的帮助器对象
+ mCartHelper = CartDBHelper.getInstance(this, 1);
+ // 打开购物车数据库的写连接
+ mCartHelper.openWriteLink();
+ // 展示商品列表
+ showGoods();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 关闭商品数据库的数据库连接
+ mGoodsHelper.closeLink();
+ // 关闭购物车数据库的数据库连接
+ mCartHelper.closeLink();
+ }
+
+ private LayoutParams mFullParams, mHalfParams;
+
+ private void showGoods() {
+ // 移除线性布局ll_channel下面的所有子视图
+ ll_channel.removeAllViews();
+ // mFullParams这个布局参数的宽度占了一整行
+ mFullParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ // mHalfParams这个布局参数的宽度与其它布局平均分
+ mHalfParams = new LayoutParams(0, LayoutParams.WRAP_CONTENT, 1);
+ // 给mHalfParams设置四周的空白距离
+ mHalfParams.setMargins(Utils.dip2px(this, 2), Utils.dip2px(this, 2), Utils.dip2px(this, 2), Utils.dip2px(this, 2));
+ // 创建一行的线性布局
+ LinearLayout ll_row = newLinearLayout(LinearLayout.HORIZONTAL, 0);
+ // 查询商品数据库中的所有商品记录
+ ArrayList goodsArray = mGoodsHelper.query("1=1");
+ int i = 0;
+ for (; i < goodsArray.size(); i++) {
+ final GoodsInfo info = goodsArray.get(i);
+ // 创建一个商品项的垂直线性布局,从上到下依次列出商品标题、商品图片、商品价格
+ LinearLayout ll_goods = newLinearLayout(LinearLayout.VERTICAL, 1);
+ ll_goods.setBackgroundColor(Color.WHITE);
+ // 添加商品标题
+ TextView tv_name = new TextView(this);
+ tv_name.setLayoutParams(mFullParams);
+ tv_name.setGravity(Gravity.CENTER);
+ tv_name.setText(info.name);
+ tv_name.setTextColor(Color.BLACK);
+ tv_name.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17);
+ ll_goods.addView(tv_name);
+ // 添加商品小图
+ ImageView iv_thumb = new ImageView(this);
+ iv_thumb.setLayoutParams(new LayoutParams(
+ LayoutParams.MATCH_PARENT, Utils.dip2px(this, 150)));
+ iv_thumb.setScaleType(ScaleType.FIT_CENTER);
+ iv_thumb.setImageBitmap(MainApplication.getInstance().mIconMap.get(info.rowid));
+ iv_thumb.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(ShoppingChannelActivity.this, ShoppingDetailActivity.class);
+ intent.putExtra("goods_id", info.rowid);
+ startActivity(intent);
+ }
+ });
+ ll_goods.addView(iv_thumb);
+ // 添加商品价格
+ LinearLayout ll_bottom = newLinearLayout(LinearLayout.HORIZONTAL, 0);
+ TextView tv_price = new TextView(this);
+ tv_price.setLayoutParams(new LayoutParams(0, LayoutParams.WRAP_CONTENT, 2));
+ tv_price.setGravity(Gravity.CENTER);
+ tv_price.setText("" + (int) info.price);
+ tv_price.setTextColor(Color.RED);
+ tv_price.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15);
+ ll_bottom.addView(tv_price);
+ // 添加购物车按钮
+ Button btn_add = new Button(this);
+ btn_add.setLayoutParams(new LayoutParams(0, LayoutParams.WRAP_CONTENT, 3));
+ btn_add.setGravity(Gravity.CENTER);
+ btn_add.setText("加入购物车");
+ btn_add.setTextColor(Color.BLACK);
+ btn_add.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15);
+ btn_add.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ addToCart(info.rowid);
+ Toast.makeText(ShoppingChannelActivity.this,
+ "已添加一份" + info.name + "到购物车", Toast.LENGTH_SHORT).show();
+ }
+ });
+ ll_bottom.addView(btn_add);
+ ll_goods.addView(ll_bottom);
+ // 把商品项添加到该行上
+ ll_row.addView(ll_goods);
+ // 每行放两个商品项,所以放满两个商品后,就要重新创建下一行的线性视图
+ if (i % 2 == 1) {
+ ll_channel.addView(ll_row);
+ ll_row = newLinearLayout(LinearLayout.HORIZONTAL, 0);
+ }
+ }
+ // 最后一行只有一个商品项,则补上一个空白格,然后把最后一行添加到ll_channel
+ if (i % 2 == 0) {
+ ll_row.addView(newLinearLayout(LinearLayout.VERTICAL, 1));
+ ll_channel.addView(ll_row);
+ }
+ }
+
+ // 创建一个线性视图的框架
+ private LinearLayout newLinearLayout(int orientation, int weight) {
+ LinearLayout ll_new = new LinearLayout(this);
+ ll_new.setLayoutParams((weight == 0) ? mFullParams : mHalfParams);
+ ll_new.setOrientation(orientation);
+ return ll_new;
+ }
+
+}
diff --git a/Coffeestore/app/src/main/java/com/example/storage/ShoppingDetailActivity.java b/Coffeestore/app/src/main/java/com/example/storage/ShoppingDetailActivity.java
new file mode 100644
index 0000000..7c05d70
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/ShoppingDetailActivity.java
@@ -0,0 +1,123 @@
+package com.example.storage;
+
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.example.storage.bean.CartInfo;
+import com.example.storage.bean.GoodsInfo;
+import com.example.storage.database.CartDBHelper;
+import com.example.storage.database.GoodsDBHelper;
+import com.example.storage.util.DateUtil;
+import com.example.storage.util.SharedUtil;
+
+@SuppressLint("SetTextI18n")
+public class ShoppingDetailActivity extends AppCompatActivity implements OnClickListener {
+ private TextView tv_title;
+ private TextView tv_count;
+ private TextView tv_goods_price;
+ private TextView tv_goods_desc;
+ private ImageView iv_goods_pic;
+ private int mCount; // 购物车中的商品数量
+ private long mGoodsId; // 当前商品的商品编号
+ private GoodsDBHelper mGoodsHelper; // 声明一个商品数据库的帮助器对象
+ private CartDBHelper mCartHelper; // 声明一个购物车数据库的帮助器对象
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_shopping_detail);
+ tv_title = findViewById(R.id.tv_title);
+ tv_count = findViewById(R.id.tv_count);
+ tv_goods_price = findViewById(R.id.tv_goods_price);
+ tv_goods_desc = findViewById(R.id.tv_goods_desc);
+ iv_goods_pic = findViewById(R.id.iv_goods_pic);
+ findViewById(R.id.iv_cart).setOnClickListener(this);
+ findViewById(R.id.btn_add_cart).setOnClickListener(this);
+ // 获取共享参数保存的购物车中的商品数量
+ mCount = Integer.parseInt(SharedUtil.getIntance(this).readShared("count", "0"));
+ tv_count.setText("" + mCount);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v.getId() == R.id.iv_cart) { // 点击了购物车图标
+ // 跳转到购物车页面
+ Intent intent = new Intent(this, ShoppingCartActivity.class);
+ startActivity(intent);
+ } else if (v.getId() == R.id.btn_add_cart) { // 点击了“添加”按钮
+ // 把该商品添加到购物车
+ addToCart(mGoodsId);
+ Toast.makeText(this, "成功添加至购物车", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ // 把指定编号的商品添加到购物车
+ private void addToCart(long goods_id) {
+ mCount++;
+ tv_count.setText("" + mCount);
+ // 把购物车中的商品数量写入共享参数
+ SharedUtil.getIntance(this).writeShared("count", "" + mCount);
+ // 根据商品编号查询购物车中的商品记录
+ CartInfo info = mCartHelper.queryByGoodsId(goods_id);
+ if (info != null) { // 购物车已存在该商品记录
+ info.count++; // 该商品的数量加一
+ info.update_time = DateUtil.getNowDateTime("");
+ // 更新购物车数据库中的商品记录信息
+ mCartHelper.update(info);
+ } else { // 购物车不存在该商品记录
+ info = new CartInfo();
+ info.goods_id = goods_id;
+ info.count = 1;
+ info.update_time = DateUtil.getNowDateTime("");
+ // 往购物车数据库中添加一条新的商品记录
+ mCartHelper.insert(info);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 获取商品数据库的帮助器对象
+ mGoodsHelper = GoodsDBHelper.getInstance(this, 1);
+ // 打开商品数据库的读连接
+ mGoodsHelper.openReadLink();
+ // 获取购物车数据库的帮助器对象
+ mCartHelper = CartDBHelper.getInstance(this, 1);
+ // 打开购物车数据库的写连接
+ mCartHelper.openWriteLink();
+ // 展示商品详情
+ showDetail();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 关闭商品数据库的数据库连接
+ mGoodsHelper.closeLink();
+ // 关闭购物车数据库的数据库连接
+ mCartHelper.closeLink();
+ }
+
+ private void showDetail() {
+ mGoodsId = getIntent().getLongExtra("goods_id", 0L);
+ if (mGoodsId > 0) {
+ GoodsInfo info = mGoodsHelper.queryById(mGoodsId);
+ tv_title.setText(info.name);
+ tv_goods_desc.setText(info.desc);
+ tv_goods_price.setText("" + info.price);
+ Bitmap pic = BitmapFactory.decodeFile(info.pic_path);
+ iv_goods_pic.setImageBitmap(pic);
+ }
+ }
+
+}
diff --git a/Coffeestore/app/src/main/java/com/example/storage/User.java b/Coffeestore/app/src/main/java/com/example/storage/User.java
new file mode 100644
index 0000000..78752bc
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/User.java
@@ -0,0 +1,32 @@
+package com.example.storage;
+/**
+ * Created by littlecurl 2018/6/24
+ */
+public class User {
+ private String name; //用户名
+ private String password; //密码
+ public User(String name, String password) {
+ this.name = name;
+ this.password = password;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getPassword() {
+ return password;
+ }
+ public void setPassword(String password) {
+ this.password = password;
+ }
+ @Override
+ public String toString() {
+ return "User{" +
+ "name='" + name + '\'' +
+ ", password='" + password + '\'' +
+ '}';
+ }
+}
+
diff --git a/Coffeestore/app/src/main/java/com/example/storage/UserActivity.java b/Coffeestore/app/src/main/java/com/example/storage/UserActivity.java
new file mode 100644
index 0000000..01dc934
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/UserActivity.java
@@ -0,0 +1,22 @@
+package com.example.storage;
+
+import androidx.appcompat.app.AppCompatActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+public class UserActivity extends AppCompatActivity {
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_user);
+ getSupportActionBar().setTitle("个人中心");
+ }
+
+ public void Jumping(View view) {
+ Intent intent = new Intent(UserActivity.this, LoginActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ }
+}
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/java/com/example/storage/bean/CartInfo.java b/Coffeestore/app/src/main/java/com/example/storage/bean/CartInfo.java
new file mode 100644
index 0000000..9dbdbec
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/bean/CartInfo.java
@@ -0,0 +1,17 @@
+package com.example.storage.bean;
+
+public class CartInfo {
+ public long rowid;
+ public int xuhao;
+ public long goods_id;
+ public int count;
+ public String update_time;
+
+ public CartInfo() {
+ rowid = 0L;
+ xuhao = 0;
+ goods_id = 0L;
+ count = 0;
+ update_time = "";
+ }
+}
diff --git a/Coffeestore/app/src/main/java/com/example/storage/bean/GoodsInfo.java b/Coffeestore/app/src/main/java/com/example/storage/bean/GoodsInfo.java
new file mode 100644
index 0000000..e61f51b
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/bean/GoodsInfo.java
@@ -0,0 +1,83 @@
+package com.example.storage.bean;
+
+import com.example.storage.R;
+
+import java.util.ArrayList;
+
+public class GoodsInfo {
+ public long rowid; // 行号
+ public int xuhao; // 序号1
+ public String name; // 名称
+ public String desc; // 描述
+ public float price; // 价格
+ public String thumb_path; // 图的保存路径
+ public String pic_path; // 图的保存路径
+ public int thumb; // 图的资源编号
+ public int pic; // 图的资源编号
+
+ public GoodsInfo() {
+ rowid = 0L;
+ xuhao = 0;
+ name = "";
+ desc = "";
+ price = 0;
+ thumb_path = "";
+ pic_path = "";
+ thumb = 0;
+ pic = 0;
+ }
+
+ // 声明一个商品的名称数组
+ private static String[] mNameArray = {
+ "来杯拿铁", "一杯咖啡", "神秘美式", "饮品+甜点套餐", "随便奶茶", "不知味气泡水"
+ };
+ // 声明一个商品的描述数组
+ private static String[] mDescArray = {
+ "来杯拿铁\n 欢迎来开盲盒啦!\n" +
+ "杯型:大杯\n" +
+ "温度: 热、冷、常温\n" ,
+ "一杯咖啡\n选择困难症的福音来啦!本店都是好喝的咖啡,不知道选那种咖啡的选择我,店家会给你搭配一杯的\n " +
+ "杯型: 咱们家只有大杯哦!\n" +
+ "温度:热、冷、常温三种哦!\n",
+ "神秘美式\n我是很神秘的美式哦!可以颠覆你对美式的想象哦!\n"+
+ "杯型: 咱们家只有大杯哦!\n"+
+ "温度:热、冷、常温三种哦!\n",
+ "饮品+甜点套餐\n 生活必须要多来一点甜甜的!\n" +
+ "杯型: 咱们家只有大杯哦!\n" +
+ "温度:热、冷、常温三种哦!\n",
+ "随便奶茶\n 当你想喝奶茶却不知道选什么奶茶的时候就选我好啦!\n" +
+ "杯型: 咱们家只有大杯哦!\n" +
+ "温度:热、冷、常温三种哦!\n",
+ "不知味气泡水\n 各种水果与气泡水碰撞在一起会是什么味道呢!\n" +
+ "杯型: 咱们家只有大杯哦!\n" +
+ "温度:热、冷、常温三种哦!\n",
+ };
+ // 声明一个商品的价格数组
+ private static float[] mPriceArray = {18, 18, 16, 25, 16, 15};
+ // 声明一个商品的小图数组
+ private static int[] mThumbArray = {
+ R.drawable.nt1, R.drawable.cf1, R.drawable.ms1,
+ R.drawable.td4, R.drawable.nc1, R.drawable.qps1
+ };
+ // 声明一个商品的大图数组
+ private static int[] mPicArray = {
+ R.drawable.ntall, R.drawable.cfall, R.drawable.msall,
+ R.drawable.tdall, R.drawable.ncall, R.drawable.qpsall
+ };
+
+ // 获取默认的信息列表
+ public static ArrayList getDefaultList() {
+ ArrayList goodsList = new ArrayList();
+ for (int i = 0; i < mNameArray.length; i++) {
+ GoodsInfo info = new GoodsInfo();
+ info.name = mNameArray[i];
+ info.desc = mDescArray[i];
+ info.price = mPriceArray[i];
+ info.thumb = mThumbArray[i];
+ info.pic = mPicArray[i];
+ goodsList.add(info);
+ }
+ return goodsList;
+ }
+
+}
diff --git a/Coffeestore/app/src/main/java/com/example/storage/database/CartDBHelper.java b/Coffeestore/app/src/main/java/com/example/storage/database/CartDBHelper.java
new file mode 100644
index 0000000..e993391
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/database/CartDBHelper.java
@@ -0,0 +1,190 @@
+package com.example.storage.database;
+
+import java.util.ArrayList;
+
+import android.annotation.SuppressLint;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+import com.example.storage.bean.CartInfo;
+
+@SuppressLint("DefaultLocale")
+public class CartDBHelper extends SQLiteOpenHelper {
+ private static final String TAG = "CartDBHelper";
+ private static final String DB_NAME = "cart.db"; // 数据库的名称
+ private static final int DB_VERSION = 1; // 数据库的版本号
+ private static CartDBHelper mHelper = null; // 数据库帮助器的实例
+ private SQLiteDatabase mDB = null; // 数据库的实例
+ private static final String TABLE_NAME = "cart_info"; // 表的名称
+
+ private CartDBHelper(Context context) {
+ super(context, DB_NAME, null, DB_VERSION);
+ }
+
+ private CartDBHelper(Context context, int version) {
+ super(context, DB_NAME, null, version);
+ }
+
+ // 利用单例模式获取数据库帮助器的唯一实例
+ public static CartDBHelper getInstance(Context context, int version) {
+ if (version > 0 && mHelper == null) {
+ mHelper = new CartDBHelper(context, version);
+ } else if (mHelper == null) {
+ mHelper = new CartDBHelper(context);
+ }
+ return mHelper;
+ }
+
+ // 打开数据库的读连接
+ public SQLiteDatabase openReadLink() {
+ if (mDB == null || !mDB.isOpen()) {
+ mDB = mHelper.getReadableDatabase();
+ }
+ return mDB;
+ }
+
+ // 打开数据库的写连接
+ public SQLiteDatabase openWriteLink() {
+ if (mDB == null || !mDB.isOpen()) {
+ mDB = mHelper.getWritableDatabase();
+ }
+ return mDB;
+ }
+
+ // 关闭数据库连接
+ public void closeLink() {
+ if (mDB != null && mDB.isOpen()) {
+ mDB.close();
+ mDB = null;
+ }
+ }
+
+ // 创建数据库,执行建表语句
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ Log.d(TAG, "onCreate");
+ String drop_sql = "DROP TABLE IF EXISTS " + TABLE_NAME + ";";
+ Log.d(TAG, "drop_sql:" + drop_sql);
+ db.execSQL(drop_sql);
+ String create_sql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " ("
+ + "_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
+ + "goods_id LONG NOT NULL," + "count INTEGER NOT NULL,"
+ + "update_time VARCHAR NOT NULL"
+ + ");";
+ Log.d(TAG, "create_sql:" + create_sql);
+ db.execSQL(create_sql);
+ }
+
+ // 修改数据库,执行表结构变更语句
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ }
+
+ // 根据指定条件删除表记录
+ public int delete(String condition) {
+ // 执行删除记录动作,该语句返回删除记录的数目
+ return mDB.delete(TABLE_NAME, condition, null);
+ }
+
+ // 删除该表的所有记录
+ public int deleteAll() {
+ // 执行删除记录动作,该语句返回删除记录的数目
+ return mDB.delete(TABLE_NAME, "1=1", null);
+ }
+
+ // 往该表添加一条记录
+ public long insert(CartInfo info) {
+ ArrayList infoArray = new ArrayList();
+ infoArray.add(info);
+ return insert(infoArray);
+ }
+
+ // 往该表添加多条记录
+ public long insert(ArrayList infoArray) {
+ long result = -1;
+ for (CartInfo info : infoArray) {
+ Log.d(TAG, "goods_id=" + info.goods_id + ", count=" + info.count);
+ // 如果存在相同rowid的记录,则更新记录
+ if (info.rowid > 0) {
+ String condition = String.format("rowid='%d'", info.rowid);
+ update(info, condition);
+ result = info.rowid;
+ continue;
+ }
+ // 不存在唯一性重复的记录,则插入新记录
+ ContentValues cv = new ContentValues();
+ cv.put("goods_id", info.goods_id);
+ cv.put("count", info.count);
+ cv.put("update_time", info.update_time);
+ // 执行插入记录动作,该语句返回插入记录的行号
+ result = mDB.insert(TABLE_NAME, "", cv);
+ // 添加成功后返回行号,失败后返回-1
+ if (result == -1) {
+ return result;
+ }
+ }
+ return result;
+ }
+
+ // 根据条件更新指定的表记录
+ public int update(CartInfo info, String condition) {
+ ContentValues cv = new ContentValues();
+ cv.put("goods_id", info.goods_id);
+ cv.put("count", info.count);
+ cv.put("update_time", info.update_time);
+ // 执行更新记录动作,该语句返回记录更新的数目
+ return mDB.update(TABLE_NAME, cv, condition, null);
+ }
+
+ public int update(CartInfo info) {
+ // 执行更新记录动作,该语句返回记录更新的数目
+ return update(info, "rowid=" + info.rowid);
+ }
+
+ // 根据指定条件查询记录,并返回结果数据队列
+ public ArrayList query(String condition) {
+ String sql = String.format("select rowid,_id,goods_id,count,update_time" +
+ " from %s where %s;", TABLE_NAME, condition);
+ Log.d(TAG, "query sql: " + sql);
+ ArrayList infoArray = new ArrayList();
+ // 执行记录查询动作,该语句返回结果集的游标
+ Cursor cursor = mDB.rawQuery(sql, null);
+ // 循环取出游标指向的每条记录
+ while (cursor.moveToNext()) {
+ CartInfo info = new CartInfo();
+ info.rowid = cursor.getLong(0);
+ info.xuhao = cursor.getInt(1);
+ info.goods_id = cursor.getLong(2);
+ info.count = cursor.getInt(3);
+ info.update_time = cursor.getString(4);
+ infoArray.add(info);
+ }
+ cursor.close(); // 查询完毕,关闭游标
+ return infoArray;
+ }
+
+ // 根据行号查询指定记录
+ public CartInfo queryById(long rowid) {
+ CartInfo info = null;
+ ArrayList infoArray = query(String.format("rowid='%d'", rowid));
+ if (infoArray.size() > 0) {
+ info = infoArray.get(0);
+ }
+ return info;
+ }
+
+ // 根据商品编号查询指定记录
+ public CartInfo queryByGoodsId(long goods_id) {
+ CartInfo info = null;
+ ArrayList infoArray = query(String.format("goods_id='%d'", goods_id));
+ if (infoArray.size() > 0) {
+ info = infoArray.get(0);
+ }
+ return info;
+ }
+
+}
diff --git a/Coffeestore/app/src/main/java/com/example/storage/database/GoodsDBHelper.java b/Coffeestore/app/src/main/java/com/example/storage/database/GoodsDBHelper.java
new file mode 100644
index 0000000..a0fd87b
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/database/GoodsDBHelper.java
@@ -0,0 +1,186 @@
+package com.example.storage.database;
+
+import java.util.ArrayList;
+
+import android.annotation.SuppressLint;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+import com.example.storage.bean.GoodsInfo;
+
+@SuppressLint("DefaultLocale")
+public class GoodsDBHelper extends SQLiteOpenHelper {
+ private static final String TAG = "GoodsDBHelper";
+ private static final String DB_NAME = "goods.db"; // 数据库的名称
+ private static final int DB_VERSION = 1; // 数据库的版本号
+ private static GoodsDBHelper mHelper = null; // 数据库帮助器的实例
+ private SQLiteDatabase mDB = null; // 数据库的实例
+ private static final String TABLE_NAME = "goods_info"; // 表的名称
+
+ private GoodsDBHelper(Context context) {
+ super(context, DB_NAME, null, DB_VERSION);
+ }
+
+ private GoodsDBHelper(Context context, int version) {
+ super(context, DB_NAME, null, version);
+ }
+
+ // 利用单例模式获取数据库帮助器的唯一实例
+ public static GoodsDBHelper getInstance(Context context, int version) {
+ if (version > 0 && mHelper == null) {
+ mHelper = new GoodsDBHelper(context, version);
+ } else if (mHelper == null) {
+ mHelper = new GoodsDBHelper(context);
+ }
+ return mHelper;
+ }
+
+ // 打开数据库的读连接
+ public SQLiteDatabase openReadLink() {
+ if (mDB == null || !mDB.isOpen()) {
+ mDB = mHelper.getReadableDatabase();
+ }
+ return mDB;
+ }
+
+ // 打开数据库的写连接
+ public SQLiteDatabase openWriteLink() {
+ if (mDB == null || !mDB.isOpen()) {
+ mDB = mHelper.getWritableDatabase();
+ }
+ return mDB;
+ }
+
+ // 关闭数据库连接
+ public void closeLink() {
+ if (mDB != null && mDB.isOpen()) {
+ mDB.close();
+ mDB = null;
+ }
+ }
+
+ // 创建数据库,执行建表语句
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ Log.d(TAG, "onCreate");
+ String drop_sql = "DROP TABLE IF EXISTS " + TABLE_NAME + ";";
+ Log.d(TAG, "drop_sql:" + drop_sql);
+ db.execSQL(drop_sql);
+ String create_sql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " ("
+ + "_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
+ + "name VARCHAR NOT NULL," + "desc VARCHAR NOT NULL,"
+ + "price FLOAT NOT NULL," + "thumb_path VARCHAR NOT NULL,"
+ + "pic_path VARCHAR NOT NULL"
+ + ");";
+ Log.d(TAG, "create_sql:" + create_sql);
+ db.execSQL(create_sql);
+ }
+
+ // 修改数据库,执行表结构变更语句
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ }
+
+ // 根据指定条件删除表记录
+ public int delete(String condition) {
+ // 执行删除记录动作,该语句返回删除记录的数目
+ return mDB.delete(TABLE_NAME, condition, null);
+ }
+
+ // 删除该表的所有记录
+ public int deleteAll() {
+ // 执行删除记录动作,该语句返回删除记录的数目
+ return mDB.delete(TABLE_NAME, "1=1", null);
+ }
+
+ // 往该表添加一条记录
+ public long insert(GoodsInfo info) {
+ ArrayList infoArray = new ArrayList();
+ infoArray.add(info);
+ return insert(infoArray);
+ }
+
+ // 往该表添加多条记录
+ public long insert(ArrayList infoArray) {
+ long result = -1;
+ for (GoodsInfo info : infoArray) {
+ // 如果存在相同rowid的记录,则更新记录
+ if (info.rowid > 0) {
+ String condition = String.format("rowid='%d'", info.rowid);
+ update(info, condition);
+ result = info.rowid;
+ continue;
+ }
+ // 不存在唯一性重复的记录,则插入新记录
+ ContentValues cv = new ContentValues();
+ cv.put("name", info.name);
+ cv.put("desc", info.desc);
+ cv.put("price", info.price);
+ cv.put("thumb_path", info.thumb_path);
+ cv.put("pic_path", info.pic_path);
+ // 执行插入记录动作,该语句返回插入记录的行号
+ result = mDB.insert(TABLE_NAME, "", cv);
+ // 添加成功后返回行号,失败后返回-1
+ if (result == -1) {
+ return result;
+ }
+ }
+ return result;
+ }
+
+ // 根据条件更新指定的表记录
+ public int update(GoodsInfo info, String condition) {
+ ContentValues cv = new ContentValues();
+ cv.put("name", info.name);
+ cv.put("desc", info.desc);
+ cv.put("price", info.price);
+ cv.put("thumb_path", info.thumb_path);
+ cv.put("pic_path", info.pic_path);
+ // 执行更新记录动作,该语句返回记录更新的数目
+ return mDB.update(TABLE_NAME, cv, condition, null);
+ }
+
+ public int update(GoodsInfo info) {
+ // 执行更新记录动作,该语句返回记录更新的数目
+ return update(info, "rowid=" + info.rowid);
+ }
+
+ // 根据指定条件查询记录,并返回结果数据队列
+ public ArrayList query(String condition) {
+ String sql = String.format("select rowid,_id,name,desc,price,thumb_path,pic_path" +
+ " from %s where %s;", TABLE_NAME, condition);
+ Log.d(TAG, "query sql: " + sql);
+ ArrayList infoArray = new ArrayList();
+ // 执行记录查询动作,该语句返回结果集的游标
+ Cursor cursor = mDB.rawQuery(sql, null);
+ // 循环取出游标指向的每条记录
+ while (cursor.moveToNext()) {
+ GoodsInfo info = new GoodsInfo();
+ info.rowid = cursor.getLong(0);
+ info.xuhao = cursor.getInt(1);
+ info.name = cursor.getString(2);
+ info.desc = cursor.getString(3);
+ info.price = cursor.getFloat(4);
+ info.thumb_path = cursor.getString(5);
+ info.pic_path = cursor.getString(6);
+ infoArray.add(info);
+ }
+ cursor.close(); // 查询完毕,关闭游标
+ return infoArray;
+ }
+
+ // 根据行号查询指定记录
+ public GoodsInfo queryById(long rowid) {
+ GoodsInfo info = null;
+ ArrayList infoArray = query(String.format("rowid='%d'", rowid));
+ if (infoArray.size() > 0) {
+ info = infoArray.get(0);
+ }
+ return info;
+ }
+
+}
diff --git a/Coffeestore/app/src/main/java/com/example/storage/util/DateUtil.java b/Coffeestore/app/src/main/java/com/example/storage/util/DateUtil.java
new file mode 100644
index 0000000..42acb52
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/util/DateUtil.java
@@ -0,0 +1,39 @@
+package com.example.storage.util;
+
+import android.annotation.SuppressLint;
+import android.text.TextUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ *
+ */
+@SuppressLint("SimpleDateFormat")
+public class DateUtil {
+ public static String getNowDateTime(String formatStr) {
+ String format = formatStr;
+ if (TextUtils.isEmpty(format)) {
+ format = "yyyyMMddHHmmss";
+ }
+ SimpleDateFormat sdf = new SimpleDateFormat(format);
+ return sdf.format(new Date());
+ }
+
+ public static String getNowTime() {
+ SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
+ return sdf.format(new Date());
+ }
+
+ public static String getNowTimeDetail() {
+ SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
+ return sdf.format(new Date());
+ }
+
+ public static String formatDate(long time) {
+ Date date = new Date(time);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ return sdf.format(date);
+ }
+
+}
diff --git a/Coffeestore/app/src/main/java/com/example/storage/util/FileUtil.java b/Coffeestore/app/src/main/java/com/example/storage/util/FileUtil.java
new file mode 100644
index 0000000..2cfe3ee
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/util/FileUtil.java
@@ -0,0 +1,133 @@
+package com.example.storage.util;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Locale;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+public class FileUtil {
+
+ // 把字符串保存到指定路径的文本文件
+ public static void saveText(String path, String txt) {
+ try {
+ // 根据指定文件路径构建文件输出流对象
+ FileOutputStream fos = new FileOutputStream(path);
+ // 把字符串写入文件输出流
+ fos.write(txt.getBytes());
+ // 关闭文件输出流
+ fos.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // 从指定路径的文本文件中读取内容字符串
+ public static String openText(String path) {
+ String readStr = "";
+ try {
+ // 根据指定文件路径构建文件输入流对象
+ FileInputStream fis = new FileInputStream(path);
+ byte[] b = new byte[fis.available()];
+ // 从文件输入流读取字节数组
+ fis.read(b);
+ // 把字节数组转换为字符串
+ readStr = new String(b);
+ // 关闭文件输入流
+ fis.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ // 返回文本文件中的文本字符串
+ return readStr;
+ }
+
+ // 把位图数据保存到指定路径的图片文件
+ public static void saveImage(String path, Bitmap bitmap) {
+ try {
+ // 根据指定文件路径构建缓存输出流对象
+ BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path));
+ // 把位图数据压缩到缓存输出流中
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos);
+ // 完成缓存输出流的写入动作
+ bos.flush();
+ // 关闭缓存输出流
+ bos.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // 从指定路径的图片文件中读取位图数据
+ public static Bitmap openImage(String path) {
+ Bitmap bitmap = null;
+ try {
+ // 根据指定文件路径构建缓存输入流对象
+ BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
+ // 从缓存输入流中解码位图数据
+ bitmap = BitmapFactory.decodeStream(bis);
+ bis.close(); // 关闭缓存输入流
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ // 返回图片文件中的位图数据
+ return bitmap;
+ }
+
+ public static ArrayList getFileList(String path, String[] extendArray) {
+ ArrayList displayedContent = new ArrayList();
+ File[] files = null;
+ File directory = new File(path);
+ if (extendArray != null && extendArray.length > 0) {
+ FilenameFilter fileFilter = getTypeFilter(extendArray);
+ files = directory.listFiles(fileFilter);
+ } else {
+ files = directory.listFiles();
+ }
+
+ if (files != null) {
+ for (File f : files) {
+ if (!f.isDirectory() && !f.isHidden()) {
+ displayedContent.add(f);
+ }
+ }
+ }
+ return displayedContent;
+ }
+
+ public static FilenameFilter getTypeFilter(String[] extendArray) {
+ final ArrayList fileExtensions = new ArrayList();
+ for (int i = 0; i < extendArray.length; i++) {
+ fileExtensions.add(extendArray[i]);
+ }
+ FilenameFilter fileNameFilter = new FilenameFilter() {
+ @Override
+ public boolean accept(File directory, String fileName) {
+ boolean matched = false;
+ File f = new File(String.format("%s/%s",
+ directory.getAbsolutePath(), fileName));
+ matched = f.isDirectory();
+ if (!matched) {
+ for (String s : fileExtensions) {
+ s = String.format(".{0,}\\%s$", s);
+ s = s.toUpperCase(Locale.getDefault());
+ fileName = fileName.toUpperCase(Locale.getDefault());
+ matched = fileName.matches(s);
+ if (matched) {
+ break;
+ }
+ }
+ }
+ return matched;
+ }
+ };
+ return fileNameFilter;
+ }
+
+}
diff --git a/Coffeestore/app/src/main/java/com/example/storage/util/SharedUtil.java b/Coffeestore/app/src/main/java/com/example/storage/util/SharedUtil.java
new file mode 100644
index 0000000..3fc6be5
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/util/SharedUtil.java
@@ -0,0 +1,33 @@
+package com.example.storage.util;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+// 这是共享参数的工具类,统一对共享参数的读写操作
+public class SharedUtil {
+ private static SharedUtil mUtil; // 声明一个共享参数工具类的实例
+ private static SharedPreferences mShared; // 声明一个共享参数的实例
+
+ // 通过单例模式获取共享参数工具类的唯一实例
+ public static SharedUtil getIntance(Context ctx) {
+ if (mUtil == null) {
+ mUtil = new SharedUtil();
+ }
+ // 从share.xml中获取共享参数对象
+ mShared = ctx.getSharedPreferences("share", Context.MODE_PRIVATE);
+ return mUtil;
+ }
+
+ // 把配对信息写入共享参数
+ public void writeShared(String key, String value) {
+ SharedPreferences.Editor editor = mShared.edit(); // 获得编辑器的对象
+ editor.putString(key, value); // 添加一个指定键名的字符串参数
+ editor.commit(); // 提交编辑器中的修改
+ }
+
+ // 根据键名到共享参数中查找对应的值对象
+ public String readShared(String key, String defaultValue) {
+ return mShared.getString(key, defaultValue);
+ }
+
+}
diff --git a/Coffeestore/app/src/main/java/com/example/storage/util/Utils.java b/Coffeestore/app/src/main/java/com/example/storage/util/Utils.java
new file mode 100644
index 0000000..12ec9bb
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/util/Utils.java
@@ -0,0 +1,56 @@
+package com.example.storage.util;
+
+import android.content.Context;
+import android.util.DisplayMetrics;
+import android.view.WindowManager;
+
+/**
+ *
+ */
+public class Utils {
+ // 根据手机的分辨率从 dp 的单位 转成为 px(像素)
+ public static int dip2px(Context context, float dpValue) {
+ // 获取当前手机的像素密度
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f); // 四舍五入取整
+ }
+
+ // 根据手机的分辨率从 px(像素) 的单位 转成为 dp
+ public static int px2dip(Context context, float pxValue) {
+ // 获取当前手机的像素密度
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return (int) (pxValue / scale + 0.5f); // 四舍五入取整
+ }
+
+ // 获得屏幕的宽度
+ public static int getScreenWidth(Context ctx) {
+ // 从系统服务中获取窗口管理器
+ WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
+ DisplayMetrics dm = new DisplayMetrics();
+ // 从默认显示器中获取显示参数保存到dm对象中
+ wm.getDefaultDisplay().getMetrics(dm);
+ return dm.widthPixels; // 返回屏幕的宽度数值
+ }
+
+ // 获得屏幕的高度
+ public static int getScreenHeight(Context ctx) {
+ // 从系统服务中获取窗口管理器
+ WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
+ DisplayMetrics dm = new DisplayMetrics();
+ // 从默认显示器中获取显示参数保存到dm对象中
+ wm.getDefaultDisplay().getMetrics(dm);
+ return dm.heightPixels; // 返回屏幕的高度数值
+ }
+
+ // 获得屏幕的像素密度
+ public static float getScreenDensity(Context ctx) {
+ // 从系统服务中获取窗口管理器
+ WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
+ DisplayMetrics dm = new DisplayMetrics();
+ // 从默认显示器中获取显示参数保存到dm对象中
+ wm.getDefaultDisplay().getMetrics(dm);
+ return dm.density; // 返回屏幕的像素密度数值
+ }
+
+}
+
diff --git a/Coffeestore/app/src/main/java/com/example/storage/util/ViewUtil.java b/Coffeestore/app/src/main/java/com/example/storage/util/ViewUtil.java
new file mode 100644
index 0000000..88c7e65
--- /dev/null
+++ b/Coffeestore/app/src/main/java/com/example/storage/util/ViewUtil.java
@@ -0,0 +1,55 @@
+package com.example.storage.util;
+
+import android.app.Activity;
+import android.content.Context;
+import android.text.InputFilter;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+
+import java.lang.reflect.Field;
+
+/**
+ *
+ */
+public class ViewUtil {
+
+ // 获取编辑框的最大长度,通过反射机制调用隐藏方法
+ public static int getMaxLength(EditText et) {
+ int length = 0;
+ try {
+ InputFilter[] inputFilters = et.getFilters();
+ for (InputFilter filter : inputFilters) {
+ Class> c = filter.getClass();
+ if (c.getName().equals("android.text.InputFilter$LengthFilter")) {
+ Field[] f = c.getDeclaredFields();
+ for (Field field : f) {
+ if (field.getName().equals("mMax")) {
+ field.setAccessible(true);
+ length = (Integer) field.get(filter);
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return length;
+ }
+
+ public static void hideAllInputMethod(Activity act) {
+ // 从系统服务中获取输入法管理器
+ InputMethodManager imm = (InputMethodManager) act.getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (imm.isActive()) { // 软键盘如果已经打开则关闭之
+ imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
+ }
+ }
+
+ public static void hideOneInputMethod(Activity act, View v) {
+ // 从系统服务中获取输入法管理器
+ InputMethodManager imm = (InputMethodManager) act.getSystemService(Context.INPUT_METHOD_SERVICE);
+ // 关闭屏幕上的输入法软键盘
+ imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
+ }
+
+}
diff --git a/Coffeestore/app/src/main/res/drawable-hdpi/check_choose.png b/Coffeestore/app/src/main/res/drawable-hdpi/check_choose.png
new file mode 100644
index 0000000..24ff38e
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-hdpi/check_choose.png differ
diff --git a/Coffeestore/app/src/main/res/drawable-hdpi/check_unchoose.png b/Coffeestore/app/src/main/res/drawable-hdpi/check_unchoose.png
new file mode 100644
index 0000000..4423ce6
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-hdpi/check_unchoose.png differ
diff --git a/Coffeestore/app/src/main/res/drawable-hdpi/text_cursor.png b/Coffeestore/app/src/main/res/drawable-hdpi/text_cursor.png
new file mode 100644
index 0000000..8d8f234
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-hdpi/text_cursor.png differ
diff --git a/Coffeestore/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/Coffeestore/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/Coffeestore/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/bao.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/bao.jpg
new file mode 100644
index 0000000..0500fae
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/bao.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/baoo.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/baoo.jpg
new file mode 100644
index 0000000..67ab3cb
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/baoo.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/cart.png b/Coffeestore/app/src/main/res/drawable-xhdpi/cart.png
new file mode 100644
index 0000000..1394a0a
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/cart.png differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/chun.jpeg b/Coffeestore/app/src/main/res/drawable-xhdpi/chun.jpeg
new file mode 100644
index 0000000..6fafb68
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/chun.jpeg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/chunn.jpeg b/Coffeestore/app/src/main/res/drawable-xhdpi/chunn.jpeg
new file mode 100644
index 0000000..ed69f2f
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/chunn.jpeg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/dong.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/dong.jpg
new file mode 100644
index 0000000..e08735b
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/dong.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/dongg.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/dongg.jpg
new file mode 100644
index 0000000..d560baa
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/dongg.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/fbm.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/fbm.jpg
new file mode 100644
index 0000000..e4fd788
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/fbm.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/fbm_s.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/fbm_s.jpg
new file mode 100644
index 0000000..d762adc
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/fbm_s.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/lt.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/lt.jpg
new file mode 100644
index 0000000..07605ac
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/lt.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/lt_s.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/lt_s.jpg
new file mode 100644
index 0000000..3d4c817
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/lt_s.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/mb.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/mb.jpg
new file mode 100644
index 0000000..f691b9c
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/mb.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/mb_s.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/mb_s.jpg
new file mode 100644
index 0000000..0bbf70e
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/mb_s.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/menu.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/menu.jpg
new file mode 100644
index 0000000..19dcee2
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/menu.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/qiu.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/qiu.jpg
new file mode 100644
index 0000000..5bbcc4e
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/qiu.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/qiuu.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/qiuu.jpg
new file mode 100644
index 0000000..922fcdb
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/qiuu.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/qkl.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/qkl.jpg
new file mode 100644
index 0000000..bfbc473
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/qkl.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/qkl_s.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/qkl_s.jpg
new file mode 100644
index 0000000..f99f9e2
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/qkl_s.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/sp.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/sp.jpg
new file mode 100644
index 0000000..976dff6
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/sp.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/sp_s.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/sp_s.jpg
new file mode 100644
index 0000000..b286c70
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/sp_s.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/tg.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/tg.jpg
new file mode 100644
index 0000000..4296f63
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/tg.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/tg_s.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/tg_s.jpg
new file mode 100644
index 0000000..263eded
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/tg_s.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/xia.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/xia.jpg
new file mode 100644
index 0000000..0f0a7eb
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/xia.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/xiaa.jpg b/Coffeestore/app/src/main/res/drawable-xhdpi/xiaa.jpg
new file mode 100644
index 0000000..424625f
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/xiaa.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/xiangshui.gif b/Coffeestore/app/src/main/res/drawable-xhdpi/xiangshui.gif
new file mode 100644
index 0000000..9296d7e
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/xiangshui.gif differ
diff --git a/Coffeestore/app/src/main/res/drawable-xhdpi/xiangshuia.gif b/Coffeestore/app/src/main/res/drawable-xhdpi/xiangshuia.gif
new file mode 100644
index 0000000..6126437
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable-xhdpi/xiangshuia.gif differ
diff --git a/Coffeestore/app/src/main/res/drawable/background.jpg b/Coffeestore/app/src/main/res/drawable/background.jpg
new file mode 100644
index 0000000..704014e
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/background.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable/bg1.png b/Coffeestore/app/src/main/res/drawable/bg1.png
new file mode 100644
index 0000000..f702957
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/bg1.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/bg5.jpg b/Coffeestore/app/src/main/res/drawable/bg5.jpg
new file mode 100644
index 0000000..c3d521b
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/bg5.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable/cf1.png b/Coffeestore/app/src/main/res/drawable/cf1.png
new file mode 100644
index 0000000..88bad79
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/cf1.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/cfall.jpg b/Coffeestore/app/src/main/res/drawable/cfall.jpg
new file mode 100644
index 0000000..9804c65
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/cfall.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable/checkbox_selector.xml b/Coffeestore/app/src/main/res/drawable/checkbox_selector.xml
new file mode 100644
index 0000000..f986826
--- /dev/null
+++ b/Coffeestore/app/src/main/res/drawable/checkbox_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/drawable/daifukuan.png b/Coffeestore/app/src/main/res/drawable/daifukuan.png
new file mode 100644
index 0000000..ee0eda6
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/daifukuan.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/daishouhuo.png b/Coffeestore/app/src/main/res/drawable/daishouhuo.png
new file mode 100644
index 0000000..7266b2a
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/daishouhuo.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/edit_text_bg.xml b/Coffeestore/app/src/main/res/drawable/edit_text_bg.xml
new file mode 100644
index 0000000..79d9e38
--- /dev/null
+++ b/Coffeestore/app/src/main/res/drawable/edit_text_bg.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/drawable/editext_selector.xml b/Coffeestore/app/src/main/res/drawable/editext_selector.xml
new file mode 100644
index 0000000..026b164
--- /dev/null
+++ b/Coffeestore/app/src/main/res/drawable/editext_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/drawable/ic_launcher_background.xml b/Coffeestore/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..0d025f9
--- /dev/null
+++ b/Coffeestore/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Coffeestore/app/src/main/res/drawable/ic_left_back.png b/Coffeestore/app/src/main/res/drawable/ic_left_back.png
new file mode 100644
index 0000000..ddf2de1
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/ic_left_back.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/log4.jpg b/Coffeestore/app/src/main/res/drawable/log4.jpg
new file mode 100644
index 0000000..f8070e5
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/log4.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable/ms1.png b/Coffeestore/app/src/main/res/drawable/ms1.png
new file mode 100644
index 0000000..8cd9917
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/ms1.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/msall.jpg b/Coffeestore/app/src/main/res/drawable/msall.jpg
new file mode 100644
index 0000000..1153571
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/msall.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable/nc1.png b/Coffeestore/app/src/main/res/drawable/nc1.png
new file mode 100644
index 0000000..0c0018c
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/nc1.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/nc4.png b/Coffeestore/app/src/main/res/drawable/nc4.png
new file mode 100644
index 0000000..91dc1d6
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/nc4.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/ncall.jpg b/Coffeestore/app/src/main/res/drawable/ncall.jpg
new file mode 100644
index 0000000..ffad3dc
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/ncall.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable/nt1.png b/Coffeestore/app/src/main/res/drawable/nt1.png
new file mode 100644
index 0000000..a8e7a76
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/nt1.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/ntall.jpg b/Coffeestore/app/src/main/res/drawable/ntall.jpg
new file mode 100644
index 0000000..da6c93c
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/ntall.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable/pingjia.png b/Coffeestore/app/src/main/res/drawable/pingjia.png
new file mode 100644
index 0000000..750c722
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/pingjia.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/qps1.png b/Coffeestore/app/src/main/res/drawable/qps1.png
new file mode 100644
index 0000000..56565ab
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/qps1.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/qpsall.jpg b/Coffeestore/app/src/main/res/drawable/qpsall.jpg
new file mode 100644
index 0000000..8e39fbe
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/qpsall.jpg differ
diff --git a/Coffeestore/app/src/main/res/drawable/selector_loginactivity_button.xml b/Coffeestore/app/src/main/res/drawable/selector_loginactivity_button.xml
new file mode 100644
index 0000000..abdf52d
--- /dev/null
+++ b/Coffeestore/app/src/main/res/drawable/selector_loginactivity_button.xml
@@ -0,0 +1,26 @@
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/drawable/shape_edit_focus.xml b/Coffeestore/app/src/main/res/drawable/shape_edit_focus.xml
new file mode 100644
index 0000000..17e8662
--- /dev/null
+++ b/Coffeestore/app/src/main/res/drawable/shape_edit_focus.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/drawable/shape_edit_normal.xml b/Coffeestore/app/src/main/res/drawable/shape_edit_normal.xml
new file mode 100644
index 0000000..04f5b4f
--- /dev/null
+++ b/Coffeestore/app/src/main/res/drawable/shape_edit_normal.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/drawable/shape_oval_red.xml b/Coffeestore/app/src/main/res/drawable/shape_oval_red.xml
new file mode 100644
index 0000000..24b679e
--- /dev/null
+++ b/Coffeestore/app/src/main/res/drawable/shape_oval_red.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/drawable/shouhou.png b/Coffeestore/app/src/main/res/drawable/shouhou.png
new file mode 100644
index 0000000..d0897d0
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/shouhou.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/td4.png b/Coffeestore/app/src/main/res/drawable/td4.png
new file mode 100644
index 0000000..0d6e0e9
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/td4.png differ
diff --git a/Coffeestore/app/src/main/res/drawable/tdall.jpg b/Coffeestore/app/src/main/res/drawable/tdall.jpg
new file mode 100644
index 0000000..6f251e5
Binary files /dev/null and b/Coffeestore/app/src/main/res/drawable/tdall.jpg differ
diff --git a/Coffeestore/app/src/main/res/layout/activity_login.xml b/Coffeestore/app/src/main/res/layout/activity_login.xml
new file mode 100644
index 0000000..a380cf9
--- /dev/null
+++ b/Coffeestore/app/src/main/res/layout/activity_login.xml
@@ -0,0 +1,228 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/layout/activity_main.xml b/Coffeestore/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..6721891
--- /dev/null
+++ b/Coffeestore/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/layout/activity_register.xml b/Coffeestore/app/src/main/res/layout/activity_register.xml
new file mode 100644
index 0000000..0b0ffc0
--- /dev/null
+++ b/Coffeestore/app/src/main/res/layout/activity_register.xml
@@ -0,0 +1,202 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Coffeestore/app/src/main/res/layout/activity_shopping_cart.xml b/Coffeestore/app/src/main/res/layout/activity_shopping_cart.xml
new file mode 100644
index 0000000..39850e8
--- /dev/null
+++ b/Coffeestore/app/src/main/res/layout/activity_shopping_cart.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/layout/activity_shopping_channel.xml b/Coffeestore/app/src/main/res/layout/activity_shopping_channel.xml
new file mode 100644
index 0000000..79cd2a7
--- /dev/null
+++ b/Coffeestore/app/src/main/res/layout/activity_shopping_channel.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/layout/activity_shopping_detail.xml b/Coffeestore/app/src/main/res/layout/activity_shopping_detail.xml
new file mode 100644
index 0000000..e1fdf1f
--- /dev/null
+++ b/Coffeestore/app/src/main/res/layout/activity_shopping_detail.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/layout/activity_shopping_title.xml b/Coffeestore/app/src/main/res/layout/activity_shopping_title.xml
new file mode 100644
index 0000000..0c331a3
--- /dev/null
+++ b/Coffeestore/app/src/main/res/layout/activity_shopping_title.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Coffeestore/app/src/main/res/layout/activity_user.xml b/Coffeestore/app/src/main/res/layout/activity_user.xml
new file mode 100644
index 0000000..df62a21
--- /dev/null
+++ b/Coffeestore/app/src/main/res/layout/activity_user.xml
@@ -0,0 +1,211 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Coffeestore/app/src/main/res/menu/menu_cart.xml b/Coffeestore/app/src/main/res/menu/menu_cart.xml
new file mode 100644
index 0000000..badd69d
--- /dev/null
+++ b/Coffeestore/app/src/main/res/menu/menu_cart.xml
@@ -0,0 +1,19 @@
+
diff --git a/Coffeestore/app/src/main/res/menu/menu_goods.xml b/Coffeestore/app/src/main/res/menu/menu_goods.xml
new file mode 100644
index 0000000..148e614
--- /dev/null
+++ b/Coffeestore/app/src/main/res/menu/menu_goods.xml
@@ -0,0 +1,13 @@
+
diff --git a/Coffeestore/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/Coffeestore/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/Coffeestore/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/Coffeestore/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/Coffeestore/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/mipmap-hdpi/ic_launcher.png b/Coffeestore/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/Coffeestore/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..61da551
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-mdpi/ic_launcher.png b/Coffeestore/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/Coffeestore/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..db5080a
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/hongyun.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/hongyun.png
new file mode 100644
index 0000000..8c9cfde
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/hongyun.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/hongyunn.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/hongyunn.png
new file mode 100644
index 0000000..56af261
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/hongyunn.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..da31a87
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/lianlian.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/lianlian.png
new file mode 100644
index 0000000..c9cd4f8
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/lianlian.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/lianliann.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/lianliann.png
new file mode 100644
index 0000000..b6daec7
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/lianliann.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/pipa.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/pipa.png
new file mode 100644
index 0000000..e043b27
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/pipa.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/ruan.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/ruan.png
new file mode 100644
index 0000000..c47f130
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/ruan.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/weiyi.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/weiyi.png
new file mode 100644
index 0000000..ac1c4ea
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/weiyi.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/weiyin.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/weiyin.png
new file mode 100644
index 0000000..be7fde2
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/weiyin.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/xiangyang.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/xiangyang.png
new file mode 100644
index 0000000..4bbb9b4
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/xiangyang.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/xiangyangn.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/xiangyangn.png
new file mode 100644
index 0000000..dc01930
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/xiangyangn.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/xiannv.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/xiannv.png
new file mode 100644
index 0000000..21862ab
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/xiannv.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/xiannvn.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/xiannvn.png
new file mode 100644
index 0000000..7d5e345
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/xiannvn.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/xiao.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/xiao.png
new file mode 100644
index 0000000..cdd8c4f
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/xiao.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/xiaon.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/xiaon.png
new file mode 100644
index 0000000..2235380
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/xiaon.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xhdpi/zhudi.png b/Coffeestore/app/src/main/res/mipmap-xhdpi/zhudi.png
new file mode 100644
index 0000000..aae982d
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xhdpi/zhudi.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/Coffeestore/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/Coffeestore/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b216f2d
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/Coffeestore/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/Coffeestore/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..e96783c
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xxxhdpi/thumb1.gif b/Coffeestore/app/src/main/res/mipmap-xxxhdpi/thumb1.gif
new file mode 100644
index 0000000..a3694c6
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xxxhdpi/thumb1.gif differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xxxhdpi/thumb2.gif b/Coffeestore/app/src/main/res/mipmap-xxxhdpi/thumb2.gif
new file mode 100644
index 0000000..b6a6ce3
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xxxhdpi/thumb2.gif differ
diff --git a/Coffeestore/app/src/main/res/mipmap-xxxhdpi/thumb3.gif b/Coffeestore/app/src/main/res/mipmap-xxxhdpi/thumb3.gif
new file mode 100644
index 0000000..d8a3795
Binary files /dev/null and b/Coffeestore/app/src/main/res/mipmap-xxxhdpi/thumb3.gif differ
diff --git a/Coffeestore/app/src/main/res/values-night/themes.xml b/Coffeestore/app/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000..203e219
--- /dev/null
+++ b/Coffeestore/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/main/res/values-w820dp/dimens.xml b/Coffeestore/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/Coffeestore/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/Coffeestore/app/src/main/res/values/colors.xml b/Coffeestore/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..b5893d6
--- /dev/null
+++ b/Coffeestore/app/src/main/res/values/colors.xml
@@ -0,0 +1,26 @@
+
+
+ #aaaaff
+ #303F9F
+ #FF4081
+
+ #000000
+ #ffffff
+ #cccccc
+ #ff0000
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+
+
+ #AAF355
+ #37CD3E
+ #64B6F8
+ #A36D1D
+ #B482B5CC
+ #20B2AA
+
+
diff --git a/Coffeestore/app/src/main/res/values/dimens.xml b/Coffeestore/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..47c8224
--- /dev/null
+++ b/Coffeestore/app/src/main/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
diff --git a/Coffeestore/app/src/main/res/values/strings.xml b/Coffeestore/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..65a31f6
--- /dev/null
+++ b/Coffeestore/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ 盲盒咖啡店
+
diff --git a/Coffeestore/app/src/main/res/values/styles.xml b/Coffeestore/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..5c4a90e
--- /dev/null
+++ b/Coffeestore/app/src/main/res/values/styles.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/Coffeestore/app/src/main/res/values/themes.xml b/Coffeestore/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..eebc2d0
--- /dev/null
+++ b/Coffeestore/app/src/main/res/values/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/Coffeestore/app/src/test/java/com/example/storage/ExampleUnitTest.java b/Coffeestore/app/src/test/java/com/example/storage/ExampleUnitTest.java
new file mode 100644
index 0000000..0230048
--- /dev/null
+++ b/Coffeestore/app/src/test/java/com/example/storage/ExampleUnitTest.java
@@ -0,0 +1,15 @@
+package com.example.storage;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/Coffeestore/build.gradle b/Coffeestore/build.gradle
new file mode 100644
index 0000000..f6f49f9
--- /dev/null
+++ b/Coffeestore/build.gradle
@@ -0,0 +1,32 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+
+
+ repositories {
+ google()
+ jcenter()
+ mavenCentral()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:7.0.0'
+ classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ maven { url 'https://jitpack.io' }
+ maven { url "https://raw.github.com/bmob/bmob-android-sdk/master" }
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
+
diff --git a/Coffeestore/gradle.properties b/Coffeestore/gradle.properties
new file mode 100644
index 0000000..52f5917
--- /dev/null
+++ b/Coffeestore/gradle.properties
@@ -0,0 +1,19 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
\ No newline at end of file
diff --git a/Coffeestore/gradle/wrapper/gradle-wrapper.jar b/Coffeestore/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..758de96
Binary files /dev/null and b/Coffeestore/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/Coffeestore/gradle/wrapper/gradle-wrapper.properties b/Coffeestore/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..e471f9e
--- /dev/null
+++ b/Coffeestore/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Dec 15 17:49:53 CST 2022
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/Coffeestore/gradlew b/Coffeestore/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/Coffeestore/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/Coffeestore/gradlew.bat b/Coffeestore/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/Coffeestore/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/Coffeestore/settings.gradle b/Coffeestore/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/Coffeestore/settings.gradle
@@ -0,0 +1 @@
+include ':app'