[Android]仿京东手机端类别页

京东手机端的类别标签页, 是一个左侧滑动可选择类别, 右侧一个类别明细的列表联动页面. 当用户选择左侧选项, 可在右侧显示更多选项来选择. 实现方式也不少. 最常见的当然是左侧和右侧各一个Fragment, 左侧Fragment放置ListView, 右侧放显示类别明细的Fragment. 如果觉得页面包含的Fragment太多, 左侧直接给一个ListView就可以了.不影响效果.

效果图:

例子中值得注意的三点:

  • 左侧列表点击某个Item可以自动上下滑动,使所点击的item自动移至列表中间
  • 点击item后保留背景色不变
  • 右侧布局

针对上面三个点,这里采取如下的解决方法:

  • 计算可见列表的可见首项或末项position值,使用smoothScrollToPosition()方法实现滑动
  • 自定义列表selector按下和松开的背景色,在adapter去更新并控制item的背景色
  • 右侧布局,采用Fragment是最好的. 里面使用ScrollView装载所有数据,可以动态的addView(),removeView(), 网格布局使用GridView. 由于Fragment, 所以更新数据和更新View都非常方便, 所以例子中直接用静态页面模拟数据了.

重在通过简单的例子解释这种实现思路, 当然实现不是唯一的.

然后,我们先来模拟右侧的Fragment数据,一看就懂的代码:


public class JDFragment extends Fragment{String TAG = "JDFragment";private View rootView = null;private LinearLayout llayout_main = null;private TextView tv = null;private LinearLayout.LayoutParams lp_gd = null;private LinearLayout.LayoutParams lp_tv = null;private ArrayList<Category> itemList = null;private GDAdapter adapter = null;@Overridepublic void onAttach(Activity activity){Log.e(TAG, "onAttach...");super.onAttach(activity);}@Overridepublic void onCreate(Bundle savedInstanceState){Log.e(TAG, "onCreate...");super.onCreate(savedInstanceState);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState){Log.e(TAG, "onCreateView...");rootView = inflater.inflate(R.layout.jd_frg_main, null);llayout_main = (LinearLayout) rootView.findViewById(R.id.llayout_jd_frg_main);tv = (TextView) rootView.findViewById(R.id.tv_jd_frg_main);updateTitle();//模拟数据for(int i=0; i<2; i++){setData();          }return rootView;}protected void updateTitle(){if(getArguments() != null){updateTitle(getArguments().getString("name"));}}protected void updateTitle(String title){if(tv != null){tv.setText(title);}}private void setData(){if(itemList == null){itemList = new ArrayList<Category>();for(int i=1; i<11; i++){itemList.add(new Category("选项 " + i, ""+i));}}//高度60dp+行距8dp = 68dpint heightUnit = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 68, getResources().getDisplayMetrics());int height;//计算Gridview总高度if(itemList.size() % 3 == 0){height = (itemList.size()/3 + 2)*heightUnit;}else{height = (itemList.size()/3 + 1)*heightUnit;}if(lp_gd == null)lp_gd = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, height);if(lp_tv == null)lp_tv = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, getResources().getDisplayMetrics()));TextView tv_title = new TextView(getActivity());tv_title.setLayoutParams(lp_tv);tv_title.setText("组一");llayout_main.addView(tv_title);GridView gridView = new GridView(getActivity());gridView.setNumColumns(3);gridView.setVerticalSpacing(8);gridView.setLayoutParams(lp_gd);adapter = new GDAdapter(getActivity(), itemList,R.drawable.cate);gridView.setAdapter(adapter);llayout_main.addView(gridView);}@Overridepublic void onActivityCreated(Bundle savedInstanceState){Log.e(TAG, "onActivityCreated...");super.onActivityCreated(savedInstanceState);}@Overridepublic void onStart(){Log.e(TAG, "onStart...");super.onStart();}@Overridepublic void onResume(){Log.e(TAG, "onResume...");super.onResume();}@Overridepublic void onPause(){Log.e(TAG, "onPause...");super.onPause();}@Overridepublic void onStop(){Log.e(TAG, "onStop...");super.onStop();}@Overridepublic void onDestroyView(){Log.e(TAG, "onDestroyView...");super.onDestroyView();}@Overridepublic void onDestroy(){Log.e(TAG, "onDestroy...");super.onDestroy();}@Overridepublic void onDetach(){Log.e(TAG, "onDetach...");super.onDetach();}static class GDAdapter extends BaseAdapter{Context context;List<Category> results;int imageId;ViewHolder holder = null;public GDAdapter(Context context, List<Category> results,int imageId) {this.context = context;this.results = results;this.imageId = imageId;}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn results.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn results.get(position);}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {Category c = (Category)getItem(position);if(convertView == null){holder = new ViewHolder();convertView = LayoutInflater.from(context).inflate(R.layout.jd_item, null);holder.tv = (TextView) convertView.findViewById(R.id.tv_jd_item);holder.imv = (ImageView) convertView.findViewById(R.id.imv_jd_item);}else{holder = (ViewHolder) convertView.getTag();}convertView.setTag(holder);holder.tv.setText(c.getName());holder.imv.setImageResource(imageId);return convertView;}class ViewHolder{TextView tv;ImageView imv;}}}

JDFragment的布局文件, jd_frg_main.xml:

<?xml version="1.0" encoding="utf-8" ?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#FFFFFF"><TextView android:id="@+id/tv_jd_frg_main"android:layout_width="match_parent"android:layout_height="25dp"android:text="Fragment"android:textSize="16sp"android:background="#EEEEEE"/><ScrollView android:id="@+id/scrlayout_jd_frg_main"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@+id/tv_jd_frg_main"android:overScrollMode="never"><LinearLayout android:id="@+id/llayout_jd_frg_main"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"/></ScrollView></RelativeLayout>

将所有数据放在ScrollView的线性布局中,使用Fragment作为容器, 可以根据需要ADD, Remove和Update数据和View. 到这里右侧页面的简单模拟实现就结束了,都是一目了然的代码.

然后就是实现左侧列表了,先是列表中简单的自定义Adapter, MyAdapter:

public class MyAdapter extends BaseAdapter
{private Context context;private List<Category> results;private int imageId;private ViewHolder holder = null;private int selectedId;public MyAdapter(Context context, List<Category> results,int imageId) {this.context = context;this.results = results;this.imageId = imageId;}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn results.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn results.get(position);}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}public void setSelected(int position){this.selectedId = position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {Category c = (Category)getItem(position);if(convertView == null){holder = new ViewHolder();convertView = LayoutInflater.from(context).inflate(R.layout.jd_item, null);holder.tv = (TextView) convertView.findViewById(R.id.tv_jd_item);holder.imv = (ImageView) convertView.findViewById(R.id.imv_jd_item);}else{holder = (ViewHolder) convertView.getTag();}if(position == selectedId){convertView.setBackgroundResource(R.drawable.sele_true);}else{convertView.setBackgroundResource(R.drawable.sele_false);}holder.tv.setText(c.getName());holder.imv.setImageResource(imageId);convertView.setTag(holder);return convertView;}class ViewHolder{TextView tv;ImageView imv;}
}

然后是主Activity了, 在里面对可见ListView的item位置进行计算, 并进行滑动处理. 当用户点击偏上的item, 列表就往下滑动, 加载顶部更多的item; 当用户点击偏下的item, 列表就往上滑动, 加载底部更多的item.

同时我们自定义按下和松开时的背景文件放在drawable, 随便一个shape就可以了. 然后点击某个item的position时, 在adapter中判断是否目标item, 是就设置按下背景色 - 白色, 否则就是正常的背景色 - 灰色.

/*** 仿京东类别页* @author AlexTam*/
public class JDActivity extends FragmentActivity{private ListView lv_main = null;private EditText et_search = null;private ArrayList<Category> itemList = new ArrayList<Category>(); private MyAdapter adapter = null;//可见列表项的数量private int visibleCount = 0;//上次点击的位置private int lastPosition = 0;private int ce = 0;//实际列表是否超出屏幕private boolean isOut = true;private JDFragment fragment = null;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.jd_main);init();}private void init(){lv_main = (ListView) findViewById(R.id.lv_main);et_search = (EditText) findViewById(R.id.et_search);for(int i=1; i<21; i++){itemList.add(new Category("选项 " + i, ""+i));}adapter = new MyAdapter(this, itemList,R.drawable.ic_launcher);lv_main.setAdapter(adapter);lv_main.setOnItemClickListener(new MyOnItemOnClick());lv_main.setSelector(R.color.pink);//模拟右侧标签页fragment = new JDFragment();Bundle bundle = new Bundle();bundle.putString("name", "c1");fragment.setArguments(bundle);FragmentManager fm = getSupportFragmentManager();FragmentTransaction ft = fm.beginTransaction();ft.replace(R.id.flayout_main, fragment, "c0").commit();adapter.setSelected(0);adapter.notifyDataSetChanged();}private class MyOnItemOnClick implements OnItemClickListener{@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {//计算滑动if(visibleCount == 0){visibleCount = lv_main.getChildCount();if(visibleCount == itemList.size())isOut = false;else{ce = visibleCount/2;}}if(position <= (parent.getFirstVisiblePosition() + ce)){   //上移lv_main.smoothScrollToPosition(position - ce);}else{   //下移if((parent.getLastVisiblePosition() + ce + 1) <= parent.getCount()){lv_main.smoothScrollToPosition(position + ce);}else{lv_main.smoothScrollToPosition(parent.getCount()-1);}}lastPosition = position;adapter.setSelected(position);adapter.notifyDataSetChanged();//更新右侧标签页的标题fragment.updateTitle("c" + (position+1));}}/*** 选项对象*/static class Category{private String name;private String id;Category(String name,String id){this.name = name;this.id = id;}public String getName(){return this.name;}}}

OK, 到此效果就出来了. 好简单吧!

[Android]仿京东手机端类别页相关推荐

  1. 仿京东手机端地址选择四级地址选择

    地址选择器是很多商城开发中必不可少的组件,有三级联动.四级联动等各种地址选择器.所有的地址选择的核心原理都是相同的,下面是仿京东地址选择的效果图: 使用方法: install npm install ...

  2. 仿天猫-手机端购物页

    ch01.html <!DOCTYPE html><html lang="en"><head><meta charset="UT ...

  3. Android仿京东、天猫商品详情页

    前言 前面在介绍控件TabLayout控件和CoordinatorLayout使用的时候说了下实现京东.天猫详情页面的效果,今天要说的是优化版,是我们线上实现的效果,首先看一下效果: 项目结构分析 首 ...

  4. python-selenium自动爬取京东手机端全部类别数据----“从祖爬到孙”

    一.序言 大家好,我是小龙.今天我们不谈Java相关技术,想和大家分享一波我大学比赛时做项目使用的一个爬虫. 事情是这样的: 比赛项目有一个关于电商的模块,奈何没有数据,然后打算爬取京东,淘宝pc端数 ...

  5. android自定义视频列表,Android仿京东天猫列表页播视频看这一篇就足够了

    阅读本文解决什么问题? 解决android 滑动列表页自动播视频中的一些技术难点.助力更好的实现类似需求.不涉及到播放器的具体编解码技术,因为各家用的播放器可能都不一样(其实是我不会~) 何时播视频最 ...

  6. 仿京东天猫商品详情页

    1.参考借鉴 Android仿京东商品详情页上拉查看图文详情 [模仿淘宝.京东.蘑菇街商品详情页,可嵌套ListView.WebView.ViewPager.FragmentTabhost等](htt ...

  7. Android 仿微信小程序开屏页加载loading

    Android 仿微信小程序开屏页加载loading 废话不多说,先上效果图~ 首先就是底层有一个灰色的圆,然后按照圆形的轨迹进行绘制. 啊~说那么多也没用,还是直接上代码吧,哈哈哈哈 绘制底部圆形及 ...

  8. Android仿京东收货地址

    Android仿京东三级联动收货地址 1.在本地新建assets目录,存放三级联动json数据,取本地json数据作为数据源 String data = com.miles.zcstc.fingerd ...

  9. php仿携程网站,仿携程网手机端

    [实例简介] 仿携程网手机端页面,有需要的朋友可以下载使用,谢谢 [实例截图] [核心代码] 75173e72-3359-4642-a0a0-72ba9fa3834f ├── __MACOSX │   ...

最新文章

  1. 【C++】C++11 STL算法(一):非修改序列操作(Non-modifying sequence operations)
  2. 印象笔记html预览,7 个方法,把印象笔记打造成轻量级笔记工具
  3. 《Python游戏编程快速上手》第四章-讲笑话
  4. Android之在ubuntu上过滤多条关键字日志
  5. android 回归测试,android测试:monkey使用方法
  6. php7扩展sphinx,php7进行安装sphinx简单记录
  7. MediaPipe: Google Research 开源的跨平台多媒体机器学习模型应用框架
  8. 食物在人体内消化主要经过哪些步骤
  9. 代替紧急通知_人员紧急替代程序与替代方案的通知
  10. (四)pscc学习笔记
  11. POJ 1182 食物链(带权并查集)
  12. 微信小程序开发学习资料
  13. 南开100题计算机三级数据库,全国计算机三级数据库技术南开100题.doc
  14. 飞鱼星路由器常见问题解答
  15. 电脑硬盘图标换成自己喜欢的图标
  16. 【GAN】生成式对抗网络论文笔记及TF2代码实现
  17. c语言 srand was not,c语言srand生成随机数的问题
  18. 华为笔记本键盘说明图_华为matebook x使用说明书
  19. JAVA的简单数据类型和复合数据类型
  20. Linux内核分析2:一个简单的时间片轮转多道程序内核代码分析

热门文章

  1. 基于STM32单片机的步数测量系统(免费开源)
  2. 推荐印度电影《起跑线》,让家长加入观影一点不为过
  3. UIImageView裁剪成圆形的方法
  4. ps打开图片的三种方式 同步部分基本操作方式
  5. 冯诺曼伊体系 计算机五大逻辑,科学网—再谈冯·诺伊曼结构 - 姜咏江的博文
  6. 记录ant design vue a-select Form编辑时回显数据库数据为value而不是label的问题
  7. win10 redis注册成服务自启动
  8. 春风十里不如Node中的一股清流
  9. 大型圆弧怎么处理_这种大圆弧一次成型,回弹怎么计算?低公差
  10. php groovy,Groovy