1. 程式人生 > >RecyclerView使用ItemDecoration實現吸頂效果

RecyclerView使用ItemDecoration實現吸頂效果

寫此部落格目的僅僅用於幫助自己做筆記
吸頂效果在很多APP都可以看見,現在可以藉助RecyclerView的ItemDecoration 來簡單實現一個吸頂效果直接上效果圖:
效果圖

  1. 首先實現一個Model實體,該Model需要包含區分不同組的欄位,例如下面這個實體用來區分的便是mTitle欄位,當然這個欄位是隨便取什麼的,只要定好就可以。
public class Model {
    private String mTitle;
    private String mContent;
    private int mRsId;

    public Model(String title, String content, int
rsId) { mTitle = title; mContent = content; mRsId = rsId; } public String getTitle() { return mTitle; } public void setTitle(String title) { mTitle = title; } public String getContent() { return mContent; } public void
setContent(String content) { mContent = content; } public int getRsId() { return mRsId; } public void setRsId(int rsId) { mRsId = rsId; } }
  1. 建立一個RecyclerView並且實現實現介面卡,先實現如下效果:
    1

  2. 介面卡程式碼如下:

public class Adapter extends RecyclerView.Adapter<Adapter
.ViewHolder> {
private List<Model> mModelList; private LayoutInflater mInflater; public Adapter(Context context) { mInflater = LayoutInflater.from(context); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = mInflater.inflate(R.layout.item_l, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) { Model model = mModelList.get(position); holder.mTextView.setText(model.getContent()); holder.mImageView.setImageResource(model.getRsId()); } @Override public int getItemCount() { return mModelList.size(); } static class ViewHolder extends RecyclerView.ViewHolder { private TextView mTextView; private ImageView mImageView; public ViewHolder(View itemView) { super(itemView); mTextView = itemView.findViewById(R.id.txt); mImageView = itemView.findViewById(R.id.img); } } }

編寫一個介面用來對資料判斷

public interface ISticky {
    //判斷是否為同類別的第一個位置
    boolean isFirstPosition(int pos);
    //獲取標題
    String getGroupTitle(int pos);
}
  1. 最重要的一步來了 就是自定義ItemDecoration,程式碼如下,詳細註釋我已經寫在裡面了
public class StickyItemDecoration extends RecyclerView.ItemDecoration {

    private ISticky mISticky;
    //矩形高度
    private int mRectHeight;
    //文字TextSize
    private int mTextPaintSize;
    private Paint mTxtPaint;
    private Paint mRectPaint;
    //分割線畫筆
    private Paint mDividerPaint;

    public StickyItemDecoration(Context context,ISticky iSticky) {
        mISticky=iSticky;
        mRectHeight= (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,30,
                context.getResources().getDisplayMetrics());

        mTextPaintSize=(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,17,
                context.getResources().getDisplayMetrics());
        mTxtPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        mTxtPaint.setColor(Color.BLACK);
        mTxtPaint.setTextSize(mTextPaintSize);

        mRectPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        mRectPaint.setStyle(Paint.Style.FILL);
        mRectPaint.setColor(Color.parseColor("#DDDDDD"));

        mDividerPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        mDividerPaint.setStyle(Paint.Style.FILL);
        mDividerPaint.setColor(Color.WHITE);
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        int childCount=parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View view=parent.getChildAt(i);
            int left=parent.getPaddingLeft();
            int right=parent.getWidth()-parent.getPaddingRight();
            int top=view.getTop()-1;
            int bottom=view.getTop();
            //Item分割線
            c.drawRect(left,top,right,bottom,mDividerPaint);
        }
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDrawOver(c, parent, state);

        int childCount=parent.getChildCount();
        int itemCount=state.getItemCount();
        int left=parent.getPaddingLeft();
        int right=parent.getWidth()-parent.getPaddingRight();
        String preGroupTitle;
        String groupTitle="";
        for (int i = 0; i < childCount; i++) {
            View child=parent.getChildAt(i);
            int pos=parent.getChildLayoutPosition(child);
            preGroupTitle=groupTitle;
            groupTitle=mISticky.getGroupTitle(pos);
            //如果當前分組名和之前分組名一樣,忽略此次迴圈
            if (groupTitle.equals(preGroupTitle)) {
                continue;
            }

            //文字的基線,保證顯示完全
            int textBaseLine=Math.max(mRectHeight,child.getTop());

            //分組標題
            String title=mISticky.getGroupTitle(pos);

            int viewBottom=child.getBottom();
            //加入限定 防止陣列越界
            if (pos + 1 < itemCount) {
                String nextGroupTitle=mISticky.getGroupTitle(pos+1);
                //當分組不一樣  並且改組要向上移動時候
                if (!nextGroupTitle.equals(groupTitle) && viewBottom < textBaseLine) {
                    //將上一個往上移動
                    textBaseLine = viewBottom;
                }
            }
            //繪製邊框
            c.drawRect(left, textBaseLine - mRectHeight, right, textBaseLine, mRectPaint);

            //繪製文字並且實現文字居中
            int value= (int) Math.abs(mTxtPaint.getFontMetrics().descent
                    +mTxtPaint.getFontMetrics().ascent);
            c.drawText(title, left,
                    textBaseLine-(mRectHeight+value)/2,
                    mTxtPaint);
        }

    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        int pos=parent.getChildLayoutPosition(view);
        if (mISticky.isFirstPosition(pos)) {
            outRect.top=mRectHeight;
            outRect.bottom=1;
        }else {
            outRect.bottom=1;
        }
    }
}

5.最後只要設定一下即可

final List<Model> modelList=new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            modelList.add(new Model("標題1","Content:1_"+i,R.mipmap.ic_launcher_round));
        }
        for (int i = 0; i < 10; i++) {
            modelList.add(new Model("標題2","Content:2_"+i,R.mipmap.ic_launcher_round));
        }
        for (int i = 0; i < 10; i++) {
            modelList.add(new Model("標題3","Content:3_"+i,R.mipmap.ic_launcher_round));
        }
        mRecyclerView.addItemDecoration(new StickyItemDecoration(this, new ISticky() {
            @Override
            public boolean isFirstPosition(int pos) {
                return pos==0||
                        !modelList.get(pos).getTitle().equals(modelList.get(pos-1).getTitle());
            }

            @Override
            public String getGroupTitle(int pos) {
                return modelList.get(pos).getTitle();
            }
        }));

備註:第一次寫部落格 如有不好之處 還望大家見諒

相關推薦

JQ實現效果代碼

簡單 scroll gpo function fixed 實現 win scrolltop 默認 吸頂下過代碼跟簡單幾行代碼就可以了 如果滾動的軍力大於100,就改變導航的定位方式,否則就默認 $(function(){ $(window).scroll(

Angular2-6 實現效果指令

做專案的時候需要用到吸頂效果,可是沒有找到單獨的外掛,所以自己實現一個吸頂的指令. 思路為檢測需要吸頂的元素是否滾動到頂部,為其加上fixed屬性 auto-fixed.directive.ts @Directive({ selector: '[txA

React Native 基礎 之ListView實現效果

當滑動時,這個section header會固定在頭部,也就是吸頂效果。但是遺憾的是,在Android平臺上不支援吸頂效果 實現吸頂效果需要用到此方法 cloneWithRowsAndSections(dataBlob, sectionIdentities, rowIde

RecyclerView使用ItemDecoration實現效果

寫此部落格目的僅僅用於幫助自己做筆記 吸頂效果在很多APP都可以看見,現在可以藉助RecyclerView的ItemDecoration 來簡單實現一個吸頂效果直接上效果圖: 首先實現一個Model實體,該Model需要包含區分不同組的欄位,例如下面這

Vue開發——實現效果

因為專案需求,最近開始轉到微信公眾號開發,接觸到了Vue框架,這個效果的實現雖說是基於Vue框架下實現的,但是同樣也可以借鑑到其他

js實現div效果

src ons posit 全局變量 mar document padding addclass type <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script

jquery實現導航效果

jquery實現導航吸頂效果,主要通過監聽頁面滾動事件和獲取頁面各引數實現,可參考我的部落格《使用原生js獲取頁面資訊》和jquery手冊 <!DOCTYPE html> <html> <head lang="en"> <meta cha

效果的另一種實現

  前面介紹過一篇文章,是使用ItemDecoration來實現吸頂效果,使用起來很解耦,簡單,方便,但是優缺點是拓展性比較差,今天就通過另一種方式來實現吸頂效果,並且吸頂欄可以高度制定佈局和互動,步入正題,下面來實現它,先看看效果圖: 一、實現原理 頭部的內容位於R

Android 最流行的效果實現及程式碼

開始逐漸領略到ItemDecoration的美~ 今天讓我 使用 ItemDecoration 來完成 可推動的懸浮導航欄的效果,最終實現的效果如下圖: 具體實現步驟如下: 根據我前面的文章所講的RecyclerView的基本使用,我們先來完成基本的recyclerView: 第一步:佈局裡寫一個Recyc

Android-使用RecyclerView的ItemDecoration 實現炫酷的 效果

開始逐漸領略到ItemDecoration的美~ 原始碼已上傳至github,感興趣的同學可以下載: 今天讓我 使用 ItemDecoration 來完成 可推動的懸浮導航欄的效果,最終實現的效果如下圖: 如果你對分型別的RecyclerView還不是太瞭解

Vue 事件監聽實現導航欄效果(頁面滾動後定位)

所說的吸頂效果就是在頁面沒有滑動之前,導航欄的效果如下圖所示:當頁面向上滑動之後,導航欄始終固定在頁面的上方。具體程式碼:寫入事件監聽,監聽滾動條。mounted () { // 事件監聽滾動條 window.addEventListener('scroll', this.watchS

Android studio RecyclerView實現炫酷效果

public class SectionDecoration extends RecyclerView.ItemDecoration { private List<NameBean> beanList; private TextPaint textPaint; priva

jquery實現導航欄效果(簡潔版)

憋說話,直接上程式碼,先是最最重要的js:   $(function(){     var a = $('#course-tab'),       b =a.offset();//返回或設定導航欄相

UWP中使用Composition API實現(2)

.com 部分 線性 col 調整 row 系統內置 模板 高度 原文:UWP中使用Composition API實現吸頂(2)在上一篇中我們討論了不涉及Pivot的吸頂操作,但是一般來說,吸頂的部分都是Pivot的Header,所以在此我們將討論關於Pivot多個Item

基於scroll的效果

初始 str 下載 瀏覽器 基礎上 function 9.png har 準備 本次要實現的是一種常見的網頁效果,如下: 頁面由頭部,導航,主體內容三部分組成,當頁面發生滾動時,頭部逐漸隱藏,導航部分向上移動,直到導航部分距離瀏覽器頂部為零時,導航部分固定不動,保持吸頂效

小程式 -- 效果

​ wxml部分 <view class=" {{menuFixed ? 'fixed': ''}}" id="affix">選單欄</view> wxss部分 .fixed{position: fixed; top: 0; } js部分 onShow:

支付寶小程序滾動監聽效果

頂部 style fix pan menu 小程序 定位 bsp color axml部分 <view class=" {{menuFixed ? ‘fixed‘: ‘‘}}" id="affix">菜單欄</view> axss部分 .fix

recycleview效果原始碼

   public String url="http://api.meituan.com/mmdb/movie/v2/list/rt/order/coming.json?ci=1&limit=12&token=&__vhost=api.maoyan.com&utm_campai

如何在Vue專案中實現元素

我的思路就是判斷合適的時候將這個元素的position設為fixed,那麼這個合適的時機如何判斷呢?我們可以計算頁面滾動的距離。 監聽頁面滾動狀態 在mounted鉤子中加入以下程式碼: mounted() { // handleScroll為頁面滾動的監聽回撥 wind

小程式 滑動選單欄效果 抖動優化

  1. 先來看一下未滑動的效果,(樣式隨便寫的,希望儘量簡單)       2.滑動到選單欄之後的吸頂效果        3. 我的html佈局,小程式我用的是mpvue寫的,使用了scss,可以自行下載d