Android Studio App开发实战项目之实现淘宝电商App首页界面(附源码,可用于大作业参考)

需要源码和图片集请点赞关注收藏后评论区留言或者私信~~~

各家电商的App首页都是动感十足,页面元素丰富令人眼花缭乱,其中运用了Android的多种组合控件,可以说是App界面开发的集大成之作,下面我们也动手实现一个。

一、需求描述

本次项目主要模仿淘宝App采用的技术,所以有底部标签栏,顶部也有标题栏,并且对于分类页面的商品列表,也会有高低不一呈现的瀑布流效果

二、界面设计

界面主要用到了以下控件

1:底部标签栏

2:广告条

3:循环视图RecyclerView

4:工具栏Toolbar

5:标签布局TabLaout

6:第二代翻页视图

7:循环视图的瀑布流布局

8:下拉刷新布局

三、关键部分

1:在ScrollView内部添加RecyclerView

2:关于ViewPager+Fragment的多重嵌套

3:电商首页项目的源码之间关系

与本次项目主要有关的代码之间关系如下

1:DepartmentStoreActivity.java 这是电商App首页的入口代码

2:DepartmentPagerAdapter.java  这是电商首页集成3个碎片页的翻页适配代码

3:DepartmentHomeFragment.java 这是首页标签对应的碎片代码

4:DepartmentClassFragment.java 这是分类标签对应的碎片代码

5:DepartmentCartFragment.java 这是购物车标签对应的碎片代码

四、演示效果 

首页效果如下

 点击下方的标签栏可切换

点击上方的标签栏可以切换到时装频道

 

购物车频道可以参见我之前的博客

 

五、代码 

主类代码

package com.example.chapter12;import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;import android.os.Bundle;
import android.widget.RadioButton;
import android.widget.RadioGroup;import com.example.chapter12.adapter.DepartmentPagerAdapter;public class DepartmentStoreActivity extends AppCompatActivity {private ViewPager vp_content; // 声明一个翻页视图对象private RadioGroup rg_tabbar; // 声明一个单选组对象@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_department_store);vp_content = findViewById(R.id.vp_content);// 构建一个翻页适配器DepartmentPagerAdapter adapter = new DepartmentPagerAdapter(getSupportFragmentManager());vp_content.setAdapter(adapter); // 设置翻页视图的适配器// 给翻页视图添加页面变更监听器vp_content.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {@Overridepublic void onPageSelected(int position) {// 选中指定位置的单选按钮rg_tabbar.check(rg_tabbar.getChildAt(position).getId());}});rg_tabbar = findViewById(R.id.rg_tabbar);// 设置单选组的选中监听器rg_tabbar.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {for (int pos=0; pos<rg_tabbar.getChildCount(); pos++) {// 获得指定位置的单选按钮RadioButton tab = (RadioButton) rg_tabbar.getChildAt(pos);if (tab.getId() == checkedId) { // 正是当前选中的按钮vp_content.setCurrentItem(pos); // 设置翻页视图显示第几页}}}});}
}

适配器类代码

package com.example.chapter12.adapter;import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;import com.example.chapter12.fragment.DepartmentHomeFragment;
import com.example.chapter12.fragment.DepartmentClassFragment;
import com.example.chapter12.fragment.DepartmentCartFragment;public class DepartmentPagerAdapter extends FragmentPagerAdapter {// 碎片页适配器的构造方法,传入碎片管理器public DepartmentPagerAdapter(FragmentManager fm) {super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);}// 获取指定位置的碎片Fragmentpublic Fragment getItem(int position) {if (position == 0) {return new DepartmentHomeFragment();} else if (position == 1) {return new DepartmentClassFragment();} else if (position == 2) {return new DepartmentCartFragment();} else {return null;}}// 获取碎片Fragment的个数public int getCount() {return 3;}
}

碎片类代码

package com.example.chapter12.fragment;import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;import com.example.chapter12.R;public class DepartmentCartFragment extends Fragment {protected View mView; // 声明一个视图对象protected AppCompatActivity mActivity; // 声明一个活动对象@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {mActivity = (AppCompatActivity) getActivity();mView = inflater.inflate(R.layout.fragment_department_cart, container, false);// 从布局文件中获取名叫tl_head的工具栏Toolbar tl_head = mView.findViewById(R.id.tl_head);tl_head.setTitle("购物车"); // 设置工具栏的标题文字mActivity.setSupportActionBar(tl_head); // 使用tl_head替换系统自带的ActionBarreturn mView;}
}

2

package com.example.chapter12.fragment;import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.widget.ViewPager2;import com.example.chapter12.R;
import com.example.chapter12.adapter.ClassPagerAdapter;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;import java.util.ArrayList;
import java.util.List;public class DepartmentClassFragment extends Fragment {protected View mView; // 声明一个视图对象protected AppCompatActivity mActivity; // 声明一个活动对象private List<String> mTitleList = new ArrayList<String>(); // 标题文字列表@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {mActivity = (AppCompatActivity) getActivity();mView = inflater.inflate(R.layout.fragment_department_class, container, false);// 从布局文件中获取名叫tl_head的工具栏Toolbar tl_head = mView.findViewById(R.id.tl_head);mActivity.setSupportActionBar(tl_head); // 使用tl_head替换系统自带的ActionBarmTitleList.add("服装");mTitleList.add("电器");// 从布局文件中获取名叫tab_title的标签布局TabLayout tab_title = mView.findViewById(R.id.tab_title);// 从布局文件中获取名叫vp2_content的二代翻页视图ViewPager2 vp2_content = mView.findViewById(R.id.vp2_content);// 构建一个分类信息的翻页适配器。注意Fragment嵌套时要传getChildFragmentManagerClassPagerAdapter adapter = new ClassPagerAdapter(mActivity, mTitleList);vp2_content.setAdapter(adapter); // 设置二代翻页视图的适配器// 把标签布局跟翻页视图通过指定策略连为一体,二者在页面切换时一起联动new TabLayoutMediator(tab_title, vp2_content, new TabLayoutMediator.TabConfigurationStrategy() {@Overridepublic void onConfigureTab(TabLayout.Tab tab, int position) {tab.setText(mTitleList.get(position)); // 设置每页的标签文字}}).attach();return mView;}}

3

package com.example.chapter12.fragment;import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;import com.example.chapter12.R;
import com.example.chapter12.adapter.MobileGridAdapter;
import com.example.chapter12.adapter.MobileRecyclerAdapter;
import com.example.chapter12.adapter.RecyclerCombineAdapter;
import com.example.chapter12.adapter.RecyclerGridAdapter;
import com.example.chapter12.bean.GoodsInfo;
import com.example.chapter12.bean.NewsInfo;
import com.example.chapter12.util.Utils;
import com.example.chapter12.widget.BannerPager;
import com.example.chapter12.widget.SpacesDecoration;import java.util.ArrayList;
import java.util.List;public class DepartmentHomeFragment extends Fragment implements BannerPager.BannerClickListener {protected View mView; // 声明一个视图对象protected AppCompatActivity mActivity; // 声明一个活动对象private List<Integer> getImageList() {ArrayList<Integer> imageList = new ArrayList<Integer>();imageList.add(R.drawable.banner_1);imageList.add(R.drawable.banner_2);imageList.add(R.drawable.banner_3);imageList.add(R.drawable.banner_4);imageList.add(R.drawable.banner_5);return imageList;}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {mActivity = (AppCompatActivity) getActivity();mView = inflater.inflate(R.layout.fragment_department_home, container, false);// 从布局文件中获取名叫tl_head的工具栏Toolbar tl_head = mView.findViewById(R.id.tl_head);tl_head.setTitle("商城首页"); // 设置工具栏的标题文字mActivity.setSupportActionBar(tl_head); // 使用tl_head替换系统自带的ActionBarinitBanner(); // 初始化广告轮播条initGrid(); // 初始化市场网格列表initCombine(); // 初始化猜你喜欢的商品展示网格initPhone(); // 初始化手机网格列表return mView;}private void initBanner() {// 从布局文件中获取名叫banner_pager的广告轮播条BannerPager banner = mView.findViewById(R.id.banner_pager);// 获取广告轮播条的布局参数LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) banner.getLayoutParams();params.height = (int) (Utils.getScreenWidth(mActivity) * 250f / 640f);banner.setLayoutParams(params); // 设置广告轮播条的布局参数banner.setImage(getImageList()); // 设置广告轮播条的广告图片列表banner.setOnBannerListener(this); // 设置广告轮播条的广告点击监听器banner.start(); // 开始轮播广告图片}// 一旦点击了广告图,就回调监听器的onBannerClick方法public void onBannerClick(int position) {String desc = String.format("您点击了第%d张图片", position + 1);Toast.makeText(mActivity, desc, Toast.LENGTH_LONG).show();}private void initGrid() {// 从布局文件中获取名叫rv_grid的循环视图RecyclerView rv_grid = mView.findViewById(R.id.rv_grid);// 创建一个网格布局管理器GridLayoutManager manager = new GridLayoutManager(mActivity, 5);rv_grid.setLayoutManager(manager); // 设置循环视图的布局管理器// 构建一个市场列表的网格适配器RecyclerGridAdapter adapter = new RecyclerGridAdapter(mActivity, NewsInfo.getDefaultGrid());adapter.setOnItemClickListener(adapter); // 设置网格列表的点击监听器adapter.setOnItemLongClickListener(adapter); // 设置网格列表的长按监听器rv_grid.setAdapter(adapter); // 设置循环视图的网格适配器rv_grid.setItemAnimator(new DefaultItemAnimator()); // 设置循环视图的动画效果rv_grid.addItemDecoration(new SpacesDecoration(1)); // 设置循环视图的空白装饰}private void initCombine() {// 从布局文件中获取名叫rv_combine的循环视图RecyclerView rv_combine = mView.findViewById(R.id.rv_combine);// 创建一个四列的网格布局管理器GridLayoutManager manager = new GridLayoutManager(mActivity, 4);// 设置网格布局管理器的占位规则// 以下占位规则的意思是:第一项和第二项占两列,其它项占一列;// 如果网格的列数为四,那么第一项和第二项平分第一行,第二行开始每行有四项。manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {@Overridepublic int getSpanSize(int position) {if (position == 0 || position == 1) { // 为第一项或者第二项return 2; // 占据两列} else { // 为其它项return 1; // 占据一列}}});rv_combine.setLayoutManager(manager); // 设置循环视图的布局管理器// 构建一个猜你喜欢的网格适配器RecyclerCombineAdapter adapter = new RecyclerCombineAdapter(mActivity, NewsInfo.getDefaultCombine());adapter.setOnItemClickListener(adapter); // 设置网格列表的点击监听器adapter.setOnItemLongClickListener(adapter); // 设置网格列表的长按监听器rv_combine.setAdapter(adapter); // 设置循环视图的网格适配器rv_combine.setItemAnimator(new DefaultItemAnimator());  // 设置循环视图的动画效果rv_combine.addItemDecoration(new SpacesDecoration(1));  // 设置循环视图的空白装饰}private void initPhone() {// 从布局文件中获取名叫rv_phone的循环视图RecyclerView rv_phone = mView.findViewById(R.id.rv_phone);// 创建一个网格布局管理器GridLayoutManager manager = new GridLayoutManager(mActivity, 3);rv_phone.setLayoutManager(manager); // 设置循环视图的布局管理器// 构建一个手机列表的循环适配器MobileGridAdapter adapter = new MobileGridAdapter(mActivity, GoodsInfo.getDefaultList());rv_phone.setAdapter(adapter); // 设置循环视图的网格适配器adapter.setOnItemClickListener(adapter); // 设置网格列表的点击监听器adapter.setOnItemLongClickListener(adapter); // 设置网格列表的长按监听器rv_phone.setItemAnimator(new DefaultItemAnimator()); // 设置循环视图的动画效果rv_phone.addItemDecoration(new SpacesDecoration(1)); // 设置循环视图的空白装饰}}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><androidx.viewpager.widget.ViewPagerandroid:id="@+id/vp_content"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1" /><RadioGroupandroid:id="@+id/rg_tabbar"android:layout_width="match_parent"android:layout_height="60dp"android:orientation="horizontal"><RadioButtonandroid:id="@+id/rb_home"style="@style/TabButton"android:checked="true"android:text="首页"android:drawableTop="@drawable/tab_first_selector" /><RadioButtonandroid:id="@+id/rb_class"style="@style/TabButton"android:text="分类"android:drawableTop="@drawable/tab_second_selector" /><RadioButtonandroid:id="@+id/rb_cart"style="@style/TabButton"android:text="购物车"android:drawableTop="@drawable/tab_third_selector" /></RadioGroup></LinearLayout>

创作不易 觉得有帮助请点赞关注收藏~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/158272.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2022年12月 电子学会青少年软件编程 中小学生Python编程 等级考试一级真题答案解析(选择题)

2022年12月Python编程等级考试一级真题解析 选择题(共25题,每题2分,共50分) 1、关于Python语言的注释,以下选项中描述错误的是 A、Python语言有两种注释方式:单行注释和多行注释 B、Python语言的单行注释以#开头 C、Python多行注释使用###来做为标记 D、注释用于解…

goland 远程调试 remote debug

1、远程服务器装好go环境&#xff0c;并设置国内源 linux go安装 参考&#xff1a; 如何在 Debian / Ubuntu 上安装 Go 开发环境 - 知乎 设置国内源 go env -w GOPROXYhttps://goproxy.cn,direct 2、远程服务器安装dlv git clone https://github.com/derekparker/delve.gi…

docker 部署hbase 并且java Api连接

首先先运行容器 docker run -d --name hbase -p 2181:2181 -p 16010:16010 -p16000:16000 -p 16020:16020 -p 16030:16030 harisekhon/hbase2.在本机的hosts中注册docker的id 因为docker内部集成了其他环境而其他环境 中的ip是docker id 所以需要在hosts中转换 192.168.80.120…

docken安装mysql并开启binlog

docker pull mysql:5.6 docker run -d -p 3306:3306 --name mysql5.6 -e MYSQL_ROOT_PASSWORD123456 --privilegedtrue mysql:5.6 docker exec -it mysql5.6 bash find /etc -name mysqld.cnf 找到配置文件/etc/mysql/mysql.conf.d/mysqld.cnf docker cp mysql5.6:/e…

MeterSphere | 接口测试请求体中,int类型的入参实现动态化变量

项目场景&#xff1a; 在接口自动化的时候&#xff0c;要把上一个接口的 Int 变量传入到 下一个接口中进行使用&#xff0c;但编译器会出现 红色的 X 符号 问题描述 如何实现 int 类型的入参实现动态化变量&#xff1f; 解决方案&#xff1a; 忽视掉这个红色 X 号&#xff0…

【Linux】xfs文件系统的xfs_info命令

xfs_info命令 ① 查看命令工具自身的版本号 xfs_info -V ② 查看指定XFS设备的详细信息 xfs_info <device_name> 其他的一些命令可以使用man xfs_info去查阅man手册&#xff1a;

优化记录 -- 记一次搜索引擎(SOLR)优化

业务场景 某服务根据用户相关信息&#xff0c;使用搜索引擎进行数据检索 软件配置 solr 1台&#xff1a;32c 64g 数据10gb左右&#xff0c;版本 7.5.5 应用服务器1台&#xff1a;16c 64g 应用程序 3节点 问题产生现象 1、因业务系统因处理能不足&#xff0c;对业务系统硬件…

不看后悔系列 | 秒做BI报表,告别低效分析

根据经验来看&#xff0c;做企业数据分析&#xff0c;通常是由业务提出需求&#xff0c;交给IT去取数开发&#xff0c;当业务通过分析报表有了新的需求时&#xff0c;仍需交给IT去取数分析&#xff0c;这就导致业务的分析效率低。进入大数据时代&#xff0c;这样的低效数据分析…

稳定性保障8个锦囊,建议收藏!

稳定性保障&#xff0c;是一切技术工作的出发点和落脚点&#xff0c;也是 IT 工作最核心的价值体现&#xff0c;当然也是技术人员最容易“翻车”的阴沟。8个稳定性保障锦囊&#xff0c;分享给各位技术人员择机使用。 #1 设定可量化的、业务可理解的可用性目标 没有度量就没有改…

2304. 网格中的最小路径代价 : 从「图论最短路」过渡到「O(1) 空间的原地模拟」

题目描述 这是 LeetCode 上的 「2304. 网格中的最小路径代价」 &#xff0c;难度为 「中等」。 Tag : 「最短路」、「图」、「模拟」、「序列 DP」、「动态规划」 给你一个下标从 0 开始的整数矩阵 grid&#xff0c;矩阵大小为 m x n&#xff0c;由从 0 到 的不同整数组成。 你…

深入理解JSON及其在Java中的应用

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a;每天一个知识点 ✨特色专栏&#xff1a…

2024中国眼博会,北京国际护眼产品与视力防控产品展览会

与社会各界眼康同仁一道&#xff0c;打造2024年度全国唯具参展价值的盛会-CEYEE中国眼博会&#xff1b; CEYEE中国眼博会概要&#xff1a; ——中国&#xff08;北京&#xff09;国际青少年眼健康产业展览会China (Beijing) International Youth eye health industry exhibiti…

集成电路工厂用什么ERP?哪家的集成电路ERP比较好

集成电路通常对制造工艺、生产设备、品质检验等方面有较高的要求&#xff0c;而随着智能技术和自动化技术的发展成熟&#xff0c;如今集成电路行业逐渐迈入数字化和智能化阶段&#xff0c;而至这个时代背景当中&#xff0c;很多集成电路工厂借助ERP实现信息化转型升级。 时至今…

java/Android:将字符串按数量分割

分割成数组 import java.util.Arrays;/*** Java将字符串按照指定长度分割成字符串数组*/ public class StringUtils {public static void main(String[] args){String data "227d77a7a244c7b2be3180f2d46be352f56ddf92866692f2cac797358097e5a3e90f6d20bb96bc516a4ab9c0…

喜爱拍拍宝宝照片的,一定要制作照片书方便保存

​制作照片书&#xff0c;让美好记忆长久保存。随着数码技术的普及&#xff0c;我们拥有了越来越多的照片&#xff0c;但如何妥善保存这些珍贵的回忆呢&#xff1f;一张张照片随意夹在相册里&#xff0c;时间一长&#xff0c;容易丢失或混乱。而照片书则不同&#xff0c;它把多…

ROS2对比ROS1的一些变化与优势(全新安装ROS2以及编译错误处理)《1》

1、概述 我们在前面介绍的ROS&#xff0c;都是ROS1的版本&#xff0c;近期对机器狗进行学习的时候&#xff0c;发现版本是ROS2了&#xff0c;也发现平时习惯的一些命令都有了变化&#xff0c;改变还是挺大的&#xff0c;不过熟悉之后还是很习惯ROS2的写法。 ROS2不是在ROS1的基…

python数据结构与算法-13_高级排序算法-分治法

分治法 (Divide and Conquer) 很多有用的算法结构上是递归的&#xff0c;为了解决一个特定问题&#xff0c;算法一次或者多次递归调用其自身以解决若干子问题。 这些算法典型地遵循分治法的思想&#xff1a;将原问题分解为几个规模较小但是类似于原问题的子问题&#xff0c;递…

#include <tf/tf.h>这个头文件有哪些主要的功能?

在 ROS&#xff08;Robot Operating System&#xff09;中&#xff0c;#include <tf/tf.h> 是一个非常重要的头文件&#xff0c;它属于 tf 转换库&#xff0c;主要用于处理和转换不同坐标系之间的位置和方向。以下是 tf/tf.h 头文件的一些主要功能&#xff1a; 坐标系转换…

SOEM主站开发篇(1):移植SOEM主站到Linux开发板

0 工具准备 1.SOEM-1.4.0源码(官网:http://openethercatsociety.github.io/) 2.EtherCAT从站(本文使用DE3E-556步进电机驱动器) 3.Linux开发板(本文为正点原子I.MX6U ALPHA开发板) 4.交叉编译工具(arm-linux-gnueabihf-gcc) 5.cmake(版本不得低于3.9,本文为3.9.2&a…

vue3+element Plus中使用日期格式化库day.js

element Plus中使用日期格式化库day.js,无需再单独引入day.js Element-plus (opens new window)组件库默认支持 dayjs 进行日期时间处理&#xff0c;所以可以直接导入使用&#xff0c;相关 Date Picker (opens new window)组件介绍。 day.js官网链接dayjs.fenxianglu.cn/ El…