国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android中recyclerView底部添加透明漸變效果

2019-10-22 18:12:38
字體:
來源:轉載
供稿:網友

前言

最近實現一個recyclerView透明漸變的效果,遇到了一些坑,嘗試了一些方法,這里記錄一下。

效果圖

recyclerview,漸變,android,透明

recyclerview,漸變,android,透明

圖片在上面顯示2列,文字在下面顯示1列;底部要有個透明漸變的效果,直到完全看不到。

gridLayoutManager動態設置列數

大概是分兩類,一類以圖片為item 一行2個,一類以文字為item 一行一個。

這個第一反應是用viewType去區分圖片類型,但是由于起初不知道gridLayout可以動態列數。就在上面兩列,下面一列上為難起來了。

如果統一用一列吧,那就把兩個image當成一個item,但是這樣要自己去計算position,而且還要考慮奇數情況下最后一行只有一個圖片的情況,這樣要多寫一些代碼和邏輯。

后面發現可以通過改變spanSize來根據viewType來改變spanCount

 //gridLayoutManager這里設置的spanCount=2 RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); if (manager instanceof GridLayoutManager) { final GridLayoutManager gridManager = ((GridLayoutManager) manager); gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {  @Override  public int getSpanSize(int position) {  int type = getItemViewType(position);  switch (type) {  case TYPE_IMAGE:  //占用1/2 表示2列  Log.d("tag", "列數2");  return 1;  case TYPE_TEXT:  //占用2/2 表示1列  Log.d("tag", "列數1");  return 2;  default:  Log.d("tag", "default列數2");  return 2;  }  } }); }

這樣item的layout就很干凈了,省去了一些麻煩。

recyclerView添加透明漸變

本來看著快搞完了,只差一個底部透明漸變了,結果就這一個效果高出了好多事情。

嘗試了下面三種方法

  • recycleView上面蓋一層漸變的layout
  • 原生的fadingEdeg,嘗試通過反射去掉頂部陰影
  • 圖層合并

第一反應是再在recycleView上面蓋一層漸變的layout。

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <gradient android:angle="90" android:startColor="@color/color_FFFFFFFF" android:endColor="@color/color_00FFFFFF"> </gradient></shape>

效果如下:

recyclerview,漸變,android,透明

看起來“蒙”了一點哈

但是這樣有個問題,就是layout使用這個shape的時候,是從開始到結束的漸變,沒有grandient的平鋪的效果,也就是只有最后一點是不透明的,不能實現最后是全不透明的。而且這個00FFFFFF其實不是真正意義上的不透明,而是白色的。

效果圖底下有一截是全透明的,這個和效果圖是有一定差距的,單純用shape實現不了。嘗試再在漸變下面添加一截全透明,就會慘不忍睹。

recyclerview,漸變,android,透明

recyclerView的fadingEdge

組里的老司機提了可以用這個recyclerView原生自帶的屬性。

android:requiresFadingEdge="vertical"android:fadingEdgeLength="40dp"

recyclerview,漸變,android,透明

運行起來看起來雖然和ui有點差距,但是好像可以接受了。

但是滑動的時候就出現問題了,這個自帶fadingEdge不僅底部有,頂部也有,而且更坑的是,recyclerView沒有提供取消頂部或者底部的接口。要么都不用,要么都要。

recyclerview,漸變,android,透明

參考網上的一種方法,通過反射去設置頂部的edge寬高,從而使得頂部陰影不顯示。

如何屏蔽RecyclerView單邊滑動到頭陰影(fadingEdge)

本來以為這樣就ok了,誰知道這樣設置竟然沒有效果。

參考給的代碼是這樣設置的:

recyclerview,漸變,android,透明

但是進api27的RecyclerView里面看,這個mTopGlow是EdgeEffect類型

recyclerview,漸變,android,透明

mRecycleView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); EdgeEffect mTopGlow = null; try {  Field topGlow = mRecycleView.getClass().getDeclaredField("mTopGlow");  if (topGlow != null) {  topGlow.setAccessible(true);  mTopGlow = (EdgeEffect) topGlow.get(mRecycleView);  } } catch (Exception e) {  e.printStackTrace(); } if (mTopGlow != null) {  //設置TOP頂部的矩形陰影大小(看注釋和代碼大概是這個作用)  mTopGlow.setSize(0, 0);  mTopGlow.finish(); } } });

這樣大部分情況topGlow也是空的。查看代碼,發現貌似只有這個方法才會給mTopGlow初始化

recyclerview,漸變,android,透明

強行在獲取topGlow對象前插入ensureTopGlow,使得它不為空:

recyclerview,漸變,android,透明

 public void makeTopGlowNoneNull() { final Class<?> clazz = RecyclerView.class; try { Method method = clazz.getDeclaredMethod("ensureTopGlow"); method.setAccessible(true); method.invoke(mRecycleView); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }

好了,經過上面的操作,mtopFlow取出來并且設置size(0,0)了,講道理頂部陰影只有一個長0,寬0的矩形,就相當于沒有了。

然而。。。

頂部陰影還是存在,而且去調試系統創建上下陰影的場景,也發現沒有調用setSize就把陰影畫出來了。之后又折騰了一陣子也沒看出來這個陰影在recyclerView里面怎么是怎么畫出來的,有知道的大兄弟麻煩告知一下。

通過圖層合并添加透明效果

參考Android實現直播聊天區域頂部漸變效果

 /** * 利用itemDecoration的onDraw和onDrawOver回調時機,進行兩個圖層的合并 * */ mRecycleView.addItemDecoration(new RecyclerView.ItemDecoration() { @SuppressLint("NewApi") @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); layerId = c.saveLayer(0.0f, 0.0f, (float) parent.getWidth(), (float) parent.getHeight(), mPaint); } @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDrawOver(c, parent, state); if (linearGradient == null) {  linearGradient = new LinearGradient(0f,parent.getHeight()-dpToPixel(54), 0f,  parent.getHeight()-dpToPixel(15), new int[] {startColor,endColor },new float[]{0.2f,0.8f},  Shader.TileMode.CLAMP); } mPaint.setXfermode(xfermode); mPaint.setShader(linearGradient); c.drawRect(0f,parent.getHeight()-dpToPixel(54),parent.getWidth(),parent.getHeight(),mPaint); mPaint.setXfermode(null); c.restoreToCount(layerId); /**  * 第一次進去的時候發現畫出來的東西很奇怪 暫未找到原因  * 需要滑動之后才會正常顯示,所以第一次進去的時候,手動調用一次刷新  */ if (recycleViewfirstComeInFlag == false) {  recycleViewfirstComeInFlag = true;  mRecycleView.postInvalidate(); } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent,  RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); } }); }

原理參考文章里面也說了,借助ItemDecoration的draw和drawOver方法將兩個圖層進行合并,用DES_IN模式,使得SRC圖層底部有了DES圖層的透明漸變。

看起來抄就完事兒了的東西,我卻搞了好一陣子。

參考demo就是一個recyclerView,我的是dialog里面裝一個recyclerView。dialog顯示在中間,因為對canvas.drawRec()參數坐標以及linearGradient的使用不太熟悉,搞出來一些事情。

關于LinearGrandient的參數

recyclerview,漸變,android,透明

前面的xy用來標明方向的。如果是Y垂直方向的漸變,只需要(0,startY)到(0,endY),X就沒啥作用,保證在Y上是垂直就行。但是這個startY和endY之前我就理解成絕對坐標了,以為手機左上角是坐標原點(0,0);

后面那個postion其實是對應各種color的位置吧,配合CLAMP模式(超出起點和終點外的默認是起點和終點的顏色向外延伸)還是挺好用的。

比起第一種直接用XML shape LienarGradient的startColor endColor要靈活很多。

然而view里面沒有像motionEvent那樣直接getRowX的方法,就通過百分比計算來找位置,又增加了復雜度。

實際情況比這些影響因素(同時還在調fadingEdge)要多,有點自找麻煩的感覺,一時陷入僵局。

倒著回去想,既然Google沒有提供獲取絕對左邊的方法,而且linearGradient也是設給paint給canvas用,那里面的坐標應該是和cavas是一致的。而canvas在很多地方如view的draw里面也能拿到,那明顯設置成相當于canvas的坐標要方便一些。

重新清醒一下頭腦,把暫時該注釋掉的注釋掉,通過最小粒度的改變來調試效果(不然一下子改變很多,出來的效果會讓人懵逼),最后總算是搞出來了。

然而事情并沒有結束。。。。。

估計是我在dialog里面顯示recyclerView的關系,通過圖層合并后,會形成很奇怪的效果,必須要滑動一下才可以正常顯示。如果recyclerView不是裝在dialog里面就不會這樣,只是單存的使用就不會這樣。

recyclerview,漸變,android,透明

很奇怪,不過這樣可以看到SRC和DES圖層 ==

暫時處理是第一次進來在drawOver完成后再postInvalidate一次,有知道原因的老哥幫忙提點一下!

 if (recycleViewfirstComeInFlag == false) {   recycleViewfirstComeInFlag = true;    mRecycleView.postInvalidate();  }

最終效果

recyclerview,漸變,android,透明

遺留的問題

  • recyclerView fadingEdge的實現,不是flow.setSize,在調試代碼時沒看出來。
  • dialog上添加recyclerView的圖層合并,最開始顯示異常的原因。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 刚察县| 加查县| 安塞县| 达拉特旗| 南汇区| 阿拉尔市| 汝南县| 龙岩市| 双辽市| 彰武县| 金秀| 黄龙县| 龙岩市| 康马县| 英德市| 来安县| 福安市| 花垣县| 来安县| 合水县| 鱼台县| 苗栗市| 莱西市| 菏泽市| 达孜县| 安阳县| 瑞金市| 班玛县| 普陀区| 浮梁县| 虞城县| 平度市| 和平区| 西乌珠穆沁旗| 南丰县| 桓台县| 天柱县| 大连市| 简阳市| 文安县| 龙口市|