RecyclerView仿饿了吗点菜页面

先看一下效果图:

效果图

左边就是一个普通的recyclerView,右边则需要一个有标题的recyclerView。

sticky-headers-recyclerview

项目地址:https://github.com/timehop/sticky-headers-recyclerview

用它在写adapter的时候,记得写两个viewholder,一个content,一个header的。

其中根据getHeaderId(int position)来确定标题,返回值相同的属于同一个标题。

添加标题

// Add the sticky headers decoration,给球队添加标题
        final StickyRecyclerHeadersDecoration headersDecor = new StickyRecyclerHeadersDecoration(teamsAndHeaderAdapter);
        recyclerviewTeams.addItemDecoration(headersDecor);

只多了这一步操作,就给recyclerView相同分类的item加上标题了。

adapter

/**
 * Created by chenlijin on 2016/3/18.
 */
public class TeamsAndHeaderAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements StickyRecyclerHeadersAdapter<RecyclerView.ViewHolder> {
    private List<Category> categoryList;
    private List<Team> teamList = new ArrayList<>();
    private Context mContext;

    public TeamsAndHeaderAdapter(Context context,List<Category> categoryList) {
        mContext = context;
        setCategoryList(categoryList);
    }

    public void setCategoryList(List<Category> categoryList) {
        this.categoryList = categoryList;
        for(int i = 0;i<categoryList.size();i++){
            if(teamList!=null){
                teamList.addAll(categoryList.get(i).getTeamList());
            }
        }
        notifyDataSetChanged();
    }

    public List<Category> getCategoryList() {
        return categoryList;
    }

    @Override
    public int getItemCount() {
        return teamList.size();
    }

    /**
     * 返回值相同会被默认为同一项
     * @param position
     * @return
     */
    @Override
    public long getHeaderId(int position) {
       return getSortType(position);
    }

    //获取当前球队的类型
    public int getSortType(int position) {
        int sort = -1;
        int sum = 0;
        for (int i=0;i<categoryList.size();i++){
            if(position>=sum){
                sort++;
            }else {
                return sort;
            }
            sum += categoryList.get(i).getTeamList().size();
        }
        return sort;
    }

    /**
     * =========================================================================
     * header的ViewHolder
     * ========================================================================
     */
    @Override
    public ContentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_team, parent, false);
        return new ContentViewHolder(view);
    }

    @Override
    public void onBindHeaderViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
        TextView textView = (TextView) viewHolder.itemView;
        textView.setText(categoryList.get(getSortType(position)).getSortName());
        textView.setBackgroundColor(getRandomColor());
    }


    private class HeaderViewHolder extends RecyclerView.ViewHolder {
        public HeaderViewHolder(View itemView) {
            super(itemView);
        }
    }

    private int getRandomColor() {
        SecureRandom rgen = new SecureRandom();
        return Color.HSVToColor(150, new float[]{
                rgen.nextInt(359), 1, 1
        });
    }

    /**
     * =========================================================================
     * 以下为contentViewHolder
     * =========================================================================
     */
    @Override
    public ContentViewHolder onCreateHeaderViewHolder(ViewGroup viewGroup) {
        View view = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.header_team_list, viewGroup, false);
        return new ContentViewHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ContentViewHolder viewHolder = (ContentViewHolder) holder;
        viewHolder.textView.setText(teamList.get(position).getName());
        //glide谷歌推荐的图片加载库
        Glide.with(mContext)
                .load(teamList.get(position).getImagePath())
                .placeholder(R.drawable.icon_logo_image_default)
                .centerCrop()
                .into(viewHolder.imageViewTeam);
    }

    private class ContentViewHolder extends RecyclerView.ViewHolder {
        TextView textView;
        ImageView imageViewTeam;
        public ContentViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.textview_teamname);
            imageViewTeam = (ImageView) itemView.findViewById(R.id.imageview_team);
        }
    }
}

两个recyclerView的相互监听

右边滚动,左边切换

监听滚动OnScrollChangeListener,由layoutmanager获取到第一个完全显示的item的position。再进行判断:

recyclerviewTeams.setOnScrollChangeListener(new View.OnScrollChangeListener() {
            @Override
            public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
                //第一个完全显示的item和最后一个item。
                int firstVisibleItem = mTeamsLayoutManager.findFirstCompletelyVisibleItemPosition();
                int lastVisibleItem = mTeamsLayoutManager.findLastVisibleItemPosition();
                //此判断,避免左侧点击最后一个item无响应
                if(lastVisibleItem != mTeamsLayoutManager.getItemCount()-1){
                    int sort = teamsAndHeaderAdapter.getSortType(firstVisibleItem);
                    changeSelected(sort);
                }else {
                    changeSelected(categoryAdapter.getItemCount()-1);
                }
                if(needMove){
                    needMove = false;
                    //获取要置顶的项在当前屏幕的位置,mIndex是记录的要置顶项在RecyclerView中的位置
                    int n = movePosition - mTeamsLayoutManager.findFirstVisibleItemPosition();
                    if ( 0 <= n && n < recyclerviewTeams.getChildCount()){
                        //获取要置顶的项顶部离RecyclerView顶部的距离
                        int top = recyclerviewTeams.getChildAt(n).getTop()-dip2px(MainActivity.this,28);
                        //最后的移动
                        recyclerviewTeams.scrollBy(0, top);
                    }
                }
            }
        });

左边点击,右边滚动到相应位置

recyclerView有三种滚动的方法:scrollTo,scrollBy,scrollToPosition。

scrollTo这个方法无响应,至于这个方法是做什么的?还请赐教。。。

scrollToPosition这个方法比较神奇。它分三种情况:

1,position在界面内,无反应

2,position在界面下方,则滚动此position到底部。

3,position在界面上方,则滚动此position到顶部。

scrollBy这个是最靠谱的一个方法了,从当前位置相对进行位移,可正可负。

按理说scrollBy是最简单的,但是recyclerviewTeams.getChildAt(n - firstItem),item如果不在屏幕内就会为空,所以就需要先把item移到屏幕内。。。这样如果item在屏幕下方,就需要先scrollToPosition,再scrollBy。所以要监听滚动,item在屏幕下方时,第一次滚动完成后,进行第二次滚动。

private void moveToPosition(int n) {
    //先从RecyclerView的LayoutManager中获取第一项和最后一项的Position
    int firstItem = mTeamsLayoutManager.findFirstVisibleItemPosition();
    int lastItem = mTeamsLayoutManager.findLastVisibleItemPosition();
    //然后区分情况
    if (n <= firstItem ){
        //当要置顶的项在当前显示的第一个项的前面时
        recyclerviewTeams.scrollToPosition(n);
    }else if ( n <= lastItem ){
        //当要置顶的项已经在屏幕上显示时
        int top = recyclerviewTeams.getChildAt(n - firstItem).getTop();
        recyclerviewTeams.scrollBy(0, top-dip2px(this,28));
    }else{
        //当要置顶的项在当前显示的最后一项的后面时
        recyclerviewTeams.scrollToPosition(n);
        movePosition = n;
        needMove = true;
    }
}

item在屏幕下方时,在监听里添加

if(needMove){
    needMove = false;
    //获取要置顶的项在当前屏幕的位置,mIndex是记录的要置顶项在RecyclerView中的位置
    int n = movePosition - mTeamsLayoutManager.findFirstVisibleItemPosition();
    if ( 0 <= n && n < recyclerviewTeams.getChildCount()){
        //获取要置顶的项顶部离RecyclerView顶部的距离
        int top = recyclerviewTeams.getChildAt(n).getTop()-dip2px(MainActivity.this,28);
        //最后的移动
        recyclerviewTeams.scrollBy(0, top);
    }
}

到此,左右两端的相互关联就完成了。

原文地址:https://heinika.github.io/2016/03/19/%E7%94%A8RecyclerView%E5%AE%9E%E7%8E%B0%E9%A5%BF%E4%BA%86%E5%90%97%E7%82%B9%E8%8F%9C%E9%A1%B5/

github下载:https://github.com/heinika/ElmShopByRecyclerView

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 简介: 提供一个让有限的窗口变成一个大数据集的灵活视图。 术语表: Adapter:RecyclerView的子类...
    酷泡泡阅读 5,053评论 0 16
  • 下午汇报最近的工作,发现一个问题,在没弄好目标的情况下最好别下手做事儿。大领导的意思和小领导的意思不一定是一个意思...
    面包和牛奶都会有的阅读 104评论 0 0
  • 他在简信里发私信,说他想自杀,不想活了,觉得活在这个世界上没脸见人。 看到他私信的简友极度紧张,纷纷发私信安慰他,...
    河洛梦话阅读 1,307评论 9 11
  • 看雨打芭蕉 乱红满天 听风声携水 一落流年 私以为是柳儿青青眉上捎 舞了眉梢 却不想你执伞回眸 成了思念 戏说要年...
    云汉藏阅读 215评论 3 8