• Android 最流行的吸顶效果的实现及代码


    开始逐渐领略到ItemDecoration的美~

    今天让我 使用 ItemDecoration 来完成 可推动的悬浮导航栏的效果,最终实现的效果如下图:

    具体实现步骤如下:

    根据我前面的文章所讲的RecyclerView的基本使用,我们先来完成基本的recyclerView

    第一步:布局里写一个RecyclerView

    第二步:实例化

    recyclerView = (RecyclerView) findViewById(R.id.recyclerView);

    第三步:获取所需的数据 (这里我们来个真实点的情景,去联网请求数据)

    /** 
        * 联网请求所需的url 
        */  
       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_campaign=AmovieBmovieCD-1&movieBundleVersion=6801&utm_source=xiaomi&utm_medium=android&utm_term=6.8.0&utm_content=868030022327462&net=255&dModel=MI%205&uuid=0894DE03C76F6045D55977B6D4E32B7F3C6AAB02F9CEA042987B380EC5687C43&lat=40.100673&lng=116.378619&__skck=6a375bce8c66a0dc293860dfa83833ef&__skts=1463704714271&__skua=7e01cf8dd30a179800a7a93979b430b2&__skno=1a0b4a9b-44ec-42fc-b110-ead68bcc2824&__skcy=sXcDKbGi20CGXQPPZvhCU3%2FkzdE%3D";
    
    //联网获取数据  
           getDataFromNet();
    
    /** 
         * 使用okhttpUtils进行联网请求数据 
         */  
        private void getDataFromNet() {  
            OkHttpUtils.  
                    get()  
                    .url(url)  
                    .build()  
                    .execute(new StringCallback() {  
                        @Override  
                        public void onError(okhttp3.Call call, Exception e, int id) {  
                            Log.e("TAG", "联网失败" + e.getMessage());  
                        }  
    
                        @Override  
                        public void onResponse(String response, int id) {  
                            Log.e("TAG", "联网成功==" + response);  
    
                            //联网成功后使用fastjson解析  
                            processData(response);  
                        }  
                    });  
        }
    
    /** 
         * 使用fastjson进行解析 
         * 
         * @param json 
         */  
        private void processData(String json) {  
            //这里使用GsonFormat生成对应的bean类  
           JSONObject jsonObject = parseObject(json);  
    
            String data = jsonObject.getString("data");  
            JSONObject dataObj = JSON.parseObject(data);  
    
            String coming = dataObj.getString("coming");  
            List<WaitMVBean.DataBean.ComingBean> comingslist = parseArray(coming, WaitMVBean.DataBean.ComingBean.class);  
    
            //测试是否解析数据成功  
    //        String strTest = comingslist.get(0).getCat();  
    //        Log.e("TAG", strTest + "222");  
    
             //解析数据成功,设置适配器-->  
    
            }  
    
        }

    第四步:解析数据成功后,创建并设置适配器,并传递相关数据

    //解析数据成功,设置适配器  
               MyRecyclerAdapter adapter = new MyRecyclerAdapter( mContext,comingslist);  
               recyclerView.setAdapter(adapter);

    适配器:

    public class MyRecyclerAdapter extends RecyclerView.Adapter {  
    
        private final List<WaitMVBean.DataBean.ComingBean> comingslist;  
        private final Context mContext;  
        private final LayoutInflater mLayoutInflater;  
    
        public MyRecyclerAdapter(Context mContext, List<WaitMVBean.DataBean.ComingBean> comingslist) {  
            this.mContext = mContext;  
            this.comingslist = comingslist;  
            mLayoutInflater = LayoutInflater.from(mContext);  
        }  
    
        @Override  
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  
            return new MyViewHolder(mLayoutInflater.inflate(R.layout.date_item, null));  
        }  
    
        @Override  
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {  
            MyViewHolder myholder = (MyViewHolder) holder;  
            myholder.setData(position);  
        }  
    
        @Override  
        public int getItemCount() {  
            return comingslist.size();  
        }  
    
        class MyViewHolder extends RecyclerView.ViewHolder {  
            private TextView mv_name;  
            private TextView mv_dec;  
            private TextView mv_date;  
            private ImageView imageView;  
    
            public MyViewHolder(View itemView) {  
                super(itemView);  
                mv_name = (TextView) itemView.findViewById(R.id.mv_name);  
                mv_dec = (TextView) itemView.findViewById(R.id.mv_dec);  
                mv_date = (TextView) itemView.findViewById(R.id.mv_date);  
                imageView = (ImageView) itemView.findViewById(R.id.image);  
            }  
    
            public void setData(int position) {  
                WaitMVBean.DataBean.ComingBean coming = comingslist.get(position);  
    
                String name = coming.getNm();  
                mv_name.setText(name);  
    
                String date = coming.getShowInfo();  
                mv_date.setText(date);  
    
                String dec = coming.getScm();  
                mv_dec.setText(dec);  
    
                //注:当你发下图片无法打开是,做个字符串替换即可  
                String imagUrl = coming.getImg();  
                String newImagUrl = imagUrl.replaceAll("w.h", "50.80");  
    
                //使用Glide加载图片  
                Glide.with(mContext)  
                        .load(newImagUrl)  
                        .into(imageView);  
            }  
        }  
    }

    item的布局:

    <?xml version="1.0" encoding="utf-8"?>  
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:background="#ffffff"  
        android:gravity="center_vertical"  
        android:orientation="horizontal">  
    
        <ImageView  
            android:id="@+id/image"  
            android:layout_width="70dp"  
            android:layout_height="110dp"  
            android:layout_marginBottom="5dp"  
            android:layout_marginLeft="10dp"  
            android:layout_marginRight="8dp"  
            android:layout_marginTop="5dp" />  
    
        <LinearLayout  
            android:layout_width="0dp"  
            android:layout_height="wrap_content"  
            android:layout_marginLeft="6dp"  
            android:layout_weight="1"  
            android:orientation="vertical">  
    
            <TextView  
                android:id="@+id/mv_name"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:text="神奇動物在哪裏"  
                android:textColor="#000000"  
                android:textSize="15sp" />  
    
            <LinearLayout  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:orientation="horizontal">  
    
                <TextView  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:text="观众"  
                    android:textColor="#55000000"  
                    android:textSize="14sp" />  
    
                <TextView  
                    android:id="@+id/tv_people"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:text="9.0 "  
                    android:textColor="#FFCE42"  
                    android:textSize="18sp" />  
    
                <TextView  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:text=" | 专业"  
                    android:textColor="#55000000"  
                    android:textSize="14sp" />  
    
                <TextView  
                    android:id="@+id/tv_professional"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:text="6.7"  
                    android:textColor="#FFCE42"  
                    android:textSize="18sp" />  
            </LinearLayout>  
    
            <TextView  
                android:id="@+id/mv_dec"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:layout_marginTop="8dp"  
                android:text="神奇動物城,法師顯超能"  
                android:textColor="#99000000"  
                android:textSize="11sp" />  
    
            <TextView  
                android:id="@+id/mv_date"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:layout_marginTop="10dp"  
                android:text="今天165家影院放映2088场"  
                android:textColor="#99000000"  
                android:textSize="11sp" />  
        </LinearLayout>  
    
    </LinearLayout>

    第五步:一定不能忘!!!

    recycleView不仅要设置适配器还要设置布局管理者,否则图片不显示

    GridLayoutManager manager = new GridLayoutManager(this, 1);  
                recyclerView.setLayoutManager(manager);

    此时RecyclerView简单的完成效果如下:

    下面开始做 可推动的 悬浮导航栏:

    第一步:首先我们来写一个类,它起标记的作用,来放每一个item的对应的悬浮栏的字符串

    public class NameBean {  
        String name;  
    
        public String getName() {  
            return name;  
        }  
    
        public void setName(String name) {  
            this.name = name;  
        }  
    }
    public class SectionDecoration extends RecyclerView.ItemDecoration {  
        private static final String TAG = "SectionDecoration";  
    
        private List<NameBean> dataList;  
    
        private DecorationCallback callback;  
        private TextPaint textPaint;  
        private Paint paint;  
        private int topGap;  
        private int alignBottom;  
        private Paint.FontMetrics fontMetrics;  
    
        public SectionDecoration(List<NameBean> dataList, Context context, DecorationCallback decorationCallback) {  
            Resources res = context.getResources();  
            this.dataList = dataList;  
            this.callback = decorationCallback;  
            //设置悬浮栏的画笔---paint  
            paint = new Paint();  
            paint.setColor(res.getColor(R.color.colorGray));  
    
            //设置悬浮栏中文本的画笔  
            textPaint = new TextPaint();  
            textPaint.setAntiAlias(true);  
            textPaint.setTextSize(DensityUtil.dip2px(context, 14));  
            textPaint.setColor(Color.DKGRAY);  
            textPaint.setTextAlign(Paint.Align.LEFT);  
            fontMetrics = new Paint.FontMetrics();  
            //决定悬浮栏的高度等  
            topGap = res.getDimensionPixelSize(R.dimen.sectioned_top);  
            //决定文本的显示位置等  
            alignBottom = res.getDimensionPixelSize(R.dimen.sectioned_alignBottom);  
        }  
    
        @Override  
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {  
            super.getItemOffsets(outRect, view, parent, state);  
            int pos = parent.getChildAdapterPosition(view);  
            Log.i(TAG, "getItemOffsets:" + pos);  
            String groupId = callback.getGroupId(pos);  
            if (groupId.equals("-1")) return;  
            //只有是同一组的第一个才显示悬浮栏  
            if (pos == 0 || isFirstInGroup(pos)) {  
                outRect.top = topGap;  
                if (dataList.get(pos).getName() == "") {  
                    outRect.top = 0;  
                }  
            } else {  
                outRect.top = 0;  
            }  
        }  
    
        @Override  
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {  
            super.onDraw(c, parent, state);  
            int left = parent.getPaddingLeft();  
            int right = parent.getWidth() - parent.getPaddingRight();  
            int childCount = parent.getChildCount();  
            for (int i = 0; i < childCount; i++) {  
                View view = parent.getChildAt(i);  
                int position = parent.getChildAdapterPosition(view);  
                String groupId = callback.getGroupId(position);  
                if (groupId.equals("-1")) return;  
                String textLine = callback.getGroupFirstLine(position).toUpperCase();  
                if (textLine == "") {  
                    float top = view.getTop();  
                    float bottom = view.getTop();  
                    c.drawRect(left, top, right, bottom, paint);  
                    return;  
                } else {  
                    if (position == 0 || isFirstInGroup(position)) {  
                        float top = view.getTop() - topGap;  
                        float bottom = view.getTop();  
                        //绘制悬浮栏  
                        c.drawRect(left, top - topGap, right, bottom, paint);  
                        //绘制文本  
                        c.drawText(textLine, left, bottom, textPaint);  
                    }  
                }  
            }  
        }  
    
        @Override  
        public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {  
            super.onDrawOver(c, parent, state);  
            int itemCount = state.getItemCount();  
            int childCount = parent.getChildCount();  
            int left = parent.getPaddingLeft();  
            int right = parent.getWidth() - parent.getPaddingRight();  
            float lineHeight = textPaint.getTextSize() + fontMetrics.descent;  
    
            String preGroupId = "";  
            String groupId = "-1";  
            for (int i = 0; i < childCount; i++) {  
                View view = parent.getChildAt(i);  
                int position = parent.getChildAdapterPosition(view);  
    
                preGroupId = groupId;  
                groupId = callback.getGroupId(position);  
                if (groupId.equals("-1") || groupId.equals(preGroupId)) continue;  
    
                String textLine = callback.getGroupFirstLine(position).toUpperCase();  
                if (TextUtils.isEmpty(textLine)) continue;  
    
                int viewBottom = view.getBottom();  
                float textY = Math.max(topGap, view.getTop());  
                //下一个和当前不一样移动当前  
                if (position + 1 < itemCount) {  
                    String nextGroupId = callback.getGroupId(position + 1);  
                    //组内最后一个view进入了header  
                    if (nextGroupId != groupId && viewBottom < textY) {  
                        textY = viewBottom;  
                    }  
                }  
                //textY - topGap决定了悬浮栏绘制的高度和位置  
                c.drawRect(left, textY - topGap, right, textY, paint);  
                //left+2*alignBottom 决定了文本往左偏移的多少(加-->向左移)  
                //textY-alignBottom  决定了文本往右偏移的多少  (减-->向上移)  
                c.drawText(textLine, left + 2 * alignBottom, textY - alignBottom, textPaint);  
            }  
        }  
    
        /** 
         * 判断是不是组中的第一个位置 
         * 
         * @param pos 
         * @return 
         */  
        private boolean isFirstInGroup(int pos) {  
            if (pos == 0) {  
                return true;  
            } else {  
                // 因为是根据 字符串内容的相同与否 来判断是不是同意组的,所以此处的标记id 要是String类型  
                // 如果你只是做联系人列表,悬浮框里显示的只是一个字母,则标记id直接用 int 类型就行了  
                String prevGroupId = callback.getGroupId(pos - 1);  
                String groupId = callback.getGroupId(pos);  
                //判断前一个字符串 与 当前字符串 是否相同  
                if (prevGroupId.equals(groupId)) {  
                    return false;  
                } else {  
                    return true;  
                }  
            }  
        }  
    
        //定义一个借口方便外界的调用  
        interface DecorationCallback {  
            String getGroupId(int position);  
    
            String getGroupFirstLine(int position);  
        }  
    }

    第三步:在向list集合中先把每一个item的 起“标记”作用的字符串都加进去

    setPullAction(comingslist);
    
    private void setPullAction(List<WaitMVBean.DataBean.ComingBean> comingslist) {  
            dataList = new ArrayList<>();  
    
            for (int i = 0; i < comingslist.size(); i++) {  
                NameBean nameBean = new NameBean();  
                String name0 = comingslist.get(i).getComingTitle();  
                nameBean.setName(name0);  
                dataList.add(nameBean);  
            }  
        }

    第四步:在setAdapter() 前,为RecyclerView添加ItemDecoration:

    recyclerView.addItemDecoration(new SectionDecoration(dataList,mContext, new SectionDecoration.DecorationCallback() {  
                   //返回标记id (即每一项对应的标志性的字符串)  
                    @Override  
                    public String getGroupId(int position) {  
                        if(dataList.get(position).getName()!=null) {  
                            return dataList.get(position).getName();  
                        }  
                        return "-1";  
                    }  
    
                    //获取同组中的第一个内容  
                    @Override  
                    public String getGroupFirstLine(int position) {  
                        if(dataList.get(position).getName()!=null) {  
                            return dataList.get(position).getName();  
                        }  
                        return "";  
                    }  
                }));

    这样就完成了~

    再看一眼最终效果感受一下:

  • 相关阅读:
    hdu6229 Wandering Robots 2017沈阳区域赛M题 思维加map
    hdu6223 Infinite Fraction Path 2017沈阳区域赛G题 bfs加剪枝(好题)
    hdu6438 Buy and Resell 买卖物品 ccpc网络赛 贪心
    hdu6441 Find Integer 求勾股数 费马大定理
    bzoj 1176 Mokia
    luogu 3415 祭坛
    bzoj 1010 玩具装箱
    bzoj 3312 No Change
    luogu 3383【模板】线性筛素数
    bzoj 1067 降雨量
  • 原文地址:https://www.cnblogs.com/wangyayun/p/9209164.html
Copyright © 2020-2023  润新知