效果图:源码与教程在文章末尾
登录界面
展示应用的登录页面,包罗用户名输入框、密码输入框、登录按钮、注册按钮以及记着密码复选框。背景为轮播图,展示商城的特色商品或运动海报,吸引用户留意。
商品列表界面
呈现商品列表页面,左侧为商品分类列表,以列表形式展示各类商品分类,如推荐、手机、电脑等,点击可切换不同分类商品。右侧为商品展示地区,使用网格布局展示商品图片、标题和代价等信息,商品图片清晰展示商品表面,标题简洁明白,代价突出显示。
商品详情界面
显示商品详情页面,顶部为商品图片,占据较大空间,以高清大图展示商品细节,吸引用户购买。下方依次为商品标题、商品详环境貌、代价信息以及参加购物车按钮。商品详环境貌详细介绍商品的特点、功能、材质等信息,帮助用户相识商品。
5.4 购物车界面
展示购物车页面,使用列表布局展示购物车中的商品信息,每行包括商品图片、标题、代价、数目、增加按钮、减少按钮和删除按钮。底部显示购物车中商品的总价,方便用户查看。
5.5 订单列表界面
呈现订单列表页面,同样采用列表布局,展示订单的详细信息,包括订单中的商品图片、标题、代价、数目、收货地点、接洽方式以及订单状态。用户可长按订单进行删除操纵,订单状态以不同颜色或标识区分,如待发货、已发货、已完成等。
使用SQLiteOpenHelper类实现数据库的创建
重写相应的方法,创建创建user_table用户数据表,全局使用的shareperfermence来存储用户名和密码,实现记着密码 的功能
- package com.example.shoppingmall.db;
- 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 androidx.annotation.Nullable;
- import com.example.shoppingmall.entity.UserInfo;
- public class UserDbHelper extends SQLiteOpenHelper {
- private static UserDbHelper sHelper;
- private static final String DB_NAME = "user.db"; //数据库名
- private static final int VERSION = 1; //版本号
- //必须实现其中一个构方法
- public UserDbHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
- super(context, name, factory, version);
- }
- //创建单例,供使用调用该类里面的的增删改查的方法
- public synchronized static UserDbHelper getInstance(Context context) {
- if (null == sHelper) {
- sHelper = new UserDbHelper(context, DB_NAME, null, VERSION);
- }
- return sHelper;
- }
- @Override
- public void onCreate(SQLiteDatabase db) {
- //创建user_table表
- db.execSQL("create table user_table(user_id integer primary key autoincrement, " +
- "username text," + //用户名
- "password text," + //密码
- "nickname text" + //
- ")");
- }
- @Override
- public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
- }
- /**
- * 登录
- */
- /**
- * 登录 根据用户名查找用户
- */
- @SuppressLint("Range")
- public UserInfo login(String username) {
- //获取SQLiteDatabase实例
- SQLiteDatabase db = getReadableDatabase();
- UserInfo userInfo = null;
- String sql = "select user_id,username,password,nickname from user_table where username=?";
- String[] selectionArgs = {username};
- Cursor cursor = db.rawQuery(sql, selectionArgs);
- if (cursor.moveToNext()) {
- int user_id = cursor.getInt(cursor.getColumnIndex("user_id"));
- String name = cursor.getString(cursor.getColumnIndex("username"));
- String password = cursor.getString(cursor.getColumnIndex("password"));
- String nickname = cursor.getString(cursor.getColumnIndex("nickname"));
- userInfo = new UserInfo(user_id, name, password, nickname);
- }
- cursor.close();
- db.close();
- return userInfo;
- }
- /**
- * 注册
- */
- public int register(String username, String password, String nickname) {
- //获取SQLiteDatabase实例
- SQLiteDatabase db = getWritableDatabase();
- ContentValues values = new ContentValues();
- //填充占位符
- values.put("username", username);
- values.put("password", password);
- values.put("nickname", nickname);
- String nullColumnHack = "values(null,?,?,?)";
- //执行
- int insert = (int) db.insert("user_table", nullColumnHack, values);
- db.close();
- return insert;
- }
- //TODO 在这里根据自己的业务需求,编写增删改查的方法,如下所示
- /**
- * 修改密码
- */
- public int updatePwd(String username, String password) {
- //获取SQLiteDatabase实例
- SQLiteDatabase db = getWritableDatabase();
- // 填充占位符
- ContentValues values = new ContentValues();
- values.put("password", password);
- // 执行SQL
- int update = db.update("user_table", values, " username=?", new String[]{username});
- // 关闭数据库连接
- db.close();
- return update;
- }
- }
复制代码 用户信息实体类
- package com.example.shoppingmall.entity;
- public class UserInfo {
- private int user_id;
- private String username;
- private static UserInfo sUserInfo;
- public int getUser_id() {
- return user_id;
- }
- public void setUser_id(int user_id) {
- this.user_id = user_id;
- }
- public String getNickname() {
- return nickname;
- }
- public void setNickname(String nickname) {
- this.nickname = nickname;
- }
- public static UserInfo getsUserInfo() {
- return sUserInfo;
- }
- public static void setsUserInfo(UserInfo sUserInfo) {
- UserInfo.sUserInfo = sUserInfo;
- }
- private String password;
- private String nickname;
- public static UserInfo getUserInfo() {
- return sUserInfo;
- }
- public UserInfo(int user_id, String username, String password, String nickname) {
- this.user_id = user_id;
- this.username = username;
- this.password = password;
- this.nickname = nickname;
- }
- public static void setUserInfo(UserInfo userInfo) {
- sUserInfo = userInfo;
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- }
复制代码 然后编写登录启动页后的布局文件
然后注册后的信息存到SQLite 数据库, 编写登录页面跳转逻辑与验证账号密码的关系,获取用户名和密码的输入值,与存入到数据库注册的进行对比,记着密码的复选框也是通过preferences 对象的getBoolean 方法来获取判断的。复选框中的checkBox 也有判断逻辑; 假如设置的用户信息在数据库中存在这,把相对应的数据放到文本框不清楚。
- // 从数据库中查询用户信息
- UserInfo login = UserDbHelper.getInstance(LoginActivity.this).login(username);
- if (login != null) {
- // 验证用户名和密码是否匹配
- if (username.equals(login.getUsername()) && password.equals(login.getPassword())) {
- // 保存用户的登录状态和信息到 SharedPreferences
- SharedPreferences.Editor editor = preferences.edit();
- editor.putBoolean("is_login", checkBox.isChecked());
- editor.putString("username", username);
- editor.putString("password", password);
- editor.apply();
- // 设置用户信息
- UserInfo.setUserInfo(login);
- Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
- // 跳转到主界面
- Intent intent = new Intent(this, MainActivity.class);
- startActivity(intent);
- finish();
- } else {
- Toast.makeText(this, "用户名或密码错误", Toast.LENGTH_SHORT).show();
- }
- } else {
- Toast.makeText(this, "账号未注册", Toast.LENGTH_SHORT).show();
- }
- }
- });
复制代码 轮播图的效果
在主要登录界面中有布局文件指示器和viewpager组件
- <!-- 轮播图 ViewPager -->
- <androidx.viewpager.widget.ViewPager
- android:id="@+id/viewPager"
- android:layout_width="match_parent"
- android:layout_height="200dp" />
- <!-- 小圆点指示器 -->
- <LinearLayout
- android:id="@+id/layoutDots"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:gravity="center"
- android:layout_marginTop="8dp">
- </LinearLayout>
复制代码 然后在主登录文件Java代码中初始化组件和 图片数组用于存储图片,加上PageAdapter适配器来充分渲染数据;
- private ViewPager viewPager;
- // 用于显示小圆点指示器的 LinearLayout
- private LinearLayout layoutDots;
- // 轮播图的图片资源数组
- private int[] images = {R.drawable.equipment, R.drawable.thefive, R.drawable.re_2, R.drawable.sport, R.drawable.jianguo};
- // 小圆点指示器数组
复制代码 还有效于定时自动轮播和获取当前索引的属性值的全局变量
- // 用于定时任务的 Handler
- private Handler handler = new Handler();
- // 定时任务的 Runnable
- private Runnable runnable;
- // 当前显示的图片索引
- private int currentPage = 0;
复制代码 分别界说三个方法, 表示适配器、监听器、启动自动切换任务的方法
- // 设置 ViewPager 的适配器和监听器
- setupViewPager();
- // 设置小圆点指示器
- setupDots();
- // 启动自动切换任务
- startAutoSlide();
复制代码 在setUpviewpager 方法中有页面滚动和页面选中时的回调方法
- // 设置 ViewPager 的适配器和监听器
- private void setupViewPager() {
- viewPager.setAdapter(new SliderAdapter());
- viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
- // 页面滚动时的回调方法
- }
- @Override
- public void onPageSelected(int position) {
- // 页面选中时的回调方法
- currentPage = position;
- updateDots(position);
- }
- @Override
- public void onPageScrollStateChanged(int state) {
- // 页面滚动状态改变时的回调方法
- if (state == ViewPager.SCROLL_STATE_IDLE) {
- // 当页面滚动停止时,启动自动切换
- startAutoSlide();
- } else {
- // 当页面正在滚动或被拖动时,停止自动切换
- stopAutoSlide();
- }
- }
- });
- }
复制代码 再设置一下小圆点指示器的状态还有切换后图片与原点绑定数据监听后的状态
- // 设置小圆点指示器
- @SuppressLint("UseCompatLoadingForDrawables")
- private void setupDots() {
- dots = new ImageView[images.length];
- for (int i = 0; i < dots.length; i++) {
- dots[i] = new ImageView(this);
- dots[i].setImageDrawable(getResources().getDrawable(R.drawable.dot_inactive));
- LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
- LinearLayout.LayoutParams.WRAP_CONTENT,
- LinearLayout.LayoutParams.WRAP_CONTENT
- );
- params.setMargins(8, 0, 8, 0);
- layoutDots.addView(dots[i], params);
- }
- updateDots(currentPage);
- }
- // 更新小圆点指示器的状态
- @SuppressLint("UseCompatLoadingForDrawables")
- private void updateDots(int position) {
- for (int i = 0; i < dots.length; i++) {
- dots[i].setImageDrawable(getResources().getDrawable(R.drawable.dot_inactive));
- }
- dots[position].setImageDrawable(getResources().getDrawable(R.drawable.dot_active));
- }
复制代码 启动启动切换图片的方法,new 了一个 Runnable 子线程, 重写了run方法,判断当前是不是最后一张图片图片,假如是 把索引设置为零,切换到第一张图片; 假如不是的话就索引加加, // 否则,切换到下一张图片
currentPage++;
通过viewPager的setCurrentItem方法来设置当前的索引图片;延迟1s实行;
焦点代码:
- // 启动自动切换任务
- private void startAutoSlide() {
- runnable = new Runnable() {
- @Override
- public void run() {
- if (currentPage == images.length - 1) {
- // 如果当前是最后一张图片,则跳转到第一张图片
- currentPage = 0;
- } else {
- // 否则,切换到下一张图片
- currentPage++;
- }
- // 设置 ViewPager 显示当前图片
- viewPager.setCurrentItem(currentPage, true);
- // 延迟1秒后再次执行此任务
- handler.postDelayed(this, 1500);
- }
- };
- // 延迟1秒后开始执行自动切换任务
- handler.postDelayed(runnable, 1500);
- }
- // 停止自动切换任务
- private void stopAutoSlide() {
- handler.removeCallbacks(runnable);
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- // 在 Activity 销毁时停止自动切换任务,避免内存泄漏
- stopAutoSlide();
- }
- // 自定义 ViewPager 的适配器
- private class SliderAdapter extends PagerAdapter {
- @Override
- public int getCount() {
- // 返回图片的数量
- return images.length;
- }
- @Override
- public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
- // 判断 view 是否与 object 对应
- return view == object;
- }
- @NonNull
- @Override
- public Object instantiateItem(@NonNull ViewGroup container, int position) {
- // 创建一个新的 ImageView 并设置图片资源
- ImageView imageView = new ImageView(LoginActivity.this);
- imageView.setImageResource(images[position]);
- imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
- container.addView(imageView);
- return imageView;
- }
- @Override
- public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
- // 移除不再使用的 ImageView
- container.removeView((ImageView) object);
- }
- }
- }
复制代码 -----------点点点……………………………………代码太多,省略RecyclerView.Adapter、Fragment、订单、购物车等适配器与详细结合的逻辑
代码,记载此次大作业的感受,如有兴趣的小同伴可以观看视频教程进行学习
目教程B站传送门-教程原地点
https://www.bilibili.com/video/BV1PjHfeXE8U/?spm_id_from=333.337.search-card.all.click&vd_source=2f1ec19ac9bc251863dc1c409be61ab4
通过网盘分享的文件:购物商城app源码rar.rar
链接: https://pan.baidu.com/s/1jGYMPdYXDP9tWBmjQNjD_Q?pwd=ricd 提取码: ricd
–来自百度网盘超级会员v2的分享
记载作业精美时刻,假如本篇博客对你有帮助的话就点个赞再走吧········~~``````````~~~~ |