RecyclerView仿餓了嗎點菜頁面

先看一下效果圖:

效果圖

左邊就是一個普通的recyclerView,右邊則需要一個有標(biāo)題的recyclerView。

sticky-headers-recyclerview

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

用它在寫adapter的時候,記得寫兩個viewholder,一個content,一個header的。

其中根據(jù)getHeaderId(int position)來確定標(biāo)題,返回值相同的屬于同一個標(biāo)題。

添加標(biāo)題

// Add the sticky headers decoration,給球隊添加標(biāo)題
        final StickyRecyclerHeadersDecoration headersDecor = new StickyRecyclerHeadersDecoration(teamsAndHeaderAdapter);
        recyclerviewTeams.addItemDecoration(headersDecor);

只多了這一步操作,就給recyclerView相同分類的item加上標(biāo)題了。

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);
    }

    //獲取當(dāng)前球隊的類型
    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的相互監(jiān)聽

右邊滾動,左邊切換

監(jiān)聽滾動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();
                //此判斷,避免左側(cè)點擊最后一個item無響應(yīng)
                if(lastVisibleItem != mTeamsLayoutManager.getItemCount()-1){
                    int sort = teamsAndHeaderAdapter.getSortType(firstVisibleItem);
                    changeSelected(sort);
                }else {
                    changeSelected(categoryAdapter.getItemCount()-1);
                }
                if(needMove){
                    needMove = false;
                    //獲取要置頂?shù)捻椩诋?dāng)前屏幕的位置,mIndex是記錄的要置頂項在RecyclerView中的位置
                    int n = movePosition - mTeamsLayoutManager.findFirstVisibleItemPosition();
                    if ( 0 <= n && n < recyclerviewTeams.getChildCount()){
                        //獲取要置頂?shù)捻楉敳侩xRecyclerView頂部的距離
                        int top = recyclerviewTeams.getChildAt(n).getTop()-dip2px(MainActivity.this,28);
                        //最后的移動
                        recyclerviewTeams.scrollBy(0, top);
                    }
                }
            }
        });

左邊點擊,右邊滾動到相應(yīng)位置

recyclerView有三種滾動的方法:scrollTo,scrollBy,scrollToPosition。

scrollTo這個方法無響應(yīng),至于這個方法是做什么的?還請賜教。。。

scrollToPosition這個方法比較神奇。它分三種情況:

1,position在界面內(nèi),無反應(yīng)

2,position在界面下方,則滾動此position到底部。

3,position在界面上方,則滾動此position到頂部。

scrollBy這個是最靠譜的一個方法了,從當(dāng)前位置相對進行位移,可正可負。

按理說scrollBy是最簡單的,但是recyclerviewTeams.getChildAt(n - firstItem),item如果不在屏幕內(nèi)就會為空,所以就需要先把item移到屏幕內(nèi)。。。這樣如果item在屏幕下方,就需要先scrollToPosition,再scrollBy。所以要監(jiān)聽滾動,item在屏幕下方時,第一次滾動完成后,進行第二次滾動。

private void moveToPosition(int n) {
    //先從RecyclerView的LayoutManager中獲取第一項和最后一項的Position
    int firstItem = mTeamsLayoutManager.findFirstVisibleItemPosition();
    int lastItem = mTeamsLayoutManager.findLastVisibleItemPosition();
    //然后區(qū)分情況
    if (n <= firstItem ){
        //當(dāng)要置頂?shù)捻椩诋?dāng)前顯示的第一個項的前面時
        recyclerviewTeams.scrollToPosition(n);
    }else if ( n <= lastItem ){
        //當(dāng)要置頂?shù)捻椧呀?jīng)在屏幕上顯示時
        int top = recyclerviewTeams.getChildAt(n - firstItem).getTop();
        recyclerviewTeams.scrollBy(0, top-dip2px(this,28));
    }else{
        //當(dāng)要置頂?shù)捻椩诋?dāng)前顯示的最后一項的后面時
        recyclerviewTeams.scrollToPosition(n);
        movePosition = n;
        needMove = true;
    }
}

item在屏幕下方時,在監(jiān)聽里添加

if(needMove){
    needMove = false;
    //獲取要置頂?shù)捻椩诋?dāng)前屏幕的位置,mIndex是記錄的要置頂項在RecyclerView中的位置
    int n = movePosition - mTeamsLayoutManager.findFirstVisibleItemPosition();
    if ( 0 <= n && n < recyclerviewTeams.getChildCount()){
        //獲取要置頂?shù)捻楉敳侩xRecyclerView頂部的距離
        int top = recyclerviewTeams.getChildAt(n).getTop()-dip2px(MainActivity.this,28);
        //最后的移動
        recyclerviewTeams.scrollBy(0, top);
    }
}

到此,左右兩端的相互關(guān)聯(lián)就完成了。

原文地址: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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,319評論 25 708
  • 簡介: 提供一個讓有限的窗口變成一個大數(shù)據(jù)集的靈活視圖。 術(shù)語表: Adapter:RecyclerView的子類...
    酷泡泡閱讀 5,386評論 0 16
  • 下午匯報最近的工作,發(fā)現(xiàn)一個問題,在沒弄好目標(biāo)的情況下最好別下手做事兒。大領(lǐng)導(dǎo)的意思和小領(lǐng)導(dǎo)的意思不一定是一個意思...
    面包和牛奶都會有的閱讀 146評論 0 0
  • 他在簡信里發(fā)私信,說他想自殺,不想活了,覺得活在這個世界上沒臉見人。 看到他私信的簡友極度緊張,紛紛發(fā)私信安慰他,...
    河洛夢話閱讀 1,483評論 9 11
  • 看雨打芭蕉 亂紅滿天 聽風(fēng)聲攜水 一落流年 私以為是柳兒青青眉上捎 舞了眉梢 卻不想你執(zhí)傘回眸 成了思念 戲說要年...
    云漢藏閱讀 256評論 3 8

友情鏈接更多精彩內(nèi)容