Android快速实现美团、饿了么首页分页导航菜单功能

移动开发 Android
前段时间公司移动端App新增一个模块,类似美团团购的功能,首页有个类似美团的分页菜单的功能,用过美团和饿了么的app的童鞋应该清楚这一功能。首页菜单可以分页切换,类似我们的banner广告切换效果,只不过只能手动切换。

前段时间公司移动端App新增一个模块,类似美团团购的功能,首页有个类似美团的分页菜单的功能,用过美团和饿了么的app的童鞋应该清楚这一功能。首页菜单可以分页切换,类似我们的banner广告切换效果,只不过只能手动切换。所以整个分页效果,我们可以采用Viewpager实现,里面的菜单项我们则可以采用RecyclerView实现,动态改变里面的菜单项,以后产品汪要改需求也是一两行代码能搞定的事,是不是很机智。所以今天我们这个首页分页菜单效果,可以采用ViewPager+RecyclerView实现,思路既然已经有了,那我们就开整吧。首先我们先看下实现的效果图。

Android快速实现美团、饿了么首页分页导航菜单功能

Android快速实现美团、饿了么首页分页导航菜单功能

Android快速实现美团、饿了么首页分页导航菜单功能

首页布局文件,分页指示器是单独封装的一个控件,后面会把代码贴出来

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.               xmlns:app="http://schemas.android.com/apk/res-auto" 
  4.               android:id="@+id/home_entrance" 
  5.               android:layout_width="match_parent" 
  6.               android:layout_height="wrap_content" 
  7.               android:orientation="vertical"
  8.  
  9.     <android.support.v4.view.ViewPager 
  10.         android:id="@+id/main_home_entrance_vp" 
  11.         android:layout_width="match_parent" 
  12.         android:layout_height="wrap_content"/> 
  13.  
  14.     <com.stx.xhb.meituancategorydemo.widget.IndicatorView 
  15.         android:id="@+id/main_home_entrance_indicator" 
  16.         android:layout_width="match_parent" 
  17.         android:layout_height="32dp" 
  18.         android:layout_marginLeft="16dp" 
  19.         android:layout_gravity="bottom" 
  20.         android:layout_marginRight="16dp" 
  21.         app:gravity="0" 
  22.         app:indicatorColor="#668b8989" 
  23.         app:indicatorColorSelected="#FF5722" 
  24.         app:indicatorWidth="6"/> 
  25.  
  26. </LinearLayout> 

ViewPager中的子控件RecyclerView

  1. item_home_entrance_vp.xml  
  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" 
  3.                                         android:layout_width="match_parent" 
  4.                                         android:layout_height="wrap_content"/> 

接下来就是RecyclerView的菜单项的布局文件 

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.              android:layout_width="match_parent" 
  4.              android:layout_height="match_parent"
  5.  
  6.     <LinearLayout 
  7.         android:layout_width="match_parent" 
  8.         android:layout_height="match_parent" 
  9.         android:gravity="center_horizontal" 
  10.         android:orientation="vertical" 
  11.         android:padding="6dp"
  12.  
  13.         <ImageView 
  14.             android:id="@+id/entrance_image" 
  15.             android:layout_width="wrap_content" 
  16.             android:layout_height="0dp" 
  17.             android:layout_margin="2dp" 
  18.             android:layout_weight="1" 
  19.             android:scaleType="fitCenter"/> 
  20.  
  21.         <TextView 
  22.             android:id="@+id/entrance_name" 
  23.             android:layout_width="wrap_content" 
  24.             android:layout_height="wrap_content" 
  25.             android:layout_margin="2dp" 
  26.             android:singleLine="true" 
  27.             android:textColor="#80000000" 
  28.             android:textSize="12dp"/> 
  29.     </LinearLayout> 
  30.  
  31.     <View 
  32.         android:layout_width="match_parent" 
  33.         android:layout_height="match_parent" 
  34.         android:background="@drawable/selector_trans_divider"/> 
  35.  
  36. </FrameLayout> 

布局都创建好了,接下来我们一起来看看里面的具体实现代码了。由于我们的菜单项有一个icon和名称name,为了方便管理,我们可以创建一个菜单项实体类ModelHomeEntrance.class

  1. /** 
  2.  * Author: Mr.xiao on 2017/5/23 
  3.  * 
  4.  * @mail:xhb_199409@163.com 
  5.  * @github:https://github.com/xiaohaibin 
  6.  * @describe:菜单项实体类 
  7.  */ 
  8. public class ModelHomeEntrance { 
  9.     private String name = ""
  10.     private int image; 
  11.  
  12.     public ModelHomeEntrance(String nameint image) { 
  13.         this.image = image; 
  14.         this.name = name
  15.     } 
  16.  
  17.  
  18.     public int getImage() { 
  19.         return image; 
  20.     } 
  21.  
  22.     public String getName() { 
  23.         return name
  24.     } 
  25.  

由于我们分页效果是以ViewPager实现的,所以我们要创建一个ViewPager的适配器,CagegoryViewPagerAdapter.Class

  1. package com.stx.xhb.meituancategorydemo.adapter; 
  2.  
  3. import android.support.v4.view.PagerAdapter; 
  4. import android.view.View
  5. import android.view.ViewGroup; 
  6.  
  7. import java.util.List; 
  8.  
  9. /** 
  10.  * Created by jxnk25 on 2016/9/21. 
  11.  * 
  12.  * @link https://xiaohaibin.github.io/ 
  13.  * @email: xhb_199409@163.com 
  14.  * @github: https://github.com/xiaohaibin 
  15.  * @description:  首页分类ViewPager适配器 
  16.  */ 
  17. public class CagegoryViewPagerAdapter extends PagerAdapter { 
  18.  
  19.     private List<View> mViewList; 
  20.     public CagegoryViewPagerAdapter(List<View> mViewList) { 
  21.         this.mViewList = mViewList; 
  22.     } 
  23.  
  24.     @Override 
  25.     public void destroyItem(ViewGroup container, int position, Object object) { 
  26.         container.removeView(mViewList.get(position)); 
  27.     } 
  28.  
  29.     @Override 
  30.     public Object instantiateItem(ViewGroup container, int position) { 
  31.         container.addView(mViewList.get(position)); 
  32.         return (mViewList.get(position)); 
  33.     } 
  34.  
  35.     @Override 
  36.     public int getCount() { 
  37.         if (mViewList == null
  38.             return 0; 
  39.         return mViewList.size(); 
  40.     } 
  41.  
  42.     @Override 
  43.     public boolean isViewFromObject(View view, Object object) { 
  44.         return view == object; 
  45.     } 

ViewPager的适配器有了,我们还得再创建一个RecyclerView的菜单项列表适配器,EntranceAdapter.Class 

  1. package com.stx.xhb.meituancategorydemo.adapter; 
  2.  
  3. import android.content.Context; 
  4. import android.support.v7.widget.RecyclerView; 
  5. import android.view.LayoutInflater; 
  6. import android.view.View
  7. import android.view.ViewGroup; 
  8. import android.widget.ImageView; 
  9. import android.widget.LinearLayout; 
  10. import android.widget.TextView; 
  11.  
  12. import com.stx.xhb.meituancategorydemo.R; 
  13. import com.stx.xhb.meituancategorydemo.model.ModelHomeEntrance; 
  14. import com.stx.xhb.meituancategorydemo.utils.ScreenUtil; 
  15.  
  16. import java.util.List; 
  17.  
  18. /** 
  19.  * Author: Mr.xiao on 2017/5/23 
  20.  * 
  21.  * @mail:xhb_199409@163.com 
  22.  * @github:https://github.com/xiaohaibin 
  23.  * @describe: 首页分页菜单项列表适配器 
  24.  */ 
  25. public class EntranceAdapter extends RecyclerView.Adapter<EntranceAdapter.EntranceViewHolder> { 
  26.  
  27.     private List<ModelHomeEntrance> mDatas; 
  28.  
  29.     /** 
  30.      * 页数下标,从0开始(通俗讲第几页) 
  31.      */ 
  32.     private int mIndex; 
  33.  
  34.     /** 
  35.      * 每页显示最大条目个数 
  36.      */ 
  37.     private int mPageSize; 
  38.  
  39.     private Context mContext; 
  40.  
  41.     private final LayoutInflater mLayoutInflater; 
  42.  
  43.     private List<ModelHomeEntrance> homeEntrances; 
  44.  
  45.     public EntranceAdapter(Context context, List<ModelHomeEntrance> datas, int indexint pageSize) { 
  46.         this.mContext = context; 
  47.         this.homeEntrances = datas; 
  48.         mPageSize = pageSize; 
  49.         mDatas = datas; 
  50.         mIndex = index
  51.         mLayoutInflater = LayoutInflater.from(context); 
  52.  
  53.     } 
  54.  
  55.     @Override 
  56.     public EntranceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
  57.         return new EntranceViewHolder(mLayoutInflater.inflate(R.layout.item_home_entrance, null)); 
  58.     } 
  59.  
  60.     @Override 
  61.     public void onBindViewHolder(EntranceViewHolder holder, final int position) { 
  62.         /** 
  63.          * 在给View绑定显示的数据时,计算正确的position = position + mIndex * mPageSize, 
  64.          */ 
  65.         final int pos = position + mIndex * mPageSize; 
  66.         holder.entranceNameTextView.setText(homeEntrances.get(pos).getName()); 
  67.         holder.entranceIconImageView.setImageResource(homeEntrances.get(pos).getImage()); 
  68.         holder.itemView.setOnClickListener(new View.OnClickListener() { 
  69.             @Override 
  70.             public void onClick(View v) { 
  71.                 ModelHomeEntrance entrance = homeEntrances.get(pos); 
  72.                 // TODO: 2017/5/24 点击事件处理 
  73.             } 
  74.         }); 
  75.     } 
  76.  
  77.     @Override 
  78.     public int getItemCount() { 
  79.         return mDatas.size() > (mIndex + 1) * mPageSize ? mPageSize : (mDatas.size() - mIndex * mPageSize); 
  80.     } 
  81.  
  82.     @Override 
  83.     public long getItemId(int position) { 
  84.         return position + mIndex * mPageSize; 
  85.     } 
  86.  
  87.     class EntranceViewHolder extends RecyclerView.ViewHolder { 
  88.  
  89.         private TextView entranceNameTextView; 
  90.         private ImageView entranceIconImageView; 
  91.  
  92.         public EntranceViewHolder(View itemView) { 
  93.             super(itemView); 
  94.             entranceIconImageView = (ImageView) itemView.findViewById(R.id.entrance_image); 
  95.             entranceNameTextView = (TextView) itemView.findViewById(R.id.entrance_name); 
  96.             LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (int) ((float) ScreenUtil.getScreenWidth() / 4.0f)); 
  97.             itemView.setLayoutParams(layoutParams); 
  98.         } 
  99.     } 

最后就是我们的MainActivity的代码实现了,我们整体的思路其实就是需要根据首页菜单项的数据源进行分页显示,首页确定单页菜单显示数量,总数除以单页显示数量取整就是显示页数,我们再根据页数来创建RecyclerView将其添加到ViewPager的适配器中,下面就让我们一起来看看具体是如何的。 

  1. package com.stx.xhb.meituancategorydemo; 
  2.  
  3. import android.os.Bundle; 
  4. import android.support.v4.view.ViewPager; 
  5. import android.support.v7.app.AppCompatActivity; 
  6. import android.support.v7.widget.GridLayoutManager; 
  7. import android.support.v7.widget.RecyclerView; 
  8. import android.view.LayoutInflater; 
  9. import android.view.View
  10. import android.widget.FrameLayout; 
  11. import android.widget.LinearLayout; 
  12.  
  13. import com.stx.xhb.meituancategorydemo.adapter.CagegoryViewPagerAdapter; 
  14. import com.stx.xhb.meituancategorydemo.adapter.EntranceAdapter; 
  15. import com.stx.xhb.meituancategorydemo.model.ModelHomeEntrance; 
  16. import com.stx.xhb.meituancategorydemo.utils.ScreenUtil; 
  17. import com.stx.xhb.meituancategorydemo.widget.IndicatorView; 
  18.  
  19. import java.util.ArrayList; 
  20. import java.util.List; 
  21.  
  22. public class MainActivity extends AppCompatActivity { 
  23.     public static final int HOME_ENTRANCE_PAGE_SIZE = 10;//首页菜单单页显示数量 
  24.     private ViewPager entranceViewPager; 
  25.     private LinearLayout homeEntranceLayout; 
  26.     private List<ModelHomeEntrance> homeEntrances; 
  27.     private IndicatorView entranceIndicatorView; 
  28.  
  29.     @Override 
  30.     protected void onCreate(Bundle savedInstanceState) { 
  31.         super.onCreate(savedInstanceState); 
  32.         setContentView(R.layout.activity_main); 
  33.         initData(); 
  34.         initView(); 
  35.         init(); 
  36.     } 
  37.  
  38.  
  39.     private void initView() { 
  40.         homeEntranceLayout = (LinearLayout) findViewById(R.id.home_entrance); 
  41.         entranceViewPager = (ViewPager) findViewById(R.id.main_home_entrance_vp); 
  42.         entranceIndicatorView = (IndicatorView) findViewById(R.id.main_home_entrance_indicator); 
  43.     } 
  44.  
  45.  
  46.     private void initData() { 
  47.         homeEntrances = new ArrayList<>(); 
  48.         homeEntrances.add(new ModelHomeEntrance("美食", R.mipmap.ic_category_0)); 
  49.         homeEntrances.add(new ModelHomeEntrance("电影", R.mipmap.ic_category_1)); 
  50.         homeEntrances.add(new ModelHomeEntrance("酒店住宿", R.mipmap.ic_category_2)); 
  51.         homeEntrances.add(new ModelHomeEntrance("生活服务", R.mipmap.ic_category_3)); 
  52.         homeEntrances.add(new ModelHomeEntrance("KTV", R.mipmap.ic_category_4)); 
  53.         homeEntrances.add(new ModelHomeEntrance("旅游", R.mipmap.ic_category_5)); 
  54.         homeEntrances.add(new ModelHomeEntrance("学习培训", R.mipmap.ic_category_6)); 
  55.         homeEntrances.add(new ModelHomeEntrance("汽车服务", R.mipmap.ic_category_7)); 
  56.         homeEntrances.add(new ModelHomeEntrance("摄影写真", R.mipmap.ic_category_8)); 
  57.         homeEntrances.add(new ModelHomeEntrance("休闲娱乐", R.mipmap.ic_category_10)); 
  58.         homeEntrances.add(new ModelHomeEntrance("丽人", R.mipmap.ic_category_11)); 
  59.         homeEntrances.add(new ModelHomeEntrance("运动健身", R.mipmap.ic_category_12)); 
  60.         homeEntrances.add(new ModelHomeEntrance("大保健", R.mipmap.ic_category_13)); 
  61.         homeEntrances.add(new ModelHomeEntrance("团购", R.mipmap.ic_category_14)); 
  62.         homeEntrances.add(new ModelHomeEntrance("景点", R.mipmap.ic_category_16)); 
  63.         homeEntrances.add(new ModelHomeEntrance("全部分类", R.mipmap.ic_category_15)); 
  64.     } 
  65.  
  66.     private void init() { 
  67.         LinearLayout.LayoutParams layoutParams12 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (int) ((float) ScreenUtil.getScreenWidth() / 2.0f)); 
  68.  
  69.         //首页菜单分页 
  70.         FrameLayout.LayoutParams entrancelayoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, (int) ((float) ScreenUtil.getScreenWidth() / 2.0f + 70)); 
  71.         homeEntranceLayout.setLayoutParams(entrancelayoutParams); 
  72.         entranceViewPager.setLayoutParams(layoutParams12); 
  73.         LayoutInflater inflater = LayoutInflater.from(this); 
  74.         //将RecyclerView放至ViewPager中: 
  75.         int pageSize = HOME_ENTRANCE_PAGE_SIZE; 
  76.         //一共的页数等于 总数/每页数量,并取整。 
  77.         int pageCount = (int) Math.ceil(homeEntrances.size() * 1.0 / pageSize); 
  78.         List<View> viewList = new ArrayList<View>(); 
  79.         for (int index = 0; index < pageCount; index++) { 
  80.             //每个页面都是inflate出一个新实例 
  81.             RecyclerView recyclerView = (RecyclerView) inflater.inflate(R.layout.item_home_entrance_vp, entranceViewPager, false); 
  82.             recyclerView.setLayoutParams(layoutParams12); 
  83.             recyclerView.setLayoutManager(new GridLayoutManager(MainActivity.this, 5)); 
  84.             EntranceAdapter entranceAdapter = new EntranceAdapter(MainActivity.this, homeEntrances, index, HOME_ENTRANCE_PAGE_SIZE); 
  85.             recyclerView.setAdapter(entranceAdapter); 
  86.             viewList.add(recyclerView); 
  87.         } 
  88.         CagegoryViewPagerAdapter adapter = new CagegoryViewPagerAdapter(viewList); 
  89.         entranceViewPager.setAdapter(adapter); 
  90.         entranceIndicatorView.setIndicatorCount(entranceViewPager.getAdapter().getCount()); 
  91.         entranceIndicatorView.setCurrentIndicator(entranceViewPager.getCurrentItem()); 
  92.         entranceViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { 
  93.             @Override 
  94.             public void onPageSelected(int position) { 
  95.                 entranceIndicatorView.setCurrentIndicator(position); 
  96.             } 
  97.         }); 
  98.     } 

以上就是实现首页分页菜单效果的主要实现代码,这种分页菜单效果在我们的应用中也比较常见,说不定啥时候公司产品汪就拿手机过来让你照着美团之类实现这种效果。

 

责任编辑:未丽燕 来源: 安卓巴士
相关推荐

2015-11-13 11:27:54

2015-03-31 18:19:37

饿了么动画效果

2023-07-13 09:16:47

循环队列指针front​

2018-01-03 09:57:19

异地双活数据库

2017-12-05 15:03:45

人工智能饿了么大数据

2017-07-21 14:48:47

AI物流O2O

2021-10-24 06:49:08

线程池中间件开源

2022-02-14 16:08:15

开源项目线程池动态可监控

2009-10-28 09:19:13

Eclipse 3.5项目导航

2017-10-27 15:44:24

饿了么张龙前端基础设施

2018-11-29 09:36:56

大数据调度系统

2022-01-11 15:35:22

数字人民币子钱包区块链

2010-09-13 14:17:42

CSS纵向导航菜单

2018-08-17 09:14:43

饿了么容器演进

2017-06-12 09:13:02

饿了么技术运营运维

2016-04-01 18:25:21

中国科技网

2016-08-26 22:36:18

大数据

2020-07-06 08:40:36

阿里饿了么思考

2015-11-16 16:00:21

2018-03-28 09:53:50

Android架构演进
点赞
收藏

51CTO技术栈公众号