diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..aa724b7
--- /dev/null
+++ b/.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/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..c9d49c3
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+RF_Week02
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..fb7f4a8
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..a2d7c21
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..bdd9278
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..7501a8a
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,43 @@
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ namespace 'com.animee.rf_week02'
+ compileSdk 32
+
+ defaultConfig {
+ applicationId "com.animee.rf_week02"
+ minSdk 28
+ targetSdk 32
+ 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
+ }
+ buildFeatures {
+ viewBinding true
+ }
+}
+
+dependencies {
+
+ implementation 'androidx.appcompat:appcompat:1.4.1'
+ implementation 'com.google.android.material:material:1.5.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+ implementation 'com.squareup.picasso:picasso:2.5.2'
+}
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/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/app/src/androidTest/java/com/animee/rf_week02/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/animee/rf_week02/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..a57d9d6
--- /dev/null
+++ b/app/src/androidTest/java/com/animee/rf_week02/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.animee.rf_week02;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("com.animee.rf_week02", appContext.getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..9d2ba5a
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/animee/rf_week02/AddressActivity.java b/app/src/main/java/com/animee/rf_week02/AddressActivity.java
new file mode 100644
index 0000000..59fd8f8
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/AddressActivity.java
@@ -0,0 +1,135 @@
+package com.animee.rf_week02;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import com.animee.rf_week02.adapter.AddressAdapter;
+import com.animee.rf_week02.databinding.ActivityAddressBinding;
+import com.animee.rf_week02.db.AddressDao;
+import com.animee.rf_week02.db.DBManager;
+import com.animee.rf_week02.view.SaveAddressDialog;
+import com.animee.rf_week02.view.TitleView;
+import com.animee.rf_week02.view.ToastUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AddressActivity extends AppCompatActivity {
+
+ ActivityAddressBinding binding;
+ List mDatas;
+ private AddressAdapter adapter;
+ SharedPreferences preferences;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ binding = ActivityAddressBinding.inflate(getLayoutInflater());
+ LinearLayout root = binding.getRoot();
+ setContentView(root);
+ setTitleView();
+ preferences = getSharedPreferences("address_pref", MODE_PRIVATE);
+
+ mDatas = new ArrayList<>();
+ // 设置适配器
+ adapter = new AddressAdapter(this, mDatas);
+ binding.addressLv.setAdapter(adapter);
+ // 加载数据库内容
+ loadDBDatas();
+ // 设置ListView的单项点击监听事件
+ binding.addressLv.setOnItemClickListener((parent, view, position, id) -> {
+ AddressDao dao = mDatas.get(position);
+ Intent intent = new Intent();
+ intent.putExtra("ads", dao);
+ setResult(RESULT_OK, intent);
+ finish();
+ });
+ // 添加底部布局
+ addFooterView();
+ }
+
+ private void addFooterView() {
+ View footerView = getLayoutInflater().inflate(R.layout.item_ads_footer, null);
+ Button addBtn = footerView.findViewById(R.id.item_ads_btn_add);
+
+ binding.addressLv.addFooterView(footerView);
+ addBtn.setOnClickListener(view -> {
+ // 弹出添加收货人地址对话框
+ showAdsDialog();
+ });
+ }
+
+ /** 显示保存地址对话框*/
+ private void showAdsDialog() {
+ SaveAddressDialog dialog = new SaveAddressDialog(this);
+ dialog.show();
+ dialog.setOnUpdateAddressListener(dao -> {
+ boolean exist = DBManager.existAddressInDB(dao);
+ if (exist) {
+ ToastUtils.showToast(AddressActivity.this, "收货地址已存在");
+ } else {
+ long l = DBManager.insertAddressToDB(dao);
+ if (l>0) {
+ ToastUtils.showToast(AddressActivity.this, "保存成功");
+ dao.setId((int) l);
+ mDatas.add(dao);
+ adapter.notifyDataSetChanged();
+ }
+ }
+ });
+ }
+
+ private void setTitleView() {
+ binding.addressTitle.setTitle(R.string.address);
+ binding.addressTitle.setVisibleImg(View.VISIBLE, View.GONE);
+ binding.addressTitle.setOnClickLeftImgListener(view -> finish());
+ }
+
+ /** 加载数据库数据, 通知适配器更新*/
+ private void loadDBDatas() {
+ mDatas.clear();
+ List list = DBManager.queryAllAddressFromDB();
+ mDatas.addAll(list);
+ // 读取共享参数的置顶信息
+ int topId = preferences.getInt("top", -1);
+ int defaultId = preferences.getInt("default", -1);
+
+ if (topId != -1 || defaultId != -1) {
+ for (int i = 0; i < mDatas.size(); i++) {
+ AddressDao dao = mDatas.get(i);
+ if (dao.getId() == topId) {
+ mDatas.remove(dao);
+ mDatas.add(0, dao);
+ }
+ if (dao.getId() == defaultId) {
+ dao.setDefault(true);
+ }
+ }
+ }
+ adapter.notifyDataSetChanged();
+ }
+
+ /**
+ * 当前页面被销毁时, 会调用的方法
+ */
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ // 获取需要置顶的数据
+ int topId = mDatas.get(0).getId();
+ // 获取默认的地址的id
+ int defaultId = adapter.getDefaultId();
+ // 写入到共享参数当中
+ SharedPreferences.Editor edit = preferences.edit();
+ edit.putInt("top", topId);
+ edit.putInt("default", defaultId);
+ edit.apply();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/animee/rf_week02/CartActivity.java b/app/src/main/java/com/animee/rf_week02/CartActivity.java
new file mode 100644
index 0000000..782f576
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/CartActivity.java
@@ -0,0 +1,79 @@
+package com.animee.rf_week02;
+
+import static android.content.ContentValues.TAG;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.animee.rf_week02.adapter.CartAdapter;
+import com.animee.rf_week02.bean.ContentDatas;
+import com.animee.rf_week02.bean.InfoBean;
+import com.animee.rf_week02.view.TitleView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CartActivity extends AppCompatActivity {
+ TitleView titleView;
+ ListView cartLv;
+ Button payBtn;
+ TextView totalTv;
+ List mDatas;
+ private CartAdapter adapter;
+
+ private double total; // 总金额
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_cart);
+ initView();
+ setTitleView();
+ loadDatas();
+
+ // 设置适配器
+ adapter = new CartAdapter(this, mDatas);
+ cartLv.setAdapter(adapter);
+ calculateTotalToTv();
+ }
+
+ // 计算购物车总价格, 显示在TextView上
+ public void calculateTotalToTv() {
+ total = 0;
+ for (InfoBean bean : mDatas) {
+ total += bean.getBuycount() * bean.getPrice();
+ }
+ totalTv.setText("¥ " + ((double)Math.round(total*100))/100);
+ }
+
+ private void loadDatas() {
+ mDatas = new ArrayList<>();
+ mDatas.addAll(ContentDatas.getBuyGoodsList());
+ }
+
+ /* 在此处针对页面标题进行设置*/
+ private void setTitleView() {
+ titleView.setTitle(R.string.cart);
+ titleView.setVisibleImg(View.VISIBLE, View.GONE);
+ titleView.setOnClickLeftImgListener(view -> finish());
+ }
+
+ private void initView() {
+ titleView = findViewById(R.id.cart_titleview);
+ cartLv = findViewById(R.id.cart_lv);
+ payBtn = findViewById(R.id.cart_btn_buy);
+ totalTv = findViewById(R.id.cart_tv_total);
+ payBtn.setOnClickListener(view -> {
+ Intent intent = new Intent(CartActivity.this, PayActivity.class);
+ intent.putExtra("total", total);
+ startActivity(intent);
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/animee/rf_week02/DetailTypeActivity.java b/app/src/main/java/com/animee/rf_week02/DetailTypeActivity.java
new file mode 100644
index 0000000..e5915ad
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/DetailTypeActivity.java
@@ -0,0 +1,156 @@
+package com.animee.rf_week02;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.GridView;
+import android.widget.ListView;
+import android.widget.Spinner;
+
+import com.animee.rf_week02.adapter.DetailGVAdapter;
+import com.animee.rf_week02.adapter.DetailLVAdapter;
+import com.animee.rf_week02.bean.ContentDatas;
+import com.animee.rf_week02.bean.InfoBean;
+import com.animee.rf_week02.view.TitleView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class DetailTypeActivity extends AppCompatActivity implements View.OnClickListener {
+
+ private String type;
+ TitleView titleView;
+ Button sortBtn, searchBtn;
+ Spinner spinner;
+ ListView goodsLv;
+ GridView goodsGv;
+ List mDatas; // 列表和网格视图的数据源
+ private DetailLVAdapter lvAdapter;
+ private DetailGVAdapter gvAdapter;
+ private boolean isAscPrice = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_detail_type);
+ // 接收数据
+ type = getIntent().getStringExtra("type");
+ // 初始化view
+ initView();
+ setTitleView();
+ // 设置ListView的内容
+ mDatas = new ArrayList<>();
+
+ // 设置适配器ListView, GridView
+ lvAdapter = new DetailLVAdapter(this, mDatas);
+ goodsLv.setAdapter(lvAdapter);
+
+ gvAdapter = new DetailGVAdapter(this, mDatas);
+ goodsGv.setAdapter(gvAdapter);
+ // 加载数据
+ loadDatas();
+ // 设置spinner的显示
+ String[] arr = {"列表显示", "网格显示"};
+ ArrayAdapter spAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, arr);
+ spinner.setAdapter(spAdapter);
+ // 切换页面的样式
+ changePageStyle();
+ // 设定监听器 搜索, 排序
+ setEvent();
+ }
+
+ private void setEvent() {
+ sortBtn.setOnClickListener(this);
+ }
+
+ /** 通过设置spinner的选中监听器切换页面显示*/
+ private void changePageStyle() {
+ spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> adapterView, View view, int pos, long l) {
+ switch (pos) {
+ case 0:
+ goodsLv.setVisibility(View.VISIBLE);
+ goodsGv.setVisibility(View.GONE);
+ break;
+ case 1:
+ goodsLv.setVisibility(View.GONE);
+ goodsGv.setVisibility(View.VISIBLE);
+ break;
+
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> adapterView) {
+
+ }
+ });
+ }
+
+ /** 第一次加载数据*/
+ private void loadDatas() {
+ for (InfoBean bean : ContentDatas.shopList) {
+ if (bean.getKind().equals(type)) {
+ mDatas.add(bean);
+ }
+ }
+ // 数据源内容发生改变, 提示适配器更新
+ lvAdapter.notifyDataSetChanged();
+ gvAdapter.notifyDataSetChanged();
+ }
+
+
+ private void setTitleView() {
+ titleView.setTitle(type);
+ titleView.setTitleColor(Color.WHITE);
+ titleView.setRightImgResource(R.mipmap.icon_gwc);
+ titleView.setOnClickLeftImgListener(view -> finish());
+ titleView.setOnClickRightImgListener(view -> {
+ // 跳转到购物车页面
+ startActivity(new Intent(DetailTypeActivity.this, CartActivity.class));
+ });
+ }
+
+ private void initView() {
+ titleView = findViewById(R.id.detail_titleview);
+ sortBtn = findViewById(R.id.detail_btn_sort);
+// searchBtn = findViewById(R.id.detail_btn_search);
+ spinner = findViewById(R.id.detail_sp);
+ goodsLv = findViewById(R.id.detail_lv);
+ goodsGv = findViewById(R.id.detail_gv);
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+// case R.id.detail_btn_search:
+// break;
+ case R.id.detail_btn_sort:
+ // 对于数据源当中的价格进行排序 从低到高
+ sortGoodsList();
+ break;
+ }
+ }
+
+ /* 对于商品列表进行排序的方法*/
+ private void sortGoodsList() {
+ if (isAscPrice) {
+ mDatas.sort(Comparator.comparingDouble(InfoBean::getPrice));
+ } else {
+ mDatas.sort((o1, o2) -> Double.compare(o2.getPrice(), o1.getPrice()));
+ }
+ isAscPrice = !isAscPrice;
+ // 提示适配器更新
+ lvAdapter.notifyDataSetChanged();
+ gvAdapter.notifyDataSetChanged();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/animee/rf_week02/MainActivity.java b/app/src/main/java/com/animee/rf_week02/MainActivity.java
new file mode 100644
index 0000000..44efcdb
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/MainActivity.java
@@ -0,0 +1,68 @@
+package com.animee.rf_week02;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import com.animee.rf_week02.bean.ContentDatas;
+import com.animee.rf_week02.view.TitleView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MainActivity extends AppCompatActivity {
+
+ ListView typleLv;
+ TitleView titleView;
+ List mDatas;
+ private ArrayAdapter adapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ initView();
+ // 初始化数据源
+ mDatas = new ArrayList<>();
+ // 设置适配器
+ adapter = new ArrayAdapter<>(this, R.layout.item_mainlv,
+ R.id.item_main_tv, mDatas);
+ typleLv.setAdapter(adapter);
+ // 获取数据
+ loadDatas();
+
+ setEvent();
+ }
+
+ private void setEvent() {
+ typleLv.setOnItemClickListener((adapterView, view, position, l) -> {
+ Intent intent = new Intent(MainActivity.this, DetailTypeActivity.class);
+ intent.putExtra("type", mDatas.get(position));
+ startActivity(intent);
+ });
+ }
+
+ /** 获取并解析网络数据, 将数据放入mDatas数据源当中*/
+ private void loadDatas() {
+ mDatas.addAll(ContentDatas.dailyKindList);
+ // 数据源信息发生改变, 提示适配器再刷新一下
+ adapter.notifyDataSetChanged();
+ }
+
+ private void initView() {
+ typleLv = findViewById(R.id.main_lv);
+ titleView = findViewById(R.id.main_titleview);
+ // 设置标题栏内容
+ titleView.setBgResource(R.color.red);
+ titleView.setTitle(R.string.main_title);
+ titleView.setTitleColor(Color.WHITE);
+ titleView.setVisibleImg(View.VISIBLE, View.INVISIBLE);
+ titleView.setOnClickLeftImgListener(view -> finish());
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/animee/rf_week02/PayActivity.java b/app/src/main/java/com/animee/rf_week02/PayActivity.java
new file mode 100644
index 0000000..9af637d
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/PayActivity.java
@@ -0,0 +1,77 @@
+package com.animee.rf_week02;
+
+import static android.content.ContentValues.TAG;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.animee.rf_week02.databinding.ActivityPayBinding;
+import com.animee.rf_week02.db.AddressDao;
+import com.animee.rf_week02.db.DBManager;
+import com.animee.rf_week02.view.ToastUtils;
+
+public class PayActivity extends AppCompatActivity implements View.OnClickListener {
+ ActivityPayBinding binding;
+ SharedPreferences preferences;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ binding = ActivityPayBinding.inflate(getLayoutInflater());
+ LinearLayout root = binding.getRoot();
+ setContentView(root);
+
+ setTitleView();
+
+ double total = getIntent().getDoubleExtra("total", 0);
+ binding.payEtTotal.setText(((double)Math.round(total*100))/100 + "");
+
+ // 获取默认的收货地址的id
+ preferences = getSharedPreferences("address_pref", MODE_PRIVATE);
+ int defaultId = preferences.getInt("default", -1);
+ AddressDao dao = DBManager.queryAddressById(defaultId);
+ if (dao != null) {
+ binding.payEtShr.setText(dao.getName());
+ binding.payEtTel.setText(dao.getTel());
+ binding.payEtAddress.setText(dao.getCity() + "|" + dao.getStreet());
+ }
+ // 设置取消订单
+ binding.payBtnCancel.setOnClickListener(view -> finish());
+ }
+
+ private void setTitleView() {
+ binding.payTitleview.setTitle("订单");
+ binding.payTitleview.setVisibleImg(View.VISIBLE, View.GONE);
+ binding.payTitleview.setOnClickLeftImgListener(view -> finish());
+
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (view.getId() == R.id.pay_iv_write) {
+ Intent intent = new Intent(PayActivity.this, AddressActivity.class);
+ startActivityIfNeeded(intent, 100);
+ }
+ }
+
+ /**
+ * 接收返回数据显示收货人信息
+ */
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == 100 && resultCode == RESULT_OK) {
+ AddressDao dao = (AddressDao) data.getSerializableExtra("ads");
+ binding.payEtShr.setText(dao.getName());
+ binding.payEtTel.setText(dao.getTel());
+ binding.payEtAddress.setText(dao.getCity() + " | " + dao.getStreet());
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/animee/rf_week02/UniteApp.java b/app/src/main/java/com/animee/rf_week02/UniteApp.java
new file mode 100644
index 0000000..cc9073f
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/UniteApp.java
@@ -0,0 +1,24 @@
+package com.animee.rf_week02;
+
+import android.app.Application;
+
+import com.animee.rf_week02.db.DBManager;
+
+/**
+ * Application
+ * 一个项目可能由多个activity对象, 但是只有一个application对象
+ * 这是个全局对象,一旦项目被启动,这个对象会被创建, 项目光比, 被内存回收, 这个对象才会被回收.
+ * 如何使用自己创建的Application对象
+ * 1. 创建一个类, 继承Application
+ * 2. 重构onCreate
+ * 3. zaiAndroidManifest文件当中, 对于application标签, 进行name属性设置
+ */
+public class UniteApp extends Application {
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ // 进行项目整体的初始化工作
+ DBManager.initDB(getApplicationContext());
+ }
+}
diff --git a/app/src/main/java/com/animee/rf_week02/adapter/AddressAdapter.java b/app/src/main/java/com/animee/rf_week02/adapter/AddressAdapter.java
new file mode 100644
index 0000000..faa32e8
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/adapter/AddressAdapter.java
@@ -0,0 +1,164 @@
+package com.animee.rf_week02.adapter;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.RadioButton;
+import android.widget.TextView;
+
+import com.animee.rf_week02.R;
+import com.animee.rf_week02.databinding.ItemAddressBinding;
+import com.animee.rf_week02.db.AddressDao;
+import com.animee.rf_week02.db.DBManager;
+import com.animee.rf_week02.view.AlertDialogUtils;
+import com.animee.rf_week02.view.SaveAddressDialog;
+import com.animee.rf_week02.view.ToastUtils;
+
+import java.util.List;
+
+public class AddressAdapter extends BaseAdapter {
+
+ Context context;
+ List mDatas;
+ int defaultId;
+
+ public int getDefaultId() {
+ return defaultId;
+ }
+
+ public AddressAdapter(Context context, List mDatas) {
+ this.context = context;
+ this.mDatas = mDatas;
+ }
+
+ @Override
+ public int getCount() {
+ return mDatas.size();
+ }
+
+ @Override
+ public Object getItem(int i) {
+ return mDatas.get(i);
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+ VHolder holder = null;
+ if (view == null) {
+ view = LayoutInflater.from(context).inflate(R.layout.item_address, viewGroup, false);
+ holder = new VHolder(view);
+ view.setTag(holder);
+ } else {
+ holder = (VHolder) view.getTag();
+ }
+ AddressDao dao = mDatas.get(i);
+ holder.binding.itemAdsTvName.setText(dao.getName());
+ holder.binding.itemAdsTvTel.setText(dao.getTel());
+ holder.binding.itemAdsTvCity.setText(dao.getCity());
+ holder.binding.itemAdsTvStreet.setText(dao.getStreet());
+ // 点击事件
+ // 编写修改地址的点击事件
+ updateAddressClick(holder.binding.itemAdsTvModify, dao);
+ // 删除地址的点击事件
+ deleteAddressClick(holder.binding.itemAdsTvDelete, dao);
+ // 复制地址的点击事件
+ copyAddressClick(holder.binding.itemAdsTvCopy, dao);
+ // 置顶的点击事件
+ setTopClick(holder.binding.itemAdsTvTop, dao);
+ // 设置默认的点击事件
+ holder.binding.itemAdsRbDefault.setChecked(dao.isDefault());
+ if (dao.isDefault()) {
+ defaultId = dao.getId();
+ } else {
+ setDefaultClick(holder.binding.itemAdsRbDefault, dao);
+ }
+
+ return view;
+ }
+
+ /**
+ * 设置默认选中的点击事件
+ * @param rb
+ * @param dao
+ */
+ private void setDefaultClick(RadioButton rb, AddressDao dao) {
+ rb.setOnClickListener(view -> {
+ for (AddressDao mData : mDatas) {
+ mData.setDefault(false);
+ }
+ dao.setDefault(true);
+ defaultId = dao.getId();
+ notifyDataSetChanged();
+ });
+ }
+
+ private void setTopClick(TextView view, AddressDao dao) {
+ view.setOnClickListener(view1 -> {
+ // 移除数据源当中这个数据, 放在第一个位置
+ mDatas.remove(dao);
+ mDatas.add(0, dao);
+ notifyDataSetChanged();
+ });
+ }
+
+ /**
+ * 复制地址到复制版当中
+ */
+ private void copyAddressClick(TextView view, AddressDao dao) {
+ view.setOnClickListener(view1 -> {
+ ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
+
+ ClipData clipData = ClipData.newPlainText("Label", dao.toString());
+ cm.setPrimaryClip(clipData);
+ ToastUtils.showToast(context, "复制成功");
+ });
+ }
+
+ private void deleteAddressClick(TextView view, AddressDao dao) {
+ view.setOnClickListener(view1 -> AlertDialogUtils.showNormalDialog(
+ context, "提示信息", "您确定要删除这条收货地址吗?",
+ "取消", "确定", null, () -> {
+ // 删除数据库当中的这条信息
+ DBManager.deleteAddressById(dao.getId());
+ // 删除数据源记录, 通知适配器更新
+ mDatas.remove(dao);
+ notifyDataSetChanged();
+ }));
+ }
+
+ /**
+ * 修改地址功能
+ */
+ private void updateAddressClick(TextView view, AddressDao dao) {
+ view.setOnClickListener(view1 -> {
+ SaveAddressDialog dialog = new SaveAddressDialog(context);
+ dialog.show();
+ dialog.setTitle("修改收获地址");
+ dialog.setAddressDao(dao);
+ dialog.setOnUpdateAddressListener(dao1 -> {
+ // 修改数据库地址
+ DBManager.modifyAddressById(dao1);
+ // 更新数据, 提示适配器更新
+ dao.clone(dao1);
+ notifyDataSetChanged();
+ });
+ });
+ }
+
+ class VHolder {
+ ItemAddressBinding binding;
+
+ public VHolder(View view) {
+ binding = ItemAddressBinding.bind(view);
+ }
+ }
+}
diff --git a/app/src/main/java/com/animee/rf_week02/adapter/CartAdapter.java b/app/src/main/java/com/animee/rf_week02/adapter/CartAdapter.java
new file mode 100644
index 0000000..c205421
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/adapter/CartAdapter.java
@@ -0,0 +1,103 @@
+package com.animee.rf_week02.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.animee.rf_week02.CartActivity;
+import com.animee.rf_week02.R;
+import com.animee.rf_week02.bean.ContentDatas;
+import com.animee.rf_week02.bean.InfoBean;
+import com.animee.rf_week02.view.AmountView;
+import com.squareup.picasso.Picasso;
+
+import java.util.List;
+
+public class CartAdapter extends BaseAdapter {
+
+ Context context;
+ List mDatas;
+
+ public CartAdapter(Context context, List mDatas) {
+ this.context = context;
+ this.mDatas = mDatas;
+ }
+
+ @Override
+ public int getCount() {
+ return mDatas.size();
+ }
+
+ @Override
+ public Object getItem(int i) {
+ return mDatas.get(i);
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+ VHolder holder = null;
+ if (view == null) {
+ view = LayoutInflater.from(context).inflate(R.layout.item_detaillv, viewGroup, false);
+ holder = new VHolder(view);
+ view.setTag(holder);
+ } else {
+ holder = (VHolder) view.getTag();
+ }
+ InfoBean bean = mDatas.get(i);
+
+
+ holder.titleTv.setText(bean.getTitle());
+ holder.priceTv.setText("¥ " + bean.getPrice());
+ holder.typeTv.setText("日常用品 - " + bean.getKind());
+ // 使用picasso加载网络图片加载到本地上
+ Picasso.with(context).load(bean.getPic()).into(holder.iv);
+ // 设置数量选择器
+ holder.amountView.setStorage(bean.getCount());
+ // =============================================================
+ holder.amountView.setShowCount(bean.getBuycount());
+ // 设置按钮的监听事件
+
+ // 设置数量调节器的监听事件
+ holder.amountView.setOnAmountListener(num -> {
+ bean.setBuycount(num);
+ // 重新计算总价格
+ ((CartActivity) context).calculateTotalToTv();
+ });
+ // 设定删除按钮点击事件
+ holder.delIv.setOnClickListener(view1 -> {
+ mDatas.remove(bean);
+ ContentDatas.remove(bean);
+ notifyDataSetChanged();
+ ((CartActivity) context).calculateTotalToTv();
+ });
+ return view;
+ }
+ class VHolder {
+ ImageView iv, delIv;
+ TextView titleTv, priceTv, typeTv;
+ AmountView amountView;
+ Button buyBtn;
+
+ public VHolder(View v) {
+ iv = v.findViewById(R.id.item_dl_iv);
+ delIv = v.findViewById(R.id.item_dl_iv_del);
+ titleTv = v.findViewById(R.id.item_dl_tv_title);
+ priceTv = v.findViewById(R.id.item_dl_tv_price);
+ typeTv = v.findViewById(R.id.item_dl_tv_type);
+ amountView = v.findViewById(R.id.item_dl_av);
+ buyBtn = v.findViewById(R.id.item_dl_btn_buy);
+ buyBtn.setVisibility(View.GONE);
+ delIv.setVisibility(View.VISIBLE);
+ }
+ }
+}
diff --git a/app/src/main/java/com/animee/rf_week02/adapter/DetailGVAdapter.java b/app/src/main/java/com/animee/rf_week02/adapter/DetailGVAdapter.java
new file mode 100644
index 0000000..35dcf42
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/adapter/DetailGVAdapter.java
@@ -0,0 +1,85 @@
+package com.animee.rf_week02.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.animee.rf_week02.R;
+import com.animee.rf_week02.bean.ContentDatas;
+import com.animee.rf_week02.bean.InfoBean;
+import com.animee.rf_week02.view.AmountView;
+import com.animee.rf_week02.view.ToastUtils;
+import com.squareup.picasso.Picasso;
+
+import java.util.List;
+
+public class DetailGVAdapter extends BaseAdapter {
+ Context context;
+ List mDatas;
+
+ public DetailGVAdapter(Context context, List mDatas) {
+ this.context = context;
+ this.mDatas = mDatas;
+ }
+
+
+ @Override
+ public int getCount() {
+ return mDatas.size();
+ }
+
+ @Override
+ public Object getItem(int i) {
+ return mDatas.get(i);
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+ VHolder holder = null;
+ if (view == null) {
+ view = LayoutInflater.from(context).inflate(R.layout.item_detailgv, viewGroup, false);
+ holder = new VHolder(view);
+ view.setTag(holder);
+ } else {
+ holder = (VHolder) view.getTag();
+ }
+ InfoBean bean = mDatas.get(i);
+
+ holder.titleTv.setText(bean.getTitle());
+ holder.priceTv.setText("¥ " + bean.getPrice());
+ // 使用picasso加载网络图片到本地上
+ Picasso.with(context).load(bean.getPic()).into(holder.iv);
+ // 设置按钮的监听事件
+ holder.buyBtn.setOnClickListener(view1 -> {
+ InfoBean newBean = InfoBean.copy(bean);
+ newBean.setBuycount(1);
+ ContentDatas.addGoodsToBuyList(newBean);
+ ToastUtils.showToast(context, "添加成功");
+ });
+ return view;
+ }
+
+ class VHolder {
+ TextView titleTv, priceTv;
+ ImageView iv;
+ Button buyBtn;
+
+ public VHolder(View v) {
+ titleTv = v.findViewById(R.id.item_dg_tv_title);
+ priceTv = v.findViewById(R.id.item_dg_tv_price);
+ iv = v.findViewById(R.id.item_dg_iv);
+ buyBtn = v.findViewById(R.id.item_dg_btn_buy);
+ }
+
+ }
+}
diff --git a/app/src/main/java/com/animee/rf_week02/adapter/DetailLVAdapter.java b/app/src/main/java/com/animee/rf_week02/adapter/DetailLVAdapter.java
new file mode 100644
index 0000000..0212322
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/adapter/DetailLVAdapter.java
@@ -0,0 +1,96 @@
+package com.animee.rf_week02.adapter;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.animee.rf_week02.DetailTypeActivity;
+import com.animee.rf_week02.R;
+import com.animee.rf_week02.bean.ContentDatas;
+import com.animee.rf_week02.bean.InfoBean;
+import com.animee.rf_week02.view.AmountView;
+import com.animee.rf_week02.view.ToastUtils;
+import com.squareup.picasso.Picasso;
+
+import java.util.List;
+
+public class DetailLVAdapter extends BaseAdapter {
+ Context context;
+ List mDatas;
+
+ public DetailLVAdapter(Context context, List mDatas) {
+ this.context = context;
+ this.mDatas = mDatas;
+ }
+
+ @Override
+ public int getCount() {
+ return mDatas.size();
+ }
+
+ @Override
+ public Object getItem(int i) {
+ return mDatas.get(i);
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+ VHolder holder = null;
+ if (view == null) {
+ view = LayoutInflater.from(context).inflate(R.layout.item_detaillv, viewGroup, false);
+ holder = new VHolder(view);
+ view.setTag(holder);
+ } else {
+ holder = (VHolder) view.getTag();
+ }
+ InfoBean bean = mDatas.get(i);
+
+ holder.titleTv.setText(bean.getTitle());
+ holder.priceTv.setText("¥ " + bean.getPrice());
+ holder.typeTv.setText("日常用品 - " + bean.getKind());
+ // 使用picasso加载网络图片加载到本地上
+ Picasso.with(context).load(bean.getPic()).into(holder.iv);
+ // 设置数量选择器
+ holder.amountView.setStorage(bean.getCount());
+ holder.amountView.setShowCount(1);
+ // 设置按钮的监听事件
+ VHolder finalHolder = holder;
+ holder.buyBtn.setOnClickListener(view1 -> {
+ int amountNum = finalHolder.amountView.getAmountNum();
+ InfoBean newBean = InfoBean.copy(bean);
+ newBean.setBuycount(amountNum);
+ ContentDatas.addGoodsToBuyList(newBean);
+ ToastUtils.showToast(context, "添加成功");
+ });
+ return view;
+ }
+
+ class VHolder {
+ ImageView iv, delIv;
+ TextView titleTv, priceTv, typeTv;
+ AmountView amountView;
+ Button buyBtn;
+
+ public VHolder(View v) {
+ iv = v.findViewById(R.id.item_dl_iv);
+ delIv = v.findViewById(R.id.item_dl_iv_del);
+ titleTv = v.findViewById(R.id.item_dl_tv_title);
+ priceTv = v.findViewById(R.id.item_dl_tv_price);
+ typeTv = v.findViewById(R.id.item_dl_tv_type);
+ amountView = v.findViewById(R.id.item_dl_av);
+ buyBtn = v.findViewById(R.id.item_dl_btn_buy);
+ }
+ }
+}
diff --git a/app/src/main/java/com/animee/rf_week02/bean/ContentDatas.java b/app/src/main/java/com/animee/rf_week02/bean/ContentDatas.java
new file mode 100644
index 0000000..57da44c
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/bean/ContentDatas.java
@@ -0,0 +1,90 @@
+package com.animee.rf_week02.bean;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class ContentDatas {
+ public static List dailyKindList = Arrays.asList("调料干货", "零食", "饮料", "烟酒", "厨房用品", "日用品", "清洁用品", "洗化用品");
+ // 商品集合
+ public static List shopList
+ = Arrays.asList(new InfoBean("http://t15.baidu.com/it/u=1118848058,701532755&fm=224&app=112&f=JPEG?w=500&h=500", "低钠盐", "调料干货", 100, 14.00),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg5.21food.cn%2Fimg%2Falbum%2F2017%2F9%2F19%2Ffood13536331244047X7.jpg&refer=http%3A%2F%2Fimg5.21food.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639486346&t=b7aca0e8238f6db68babcda8508f4be7", "优质白砂糖", "调料干货", 350, 16.50),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimage3.suning.cn%2Fuimg%2Fb2c%2Fnewcatentries%2F0070118418-000000000147925824_5_800x800.jpg&refer=http%3A%2F%2Fimage3.suning.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg", "老姜红糖", "调料干货", 350, 24.50),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fn.sinaimg.cn%2Fsinakd202121s%2F419%2Fw700h519%2F20210201%2F709d-kiksqxh4937217.jpg&refer=http%3A%2F%2Fn.sinaimg.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670152659&t=8cce7563a9923ca345c64337eb53f84e", "太太乐鸡精", "调料干货", 350, 18.50),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fqny.smzdm.com%2F202105%2F16%2F60a0b3bb8b63c5683.jpg_d250.jpg&refer=http%3A%2F%2Fqny.smzdm.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg", "金龙鱼实用调和油", "调料干货", 350, 41.00),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimage.suning.cn%2Fcontent%2Fcatentries%2F00000000010690%2F000000000106903642%2Ffullimage%2F000000000106903642_1f.jpg&refer=http%3A%2F%2Fimage.suning.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg", "福临门实用调和油", "调料干货", 250, 46.50),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.51yuansu.com%2Fpic3%2Fcover%2F00%2F79%2F64%2F58c73bcac0cd4_610.jpg&refer=http%3A%2F%2Fbpic.51yuansu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670152759&t=cbdaba0ecad2fe0e895066f8d9f3cb17", "旺旺维粒多", "零食", 200, 3.5),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fduolimi.cn%2FUpLoad%2F2014-8-12%2F20140812142292129212.jpg&refer=http%3A%2F%2Fduolimi.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670152790&t=8982b4fbbc1ac0935daa927334854cf8", "鱿鱼卷", "零食", 200, 14.3),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fqny.smzdm.com%2F202109%2F08%2F61382ef72bdc72248.jpg&refer=http%3A%2F%2Fqny.smzdm.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670152819&t=d2416411f1f0de8130f5b10dd4b3e556", "乐事分享装", "零食", 200, 22.9),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.alicdn.com%2Fimgextra%2Fi2%2F1588913126%2FO1CN01e2GB3u1YxkpEJPS8s_%21%210-item_pic.jpg_400x400.jpg&refer=http%3A%2F%2Fimg.alicdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670152846&t=b8c50e183bdd5d7f8539d366dd635cd8", "旺旺大礼包", "零食", 200, 40.50),
+ new InfoBean("https://img2.baidu.com/it/u=926088687,2201683876&fm=253&fmt=auto&app=138&f=JPEG?w=750&h=332", "旺仔小馒头", "零食", 200, 8.5),
+ new InfoBean("https://img1.baidu.com/it/u=710704254,2877306920&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500", "景田饮用纯净水", "饮料", 120, 5.00),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimgservice.suning.cn%2Fuimg1%2Fb2c%2Fimage%2FKxljet_TrpJGpkdwxe3jhw.jpg_800w_800h_4e&refer=http%3A%2F%2Fimgservice.suning.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670153220&t=6f149b65d4af1845759c08687c146c30", "可口可乐", "饮料", 120, 3.00),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fp1.meituan.net%2Fwmproduct%2F6f611ad7b70a501af6a93cb3dc72da1f215283.jpg%2540249w_249h_1e_1c_1l%7Cwatermark%253D1%2526%2526r%253D1%2526p%253D9%2526x%253D2%2526y%253D2%2526relative%253D1%2526o%253D20&refer=http%3A%2F%2Fp1.meituan.net&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670153253&t=0e2e40824f97eb5519fce2c1920af3a3", "雪碧", "饮料", 120, 3.00),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.yzcdn.cn%2Fupload_files%2F2015%2F04%2F18%2FFq1guyExiPbuPIUKFepobzEGs9o4.jpg%3FimageView2%2F2%2Fw%2F580%2Fh%2F580%2Fq%2F75%2Fformat%2Fjpg&refer=http%3A%2F%2Fimg.yzcdn.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639378582&t=7b34c9c92980e316d3877f2cdbd8781a", "中华(盒)", "烟酒", 500, 50),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.cnxiangyan.com%2Fuploads%2Fallimg%2F200720%2F2706-200H0111242509.jpg&refer=http%3A%2F%2Fwww.cnxiangyan.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639466559&t=70d7d55a334067ed99a8e374b890a1a6", "黄鹤楼(盒)", "烟酒", 200, 20),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.baike.soso.com%2Fugc%2Fbaikepic2%2F31517%2F20170202092126-1334117041.jpg%2F0&refer=http%3A%2F%2Fpic.baike.soso.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639466743&t=02cb2f0e804897fcb72a472942582990", "万宝路(盒)", "烟酒", 300, 22),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.yzcdn.cn%2Fupload_files%2F2017%2F06%2F30%2FFpwlPLqdyp7MWU0e0NaeZMQ_7E4T.jpg%3FimageView2%2F2%2Fw%2F580%2Fh%2F580%2Fq%2F75%2Fformat%2Fjpg&refer=http%3A%2F%2Fimg.yzcdn.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639466857&t=90649667928871a0514c991401665cf1", "玉溪(盒)", "烟酒", 180, 40),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.lingshimiyu.com%2Fuploadfile%2F2018100213565617523.jpg&refer=http%3A%2F%2Fwww.lingshimiyu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670153035&t=3273677af8506c05dc8985a0d8168d6d", "旺旺仙贝", "零食", 3000, 6.8),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.yzcdn.cn%2Fupload_files%2F2018%2F07%2F13%2FFkB7uynmnBbpZg--ghsgDEDEbJ4V.jpg%3FimageView2%2F2%2Fw%2F580%2Fh%2F580%2Fq%2F75%2Fformat%2Fjpg&refer=http%3A%2F%2Fimg.yzcdn.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639382650&t=235174b3d2f9687201935b064ec4e179", "好丽友派", "零食", 200, 12.5),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbkimg.cdn.bcebos.com%2Fpic%2Fac4bd11373f082025aaf523eabb2ecedab64034fadd2&refer=http%3A%2F%2Fbkimg.cdn.bcebos.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670153102&t=714a2a9cade82a58c7ae9ab38fe4886b", "奥利奥", "零食", 300, 10.5),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fqny.smzdm.com%2F202011%2F10%2F5faa0467505085888.jpg_d250.jpg&refer=http%3A%2F%2Fqny.smzdm.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670153135&t=abcdb78d911c690796967c32b8a76424", "趣多多", "零食", 300, 8.8),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.xplian.net%2FtuxpJDEwLmFsaWNkbi5jb20vaTIvMjMwMjMwMjE0Mi9UQjIwT2UxYjlDV0J1Tmp5MEZoWFhiNkVWWGFfISEyMzAyMzAyMTQyJDk.jpg&refer=http%3A%2F%2Fwww.xplian.net&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639457310&t=98957bf46afc7f2b9c75829bc3423587", "可比克薯片", "零食", 300, 8.5),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fgaitaobao3.alicdn.com%2Ftfscom%2Fi1%2FTB16iWoSpXXXXXMXFXXXXXXXXXX_%21%210-item_pic.jpg_300x300.jpg&refer=http%3A%2F%2Fgaitaobao3.alicdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639457890&t=cdfdd11e021783ae4f4435c25b97ae6e", "盼盼膨化饼干", "零食", 300, 13),
+ new InfoBean("http://pic1.zhimg.com/v2-4985e07fa1218110910af1faf3dd1c69_hd.jpg", "蟹黄瓜子", "零食", 230, 9.5),
+ new InfoBean("http://img04.taobaocdn.com/bao/uploaded/i4/T1rWANFrJcXXXXXXXX_!!0-item_pic.jpg", "士力架", "零食", 300, 12),
+ new InfoBean("http://pic4.zhimg.com/v2-dabe30c4df18502b1bf4aa6fa2b1bc31_hd.jpg", "酸奶草莓", "零食", 210, 8.5),
+ new InfoBean("https://gd3.alicdn.com/imgextra/i4/409015871/O1CN01RGzuCI1tExyD6nIGP_!!409015871.jpg", "康师傅方便面/箱", "零食", 400, 60),
+ new InfoBean("https://gd2.alicdn.com/imgextra/i2/760015/O1CN01td3xdm1Byubg6aqY0_!!760015.jpg", "老北京方便面36袋/箱", "零食", 300, 35),
+ new InfoBean("https://gd4.alicdn.com/imgextra/i4/2209812732121/O1CN014Dv4qO1RXSguXewby_!!2209812732121.jpg", "卫龙魔芋爽丝500g", "零食", 200, 1),
+ new InfoBean("https://gd2.alicdn.com/imgextra/i4/2209812732121/O1CN01d4Qosc1RXSk3jCfFr_!!2209812732121.jpg", "卫龙辣条小面筋18g", "零食", 200, 0.5),
+ new InfoBean("https://g-search1.alicdn.com/img/bao/uploaded/i4/i4/1741393998/O1CN01rdupuA1fP8BlsOAQc_!!0-item_pic.jpg_460x460Q90.jpg", "电饭锅支架", "厨房用品", 60, 59.5),
+ new InfoBean("https://g-search1.alicdn.com/img/bao/uploaded/i4/i2/3284480025/O1CN01b0oXkh1C3UXOY59vU_!!0-item_pic.jpg_460x460Q90.jpg", "九阳刀具套装", "厨房用品", 100, 89),
+ new InfoBean("https://g-search2.alicdn.com/img/bao/uploaded/i4/i2/2889308890/O1CN01wBkyqQ2FXfk9Ic9N9_!!0-item_pic.jpg_460x460Q90.jpg", "苏泊尔刀具套装", "厨房用品", 100, 229),
+ new InfoBean("https://g-search3.alicdn.com/img/bao/uploaded/i4/i3/3284480025/O1CN01vZSpsx1C3UcWqtknh_!!0-item_pic.jpg_460x460Q90.jpg_.webp", "九阳油壶", "厨房用品", 200, 29),
+ new InfoBean("https://img.alicdn.com/imgextra/i4/2549841410/O1CN01Fe8qlY1MHp5jCnEf7_!!2549841410.jpg_430x430q90.jpg", "双立人菜刀", "厨房用品", 200, 69),
+ new InfoBean("https://imgservice.suning.cn/uimg1/b2c/image/HrO-XQi8_3SXFkxghHWdtQ.jpg_800w_800h_4e", "飘柔洗发水", "洗化用品", 200, 18),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.alicdn.com%2Fi4%2F2211100827839%2FO1CN01ftONwa27mJSPX5i8b_%21%210-item_pic.jpg&refer=http%3A%2F%2Fimg.alicdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670153334&t=5b7bba59ea84a9066037bc2685e06f71", "潘婷洗发水", "洗化用品", 200, 33),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.alicdn.com%2Fbao%2Fuploaded%2Fi2%2FTB10EsBGXXXXXb9XpXXXXXXXXXX_%21%210-item_pic.jpg_400x400q90.jpg&refer=http%3A%2F%2Fimg.alicdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670153369&t=fe68fe4bd5092ed34eba0198f26cdc67", "海飞丝洗发水", "洗化用品", 200, 19),
+ new InfoBean("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fqna.smzdm.com%2F202108%2F31%2F612e31a879ee68678.jpg_e600.jpg&refer=http%3A%2F%2Fqna.smzdm.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670153418&t=05beed362c43a4ff16828a4d1153a296", "清扬洗发水", "洗化用品", 200, 31));
+
+ /**
+ * 购买商品列表
+ */
+ private static List buyGoodsList = new ArrayList<>();
+
+ public static List getBuyGoodsList() {
+ return buyGoodsList;
+ }
+
+ public static void addGoodsToBuyList(InfoBean bean) {
+ boolean flag = true;
+ for (InfoBean buyBean : buyGoodsList) {
+ if (buyBean.getTitle().equals(bean.getTitle())) {
+ int buycount = bean.getBuycount();
+ buyBean.setBuycount(buyBean.getBuycount() + buycount);
+ flag = false;
+ break;
+ }
+ }
+ if (flag) {
+ buyGoodsList.add(bean);
+ }
+ }
+
+ public static void printBuyList() {
+ Log.i("lsh", "printBuyList: size====" + buyGoodsList.size());
+ String msg = "";
+ for (InfoBean bean : buyGoodsList) {
+ msg = bean.getTitle() + ":" + bean.getBuycount();
+ Log.i("lsh", "printBuyList: goods=~~~" + msg);
+ }
+ }
+
+ public static void remove(InfoBean bean) {
+ buyGoodsList.remove(bean);
+ }
+}
diff --git a/app/src/main/java/com/animee/rf_week02/bean/InfoBean.java b/app/src/main/java/com/animee/rf_week02/bean/InfoBean.java
new file mode 100644
index 0000000..cf99153
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/bean/InfoBean.java
@@ -0,0 +1,68 @@
+package com.animee.rf_week02.bean;
+/* 表示每一个用品对象*/
+public class InfoBean {
+ private String pic; //图片地址
+ private String title; //标题
+ private String kind; //种类
+ private int count; //库存
+ private double price; //价格
+ private int buycount = 0; //购买数量
+
+ public InfoBean() {}
+ public InfoBean(String pic, String title, String kind, int count, double price, int buycount) {
+ this.pic = pic;
+ this.title = title;
+ this.kind = kind;
+ this.count = count;
+ this.price = price;
+ this.buycount = buycount;
+ }
+ public int getBuycount() {
+ return buycount;
+ }
+ public void setBuycount(int buycount) {
+ this.buycount = buycount;
+ }
+ public String getPic() {
+ return pic;
+ }
+ public void setPic(String pic) {
+ this.pic = pic;
+ }
+ public String getTitle() {
+ return title;
+ }
+ public void setTitle(String title) {
+ this.title = title;
+ }
+ public String getKind() {
+ return kind;
+ }
+ public void setKind(String kind) {
+ this.kind = kind;
+ }
+ public int getCount() {
+ return count;
+ }
+ public void setCount(int count) {
+ this.count = count;
+ }
+ public double getPrice() {
+ return price;
+ }
+ public void setPrice(double price) {
+ this.price = price;
+ }
+ public InfoBean(String pic, String title, String kind, int count, double price) {
+ this.pic = pic;
+ this.title = title;
+ this.kind = kind;
+ this.count = count;
+ this.price = price;
+ }
+
+ public static InfoBean copy(InfoBean oldBean){
+ return new InfoBean(oldBean.getPic(),oldBean.getTitle(),oldBean.getKind(),
+ oldBean.getCount(),oldBean.getPrice());
+ }
+}
diff --git a/app/src/main/java/com/animee/rf_week02/db/AddressDao.java b/app/src/main/java/com/animee/rf_week02/db/AddressDao.java
new file mode 100644
index 0000000..f2ff57b
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/db/AddressDao.java
@@ -0,0 +1,132 @@
+package com.animee.rf_week02.db;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * 用户地址
+ */
+public class AddressDao implements Serializable {
+
+ private int id;
+ private String name;
+ private String tel;
+ private String city;
+ private String street;
+ private Boolean isDefault;
+ private Boolean isTop;
+
+ public AddressDao() {
+ }
+
+ public AddressDao(int id, String name, String tel, String city, String street) {
+ this.id = id;
+ this.name = name;
+ this.tel = tel;
+ this.city = city;
+ this.street = street;
+ }
+
+ public AddressDao(int id, String name, String tel, String city, String street, Boolean isDefault, Boolean isTop) {
+ this.id = id;
+ this.name = name;
+ this.tel = tel;
+ this.city = city;
+ this.street = street;
+ this.isDefault = isDefault;
+ this.isTop = isTop;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ AddressDao dao = (AddressDao) o;
+ return Objects.equals(name, dao.name) && Objects.equals(tel, dao.tel) && Objects.equals(city, dao.city) && Objects.equals(street, dao.street);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, tel, city, street);
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTel() {
+ return tel;
+ }
+
+ public void setTel(String tel) {
+ this.tel = tel;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public Boolean getDefault() {
+ return isDefault;
+ }
+
+ public boolean isDefault() {
+ if (isDefault == null) {
+ return false;
+ }
+ return isDefault;
+ }
+
+ public void setDefault(Boolean aDefault) {
+ isDefault = aDefault;
+ }
+
+ public Boolean getTop() {
+ return isTop;
+ }
+
+ public void setTop(Boolean top) {
+ isTop = top;
+ }
+
+ public void clone(AddressDao dao) {
+ this.setName(dao.getName());
+ this.setCity(dao.getCity());
+ this.setTel(dao.getTel());
+ this.setStreet(dao.getStreet());
+ this.setId(dao.getId());
+ }
+
+ @Override
+ public String toString() {
+ return "姓名:" + name +
+ ", 电话:" + tel +
+ ", 地址:" + city + street;
+ }
+
+
+}
diff --git a/app/src/main/java/com/animee/rf_week02/db/DBManager.java b/app/src/main/java/com/animee/rf_week02/db/DBManager.java
new file mode 100644
index 0000000..bd00b8e
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/db/DBManager.java
@@ -0,0 +1,111 @@
+package com.animee.rf_week02.db;
+
+import android.annotation.SuppressLint;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 数据库管理工具
+ */
+public class DBManager {
+
+ private static SQLiteDatabase db;
+
+ public static void initDB(Context context) {
+ DBOpenHelper helper = new DBOpenHelper(context);
+ db = helper.getWritableDatabase();
+ }
+
+ /**
+ * 查询用户地址信息表全部内容
+ */
+ @SuppressLint({"Recycle", "Range"})
+ public static List queryAllAddressFromDB() {
+ List list = new ArrayList<>();
+ String sql = "select * from addresstb";
+ Cursor cursor = db.rawQuery(sql, null);
+ while (cursor.moveToNext()) {
+ int id = cursor.getInt(cursor.getColumnIndex("id"));
+ String name = cursor.getString(cursor.getColumnIndex("name"));
+ String tel = cursor.getString(cursor.getColumnIndex("tel"));
+ String city = cursor.getString(cursor.getColumnIndex("city"));
+ String street = cursor.getString(cursor.getColumnIndex("street"));
+ AddressDao dao = new AddressDao(id, name, tel, city, street);
+ list.add(dao);
+ }
+ return list;
+ }
+
+ /**
+ * 查询address是否存在
+ *
+ * @param dao
+ * @return
+ */
+ public static boolean existAddressInDB(AddressDao dao) {
+ String sql = "select * from addresstb" +
+ " where name = '" + dao.getName() + "'" +
+ " and tel = '" + dao.getTel() + "'" +
+ " and city = '" + dao.getCity() + "'" +
+ " and street = '" + dao.getStreet() + "'";
+ Cursor cursor = db.rawQuery(sql, null);
+ int count = cursor.getCount();
+ return count > 0;
+ }
+
+ /**
+ * 插入地址到数据库当中
+ */
+ public static long insertAddressToDB(AddressDao dao) {
+ ContentValues values = new ContentValues();
+ values.put("name", dao.getName());
+ values.put("tel", dao.getTel());
+ values.put("city", dao.getCity());
+ values.put("street", dao.getStreet());
+
+ return db.insert("addresstb", null, values);
+ }
+
+ /**
+ * 通过id修改该数据库内容
+ * @param dao
+ */
+ public static int modifyAddressById(AddressDao dao) {
+ ContentValues values = new ContentValues();
+ values.put("name", dao.getName());
+ values.put("tel", dao.getTel());
+ values.put("city", dao.getCity());
+ values.put("street", dao.getStreet());
+
+ return db.update("addresstb", values, "id = " + dao.getId(), null);
+ }
+
+ /**
+ * 通过id删除数据库的地址
+ * @param id
+ */
+ public static int deleteAddressById(int id) {
+ int i = db.delete("addresstb", "id = " + id, null);
+ return i;
+ }
+
+ @SuppressLint("Range")
+ public static AddressDao queryAddressById(int defaultId) {
+ Cursor cursor= db.query("addresstb", null, "id = " + defaultId, null, null, null, null);
+ if (cursor.moveToFirst()) {
+ int id = cursor.getInt(cursor.getColumnIndex("id"));
+ String name = cursor.getString(cursor.getColumnIndex("name"));
+ String tel = cursor.getString(cursor.getColumnIndex("tel"));
+ String city = cursor.getString(cursor.getColumnIndex("city"));
+ String street = cursor.getString(cursor.getColumnIndex("street"));
+ return new AddressDao(id, name, tel, city, street);
+ }
+ return null;
+ }
+
+}
diff --git a/app/src/main/java/com/animee/rf_week02/db/DBOpenHelper.java b/app/src/main/java/com/animee/rf_week02/db/DBOpenHelper.java
new file mode 100644
index 0000000..072b77d
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/db/DBOpenHelper.java
@@ -0,0 +1,47 @@
+package com.animee.rf_week02.db;
+
+import android.content.Context;
+import android.database.DatabaseErrorHandler;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public class DBOpenHelper extends SQLiteOpenHelper {
+ public DBOpenHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
+ super(context, name, factory, version);
+ }
+
+ public DBOpenHelper(@Nullable Context context) {
+ super(context, "heartgo.db", null, 1);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ String sql =
+ "create table addresstb(" +
+ "id integer primary key autoincrement," +
+ "name varchar(30) not null," +
+ "tel varchar(20) not null," +
+ "city varchar(50)," +
+ "street varchar(255)" +
+ ")";
+ db.execSQL(sql);
+
+ // 测试添加一条记录
+ sql = "insert into addresstb values (1, '张三', '12345678912', '四川', '天府新区1号楼')";
+ db.execSQL(sql);
+
+ sql = "insert into addresstb values (2, '李四', '13549846515', '重庆', '阳关小区1号楼')";
+ db.execSQL(sql);
+
+ sql = "insert into addresstb values (3, '王五', '15916549163', '杭州', '翻斗花园1号楼')";
+ db.execSQL(sql);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
+
+ }
+}
diff --git a/app/src/main/java/com/animee/rf_week02/view/AlertDialogUtils.java b/app/src/main/java/com/animee/rf_week02/view/AlertDialogUtils.java
new file mode 100644
index 0000000..ab98b27
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/view/AlertDialogUtils.java
@@ -0,0 +1,32 @@
+package com.animee.rf_week02.view;
+
+import android.app.AlertDialog;
+import android.app.DatePickerDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+
+public class AlertDialogUtils {
+ public interface OnBtnClickListener {
+ public void onBtnClick();
+ }
+
+ public static void showNormalDialog(Context context, String title, String msg,
+ String lInfo, String rInfo,
+ OnBtnClickListener lListener, OnBtnClickListener rListener) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(title)
+ .setMessage(msg)
+ .setPositiveButton(rInfo, (dialog, i) -> {
+ if (rListener != null) {
+ rListener.onBtnClick();
+ }
+ dialog.cancel();
+ }).setNegativeButton(lInfo, (dialog, i) -> {
+ if (lListener != null) {
+ lListener.onBtnClick();
+ }
+ dialog.cancel();
+ });
+ builder.create().show();
+ }
+}
diff --git a/app/src/main/java/com/animee/rf_week02/view/AmountView.java b/app/src/main/java/com/animee/rf_week02/view/AmountView.java
new file mode 100644
index 0000000..202781f
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/view/AmountView.java
@@ -0,0 +1,136 @@
+package com.animee.rf_week02.view;
+
+import android.content.Context;
+import android.os.TestLooperManager;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+import androidx.annotation.Nullable;
+
+import com.animee.rf_week02.R;
+import com.google.android.material.internal.TextWatcherAdapter;
+
+public class AmountView extends LinearLayout implements View.OnClickListener {
+ private Button subBtn, addBtn;
+ private EditText numEt;
+ private int storage = 100;
+ private int showCount = 1;
+
+ // 设置产品库存
+ public void setStorage(int storage) {
+ this.storage = storage;
+ }
+
+ // 设置显示数量
+ public void setShowCount(int count) {
+ this.showCount = count;
+ numEt.setText("" + showCount);
+ }
+
+ // 将这个view当中的数量传递出去
+ public interface OnAmountListener {
+ public void onAmount(int num);
+ }
+
+ OnAmountListener onAmountListener;
+
+ public void setOnAmountListener(OnAmountListener onAmountListener) {
+ this.onAmountListener = onAmountListener;
+ }
+
+ public AmountView(Context context) {
+ this(context, null);
+ }
+
+ public AmountView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ LayoutInflater.from(context).inflate(R.layout.amount_view, this);
+ initView();
+ }
+
+ private void initView() {
+ subBtn = findViewById(R.id.amount_btn_sub);
+ addBtn = findViewById(R.id.amount_btn_plus);
+ numEt = findViewById(R.id.amount_et);
+ subBtn.setOnClickListener(this);
+ addBtn.setOnClickListener(this);
+ // 设置输入框的监听器
+ numEt.addTextChangedListener(watcher);
+ }
+ // 返回输入框当中的数据
+ public int getAmountNum() {
+ String after = numEt.getText().toString().trim();
+ if (TextUtils.isEmpty(after)) {
+ return 1;
+ }
+ return Integer.parseInt(after);
+ }
+ TextWatcher watcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+// Log.d("beforeTextChanged : ", charSequence.toString()
+// + ", " + i + ", " + i1 + ", " + i2);
+ }
+
+ @Override
+ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+// Log.d("onTextChanged : ", charSequence.toString()
+// + ", " + i + ", " + i1 + ", " + i2);
+// System.out.println();
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ String after = editable.toString().trim();
+ if (TextUtils.isEmpty(after)) {
+ showCount = 1;
+ numEt.setText("1");
+ return;
+ }
+ showCount = Integer.parseInt(after);
+ if (showCount < 1) {
+ showCount = 1;
+ numEt.setText(showCount + "");
+ } else if (showCount > storage) {
+ showCount = storage;
+ numEt.setText(showCount + "");
+ }
+
+ if (onAmountListener != null) {
+ onAmountListener.onAmount(showCount);
+ }
+ }
+ };
+
+ @Override
+ public void onClick(View view) {
+ String numstr = numEt.getText().toString().trim();
+ int num = Integer.parseInt(numstr);
+ switch (view.getId()) {
+ case R.id.amount_btn_sub:
+ if (num > 1) {
+ num--;
+ }
+ break;
+ case R.id.amount_btn_plus:
+ if (num < storage) {
+ num++;
+ }
+ break;
+ }
+ numEt.clearFocus(); // 失去焦点
+ numEt.setText(num + "");
+ if (onAmountListener != null) {
+ onAmountListener.onAmount(showCount);
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/animee/rf_week02/view/SaveAddressDialog.java b/app/src/main/java/com/animee/rf_week02/view/SaveAddressDialog.java
new file mode 100644
index 0000000..16dc5f4
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/view/SaveAddressDialog.java
@@ -0,0 +1,120 @@
+package com.animee.rf_week02.view;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+import androidx.annotation.NonNull;
+
+import com.animee.rf_week02.R;
+import com.animee.rf_week02.databinding.DialogAddressBinding;
+import com.animee.rf_week02.db.AddressDao;
+
+import java.util.regex.Pattern;
+
+public class SaveAddressDialog extends Dialog implements View.OnClickListener {
+ DialogAddressBinding binding;
+ AddressDao addressDao; // 修改地址会传入地址内容
+
+ public SaveAddressDialog(@NonNull Context context) {
+ super(context);
+ }
+
+ public interface OnUpdateAddressListener {
+ public void onUpdateAddress(AddressDao dao);
+ }
+
+ private OnUpdateAddressListener onUpdateAddressListener;
+
+ public void setOnUpdateAddressListener(OnUpdateAddressListener onUpdateAddressListener) {
+ this.onUpdateAddressListener = onUpdateAddressListener;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ binding = DialogAddressBinding.inflate(getLayoutInflater());
+ RelativeLayout root = binding.getRoot();
+ setContentView(root);
+ setEvent();
+ }
+
+ private void setEvent() {
+ binding.dgAdsBtn.setOnClickListener(this);
+ binding.dgAdsIvCancel.setOnClickListener(this);
+ }
+
+ /**
+ * 修改对话框标题方法
+ */
+ public void setTitle(String msg) {
+ binding.dgAdsTvTitle.setText(msg);
+ }
+
+ /**
+ * 设置对话框中输入框的显示
+ */
+ public void setAddressDao(AddressDao dao) {
+ this.addressDao = dao;
+ binding.dgAdsEtShr.setText(dao.getName());
+ binding.dgAdsEtTel.setText(dao.getTel());
+ binding.dgAdsEtCity.setText(dao.getCity());
+ binding.dgAdsEtStreet.setText(dao.getStreet());
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.dg_ads_btn:
+ AddressDao dao = judgeInputMsg();
+ // 添加新地址逻辑: 如果这个地址没有一摸一样的就添加数据库, 如果有一样的就不添加, 提示用户
+ if (dao != null) {
+ // 判断是否传入了原来的地址, 没有传入说明是添加地址, 否则为修改地址
+ if (this.addressDao == null) {
+ if (onUpdateAddressListener != null) { // 增加地址的判断
+ onUpdateAddressListener.onUpdateAddress(dao);
+ }
+ } else { // 修改地址的判断
+ // 1. 判断修改该内容和原来内容是否一致, 完全一致, 不修改, 提示用户
+ if (dao.equals(this.addressDao)) {
+ ToastUtils.showToast(getContext(), "未进行修改该, 于原内容一致! ");
+ } else {
+ // 2. 不一致, 将修改该后的数据回调回去, 在回调之前设置id, 在适配器更新地址
+ dao.setId(addressDao.getId());
+ if (onUpdateAddressListener != null) { // 增加地址的判断
+ onUpdateAddressListener.onUpdateAddress(dao);
+ }
+ }
+ }
+ cancel();
+ }
+ break;
+ case R.id.dg_ads_iv_cancel:
+ cancel();
+ break;
+
+ }
+ }
+
+ private AddressDao judgeInputMsg() {
+ String name = binding.dgAdsEtShr.getText().toString().trim();
+ String tel = binding.dgAdsEtTel.getText().toString().trim();
+ String city = binding.dgAdsEtCity.getText().toString().trim();
+ String street = binding.dgAdsEtStreet.getText().toString().trim();
+
+ if (TextUtils.isEmpty(name) || TextUtils.isEmpty(tel) || TextUtils.isEmpty(city) || TextUtils.isEmpty(street)) {
+ ToastUtils.showToast(getContext(), "输入信息不能为空");
+ return null;
+ }
+ // 手机号的正则表达式
+ if (!Pattern.matches("^1[3-9]\\d{9}$", tel)) {
+ ToastUtils.showToast(getContext(), "输入手机号不符合规则");
+ return null;
+ }
+ return new AddressDao(0, name, tel, city, street);
+ }
+
+}
diff --git a/app/src/main/java/com/animee/rf_week02/view/TitleView.java b/app/src/main/java/com/animee/rf_week02/view/TitleView.java
new file mode 100644
index 0000000..54ca084
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/view/TitleView.java
@@ -0,0 +1,129 @@
+package com.animee.rf_week02.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.animee.rf_week02.R;
+
+/**
+ * 接口回调:
+ * 当这个类的某项事件由他触发, 但是功能不是由他决定, 就可以用接口回调解决
+ * 1. 创建接口, 编写回调方法
+ * 2. 在这个类中, 将接口设置为成员变量, 然后通过set方法对其进行赋值
+ * 2. 在被触发的地方调用这个接口的方法
+ */
+public class TitleView extends RelativeLayout implements View.OnClickListener {
+ private ImageView leftIv, rightIv;
+ private TextView titleTv;
+ private RelativeLayout layout;
+
+ public interface OnclickImgListener {
+ public void onClick(View view);
+ }
+
+ OnclickImgListener leftListener, rightListener;
+
+ public void setOnClickLeftImgListener(OnclickImgListener leftListener) {
+ this.leftListener = leftListener;
+ }
+
+ public void setOnClickRightImgListener(OnclickImgListener rightListener) {
+ this.rightListener = rightListener;
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.title_iv_left:
+// ((Activity)getContext()).finish();
+ if (leftListener != null) {
+ leftListener.onClick(view);
+ }
+ break;
+ case R.id.title_iv_right:
+ if (rightListener != null) {
+ rightListener.onClick(view);
+ }
+ break;
+ }
+ }
+
+ // 在代码当中创建view对象时, 会调用的构造方法
+ public TitleView(Context context) {
+ this(context, null);
+ }
+
+ // 在布局当中些view对象时, 会调用的构造方法
+ public TitleView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ LayoutInflater.from(context).inflate(R.layout.title_layout, this);
+ initView();
+ setEvent();
+ }
+
+ private void setEvent() {
+ leftIv.setOnClickListener(this);
+ rightIv.setOnClickListener(this);
+ }
+
+ private void initView() {
+ leftIv = findViewById(R.id.title_iv_left);
+ rightIv = findViewById(R.id.title_iv_right);
+ titleTv = findViewById(R.id.title_tv);
+ layout = findViewById(R.id.title_view);
+ }
+
+ /**
+ * 设置标题
+ */
+ public void setTitle(String title) {
+ titleTv.setText(title);
+ }
+
+ public void setTitle(int titleId) {
+ titleTv.setText(titleId);
+ }
+
+ /**
+ * 设置标题颜色
+ */
+ public void setTitleColor(int color) {
+ titleTv.setTextColor(color);
+ }
+
+ /**
+ * 设置背景颜色
+ */
+ public void setBgResource(int color) {
+ layout.setBackgroundResource(color);
+ }
+
+ public void setBdColor(int color) {
+ layout.setBackgroundColor(color);
+ }
+
+ /**
+ * 设置是否显示左右图片
+ */
+ public void setVisibleImg(int left, int right) {
+ leftIv.setVisibility(left);
+ rightIv.setVisibility(right);
+ }
+
+ /**
+ * 修改左边显示图片
+ */
+ public void setLeftImgResource(int resId) {
+ leftIv.setImageResource(resId);
+ }
+
+ public void setRightImgResource(int resId) {
+ rightIv.setImageResource(resId);
+ }
+
+}
diff --git a/app/src/main/java/com/animee/rf_week02/view/ToastUtils.java b/app/src/main/java/com/animee/rf_week02/view/ToastUtils.java
new file mode 100644
index 0000000..4a3a17c
--- /dev/null
+++ b/app/src/main/java/com/animee/rf_week02/view/ToastUtils.java
@@ -0,0 +1,11 @@
+package com.animee.rf_week02.view;
+
+import android.content.Context;
+import android.widget.Toast;
+
+public class ToastUtils {
+
+ public static void showToast(Context context, String msg) {
+ Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
+ }
+}
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/amount_btn.xml b/app/src/main/res/drawable/amount_btn.xml
new file mode 100644
index 0000000..ae2f096
--- /dev/null
+++ b/app/src/main/res/drawable/amount_btn.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_btn.xml b/app/src/main/res/drawable/bg_btn.xml
new file mode 100644
index 0000000..ffaf215
--- /dev/null
+++ b/app/src/main/res/drawable/bg_btn.xml
@@ -0,0 +1,15 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_detailbtn.xml b/app/src/main/res/drawable/bg_detailbtn.xml
new file mode 100644
index 0000000..4ef7006
--- /dev/null
+++ b/app/src/main/res/drawable/bg_detailbtn.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..07d5da9
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_address.xml b/app/src/main/res/layout/activity_address.xml
new file mode 100644
index 0000000..5ff8c63
--- /dev/null
+++ b/app/src/main/res/layout/activity_address.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_cart.xml b/app/src/main/res/layout/activity_cart.xml
new file mode 100644
index 0000000..5d6970d
--- /dev/null
+++ b/app/src/main/res/layout/activity_cart.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_detail_type.xml b/app/src/main/res/layout/activity_detail_type.xml
new file mode 100644
index 0000000..578253c
--- /dev/null
+++ b/app/src/main/res/layout/activity_detail_type.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..30f37d7
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_pay.xml b/app/src/main/res/layout/activity_pay.xml
new file mode 100644
index 0000000..1403d93
--- /dev/null
+++ b/app/src/main/res/layout/activity_pay.xml
@@ -0,0 +1,214 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/amount_view.xml b/app/src/main/res/layout/amount_view.xml
new file mode 100644
index 0000000..d1e29a2
--- /dev/null
+++ b/app/src/main/res/layout/amount_view.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_address.xml b/app/src/main/res/layout/dialog_address.xml
new file mode 100644
index 0000000..2957b64
--- /dev/null
+++ b/app/src/main/res/layout/dialog_address.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_address.xml b/app/src/main/res/layout/item_address.xml
new file mode 100644
index 0000000..d6a1361
--- /dev/null
+++ b/app/src/main/res/layout/item_address.xml
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_ads_footer.xml b/app/src/main/res/layout/item_ads_footer.xml
new file mode 100644
index 0000000..b3cd19f
--- /dev/null
+++ b/app/src/main/res/layout/item_ads_footer.xml
@@ -0,0 +1,15 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_detailgv.xml b/app/src/main/res/layout/item_detailgv.xml
new file mode 100644
index 0000000..0a1bc0c
--- /dev/null
+++ b/app/src/main/res/layout/item_detailgv.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_detaillv.xml b/app/src/main/res/layout/item_detaillv.xml
new file mode 100644
index 0000000..af77761
--- /dev/null
+++ b/app/src/main/res/layout/item_detaillv.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_mainlv.xml b/app/src/main/res/layout/item_mainlv.xml
new file mode 100644
index 0000000..ba62aea
--- /dev/null
+++ b/app/src/main/res/layout/item_mainlv.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/title_layout.xml b/app/src/main/res/layout/title_layout.xml
new file mode 100644
index 0000000..dc09051
--- /dev/null
+++ b/app/src/main/res/layout/title_layout.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml
new file mode 100644
index 0000000..6f3b755
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 0000000..c209e78
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..b2dfe3d
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_back.png b/app/src/main/res/mipmap-hdpi/icon_back.png
new file mode 100644
index 0000000..2bd9d9e
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_back.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_close.png b/app/src/main/res/mipmap-hdpi/icon_close.png
new file mode 100644
index 0000000..b89c41c
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_close.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_gwc.png b/app/src/main/res/mipmap-hdpi/icon_gwc.png
new file mode 100644
index 0000000..326870e
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_gwc.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_laji.png b/app/src/main/res/mipmap-hdpi/icon_laji.png
new file mode 100644
index 0000000..5ab6199
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_laji.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_money.png b/app/src/main/res/mipmap-hdpi/icon_money.png
new file mode 100644
index 0000000..2f57216
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_money.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_more.png b/app/src/main/res/mipmap-hdpi/icon_more.png
new file mode 100644
index 0000000..890c3bb
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_more.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_nav.png b/app/src/main/res/mipmap-hdpi/icon_nav.png
new file mode 100644
index 0000000..eeb975e
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_nav.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_nt.png b/app/src/main/res/mipmap-hdpi/icon_nt.png
new file mode 100644
index 0000000..ad74472
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_nt.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_search.png b/app/src/main/res/mipmap-hdpi/icon_search.png
new file mode 100644
index 0000000..5eeebe2
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_search.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_setting.png b/app/src/main/res/mipmap-hdpi/icon_setting.png
new file mode 100644
index 0000000..0b6f63f
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_setting.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_write.png b/app/src/main/res/mipmap-hdpi/icon_write.png
new file mode 100644
index 0000000..debe987
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_write.png differ
diff --git a/app/src/main/res/mipmap-hdpi/popup.png b/app/src/main/res/mipmap-hdpi/popup.png
new file mode 100644
index 0000000..3dd9e51
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/popup.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 0000000..4f0f1d6
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..62b611d
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 0000000..948a307
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..1b9a695
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..28d4b77
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..9287f50
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..aa7d642
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..9126ae3
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000..568081b
--- /dev/null
+++ b/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..d8f54da
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,13 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+ #FFFF0000
+ #DCDCDC
+ #808080
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..4b6da52
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,28 @@
+
+ RF_Week02
+ 安心Go
+ 点击搜索
+ 价格排序
+ 列表展示
+ 网格展示
+ 购买
+ 设定为默认
+ 已设定为默认
+ 修改
+ 删除
+ 置顶
+ 复制
+ 添加收货地址
+ 收货地址
+ 购物车
+ 收货人:
+ 收货人姓名
+ 收货人手机号
+ 手机号:
+ 地 区:
+ 地 址:
+ 地区省市
+ 如街道, 门牌号, 小区, 村镇等
+ 保存
+ 加入购物车
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..f39d105
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 0000000..fa0f996
--- /dev/null
+++ b/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 0000000..9ee9997
--- /dev/null
+++ b/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/com/animee/rf_week02/ExampleUnitTest.java b/app/src/test/java/com/animee/rf_week02/ExampleUnitTest.java
new file mode 100644
index 0000000..5fdd359
--- /dev/null
+++ b/app/src/test/java/com/animee/rf_week02/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.animee.rf_week02;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..0114b27
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,5 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ id 'com.android.application' version '7.4.1' apply false
+ id 'com.android.library' version '7.4.1' apply false
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..3e927b1
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,21 @@
+# 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
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..e708b1c
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..e44aa33
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sat Apr 15 17:38:59 CST 2023
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..4f906e0
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, 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"
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@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 Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@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="-Xmx64m" "-Xms64m"
+
+@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 execute
+
+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 execute
+
+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
+
+: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 %*
+
+: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/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..ebda9bf
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,16 @@
+pluginManagement {
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+rootProject.name = "RF_Week02"
+include ':app'