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…

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…

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

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

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

​制作照片书&#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;递…

sap系统连接其它系统

本文来自博客园&#xff0c;作者&#xff1a;Lovemywx2&#xff0c;转载请注明原文链接&#xff1a;https://www.cnblogs.com/1187163927ch/p/8669859.html JAVA连接ORACLE数据库 1&#xff0c;首先需要在Oracle安装完成之后新建一个用户 --新建用户 create user chenh iden…

呼叫中心自建好还是云外呼好用?

传统的呼叫中心在科技的发展下已经被不适用了&#xff0c;都开始使用起智能化的呼叫中心&#xff0c;一个是自建式呼叫中心&#xff0c;一个是云外呼系统。那自建式呼叫中心与云外呼系统的区别有哪些呢&#xff1f; 1、企业自建呼叫中心 劣势 系统维护更新难&#xff1a;自建…

Proxifier联动BurpSuite抓取小程序

直接上软件包 Proxifier安装包https://pan.quark.cn/s/7fb9ad6deb7cProxifier配置文件https://pan.quark.cn/s/049c5f21c97e 无话可说直接操作 1、安装Proxifier步骤可以省略..... 2、将下面文件导入到Proxifier中 3、左上角文件-导入配置文件&#xff08;因为我已经导入过…

【CodeTop】TOP 100 刷题 11-20

文章目录 11. 二叉树的层序遍历题目描述代码与解题思路 12. 搜索旋转排序数组题目描述代码与解题思路 13. 买卖股票的最佳时机题目描述代码和解题思路 14. 岛屿数量题目描述代码与解题思路 15. 环形链表题目描述代码与解题思路 16. 有效的括号题目描述代码与解题思路 17. 合并两…

使用 millis() 函数作为延迟的替代方法(电位器控制延迟时间)

接线图&#xff1a; 代码&#xff1a; unsigned long currentMillis 0; unsigned long previousMillis_LED1 0; unsigned long LED1_delay0; unsigned long previousMillis_LED2 0; unsigned long LED2_delay0; #define LED1 3 #define LED2 9 #define P1 A2 …

python写文件

output_file open(E:/XD_transfer/代码/CNN_new/try.csv, w) output_file.write(Sample, \n) for j in range(5):output_file.write(str(j) \n)

2023亚太杯数学建模思路 - 案例:最短时间生产计划安排

文章目录 0 赛题思路1 模型描述2 实例2.1 问题描述2.2 数学模型2.2.1 模型流程2.2.2 符号约定2.2.3 求解模型 2.3 相关代码2.4 模型求解结果 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 最短时…