安卓当下最流行的吸顶效果的实现(转)
原文出處:?李詩雨???
開始逐漸領略到ItemDecoration的美~
今天讓我 使用?ItemDecoration?來完成?可推動的懸浮導航欄的效果,最終實現的效果如下圖:
具體實現步驟如下:
根據我前面的文章所講的RecyclerView的基本使用,我們先來完成基本的recyclerView:
第一步:布局里寫一個RecyclerView
第二步:實例化
Java| 1 | recyclerView = (RecyclerView) findViewById(R.id.recyclerView); | 
第三步:獲取所需的數據 (這里我們來個真實點的情景,去聯網請求數據)
Java| 1 2 3 4 | /** ????* 聯網請求所需的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"; | 
?
Java| 1 2 | //聯網獲取數據?? ?????? getDataFromNet(); | 
?
Java| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /** ???? * 使用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);?? ????????????????????}?? ????????????????});?? ????} | 
?
Java| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /** ???? * 使用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");?? ?? ???????? //解析數據成功,設置適配器-->?? ???????? ????????}?? ?? ????} | 
第四步:解析數據成功后,創建并設置適配器,并傳遞相關數據
Java| 1 2 3 | //解析數據成功,設置適配器?? ?????????? MyRecyclerAdapter adapter = new MyRecyclerAdapter( mContext,comingslist);?? ?????????? recyclerView.setAdapter(adapter); | 
適配器:
Java| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 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的布局:
Java| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | <?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不僅要設置適配器還要設置布局管理者,否則圖片不顯示
Java| 1 2 | GridLayoutManager manager = new GridLayoutManager(this, 1);?? ????????????recyclerView.setLayoutManager(manager); | 
此時RecyclerView簡單的完成效果如下:
下面開始做 可推動的 懸浮導航欄:
第一步:首先我們來寫一個類,它起標記的作用,來放每一個item的對應的懸浮欄的字符串
Java| 1 2 3 4 5 6 7 8 9 10 11 | public class NameBean {?? ????String name;?? ?? ????public String getName() {?? ????????return name;?? ????}?? ?? ????public void setName(String name) {?? ????????this.name = name;?? ????}?? } | 
第二步:自定義一個SectionDecoration 類?繼承 RecyclerView的ItemDecoration
Java| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | 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的 起“標記”作用的字符串都加進去
Java| 1 | setPullAction(comingslist); | 
?
Java| 1 2 3 4 5 6 7 8 9 10 | 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:
Java| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 "";?? ????????????????}?? ????????????})); | 
這樣就完成了~
再看一眼最終效果感受一下:
轉載于:https://www.cnblogs.com/henkun010/p/6645616.html
總結
以上是生活随笔為你收集整理的安卓当下最流行的吸顶效果的实现(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 南京哪家洗车最干净、而已汽车美容做的也很
- 下一篇: 第三次作业+105032014085
