最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android 知乎廣告效果實(shí)現(xiàn)代碼

 更新時間:2018年01月24日 15:58:48   作者:達(dá)峰a  
這篇文章主要介紹了Android 知乎廣告效果實(shí)現(xiàn)代碼,需要的朋友可以參考下

知乎的廣告效果一直想寫,無奈最近才有時間。

先看效果:

肯定要自定義view了,一個類似imageView的控件,還要給它一個值用來指定廣告圖片的顯示位置。

問題:

1.圖片如何在范圍內(nèi)(單個item范圍)上下移動,如窗戶一般,后面的圖是可以動的,但是窗戶是固定的。
2.圖片移動的時機(jī)肯定和recycleView滾動監(jiān)聽item有關(guān),用哪些方法?

解決:

1.窗戶問題首先想到imageView的scaleType屬性,而scaleType中只有matrix和center可以在不縮放圖片的情況下顯示一張大圖中的部分,center始終顯示在圖片中間部分,不符合要求,matrix不指定顯示位置。

2.recycleView Item的滾動監(jiān)聽,剛好前段時間在仿寫微博視頻自動播放時接觸過,recycleView提供了一些譬如FindFirstVisibleItemPosition(當(dāng)前屏幕第一個item的position),F(xiàn)indFirstCompletelyVisibleItemPosition(當(dāng)前屏幕第一個完全顯示item的position)等方法,可以利用這些方法,把當(dāng)前的item找到,再利用instanceof關(guān)鍵字比較當(dāng)前item是不是我的廣告item,如果是再想辦法讓廣告圖片動起來。

步驟:

1.自定義一個廣告imageView,把他變成窗戶:

繼承imageView,只需要重寫他的2個方法,onSizeChanged和onDraw。
onSizeChanged用來得到控件高度
onDraw移動廣告圖片

int itemHeight = 0;  //自定義imageView高度
private float rate = 1; //初始化顯示比率

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
  itemHeight = h; //廣告item的高度
}

@Override
protected void onDraw(Canvas canvas) {
  Drawable drawable = getDrawable();
  if (drawable == null) {
    return;
  }
  int w = getWidth();
  int h = (int) (getWidth() * 1.0f / drawable.getIntrinsicWidth() * drawable.getIntrinsicHeight());
  drawable.setBounds(0, 0, w, h);//設(shè)置圖片顯示的絕對范圍
  int maxDy = h - itemHeight; //圖片可以移動的最大距離為(圖片有效移動距離):  (0 ~ -maxDy)
  canvas.save();
  canvas.translate(0, -rate * maxDy);
  super.onDraw(canvas);
  canvas.restore();
}



public void setDy(int itemDy, int rvheight) {
  int allHeight = rvheight - itemHeight; //有效滑動高度(廣告有效移動距離)
  rate = itemDy * 1f / allHeight;
  
  if (rate <= 0) {
    rate = 0;
  }
  if (rate >= 1) {
    rate = 1;
  }
  invalidate();
}

setDy方法可以先不管。

onDraw中說幾個點(diǎn):

super.onDraw(canvas)代碼中的位置

super.onDraw(canvas)是實(shí)現(xiàn)原本imageView邏輯的地方,涉及自定義view繪制先后問題;假如我用canvas畫了一個圓,畫圓代碼寫在super之前: 這個圓會先繪制出來,再走super,就會出現(xiàn)imageView把圓擋住的情況,畫圓代碼寫在super之后:
先走super再畫圓,圓就在imageView的上面。參考上面代碼中的super位置,先把圖片的位置通過 canvas.translate方法移動之后,再利用super原本邏輯繪制出圖片,就實(shí)現(xiàn)圖片在窗口中移動的效果了。 (此番解釋只針對繼承已有的imageview,textview等,如果是繼承View,super位置就很隨意了,因?yàn)閟uper是個空實(shí)現(xiàn))

drawable.setBounds(l,t,r,b)方法

這個方法給圖片設(shè)定一個絕對位置范圍~(或者說相對屏幕的顯示范圍)~,上面代碼中的范圍計算~(參數(shù)r,b)~其實(shí)就是 整個屏幕除開狀態(tài)欄導(dǎo)航欄以外的范圍~(recycleView的范圍)~。 int w = getWidth()算出圖片可以顯示的最大寬度,再通過最大寬度 / 圖片原本寬度 = 最大高度 / 圖片原本高度 計算出最大高度 h。也就是int h = ....這一句。

通過onDraw方法,已經(jīng)可以實(shí)現(xiàn):一個imageView控件,動態(tài)的去移動它的內(nèi)部圖片。這個自定義的imageView就算是完成了。

2.獲取recycleView監(jiān)聽以及位置計算

寫監(jiān)聽之前想想如何把recycleView的item與自定義imageView聯(lián)系起來,通過 canvas.translate(dx,dy)讓圖片動起來,必須要求出dy:
可以看看效果,只要廣告的item有一點(diǎn)不在屏幕內(nèi),那么其中的圖片是不會移動的,那么我們廣告item有效移動距離就是整個recycleView的高度減去廣告item的高度,如圖綠色線:

而我們自定義imageView中圖片有效移動距離是整個圖片的高度減去窗口的高度,如圖綠色線:(紅色框就相當(dāng)于自定義imageView窗口,整張圖就是窗后可以translate的圖片)

關(guān)系就出來了: 廣告item位置 / 廣告有效移動距離 = dy / 圖片有效移動距離

重寫RecyclerView.OnScrollListener中的onScrolled方法,我們要得到:廣告item位置 和 廣告有效移動距離

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
  super.onScrolled(recyclerView, dx, dy);

  int first = layoutManager.findFirstCompletelyVisibleItemPosition(); //第一個完全顯示的item
  int last = layoutManager.findLastCompletelyVisibleItemPosition(); //最后一個完全顯示的item
  int firstPosition = layoutManager.findFirstVisibleItemPosition(); //第一個顯示的item
  int lastPosition = layoutManager.findLastVisibleItemPosition(); //最后一個顯示的item 
  
  //循環(huán)遍歷當(dāng)前屏幕中顯示的所有item
  for (int i = firstPosition; i <= lastPosition; i++) {
    RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(i);
    //找出屏幕中的廣告item
    if (viewHolder instanceof TxRecycleAdapter.ZhiHuHolder) {
      TxRecycleAdapter.ZhiHuHolder zhiHuHolder = (TxRecycleAdapter.ZhiHuHolder) viewHolder;
      View itemView = zhiHuHolder.itemView;
      //獲取到廣告item的位置 (item的頂部 與 recycleView頂部的距離)
      int top = itemView.getTop();
      //獲取recycleView的高度
      int height = recyclerView.getHeight();
      //調(diào)用自定義imageView中的方法,實(shí)現(xiàn)圖片的移動
      zhiHuHolder.adImageView.setDy(top, height);
    }
  }
}

int top = itemView.getTop(); top = 廣告item位置;
廣告有效移動距離 = recycleView的高度 - 廣告item的高度,這一點(diǎn)的實(shí)現(xiàn)放在了自定義imageView的setDy方法中。
注意方法中的for循環(huán)

for (int i = firstPosition; i <= lastPosition; i++) {}

rate等于1圖片剛好顯示在 頂部
rate等于0圖片剛好顯示在 底部
rate從0~1:
滑動慢 rate可能是這么變化的:0.05, 0.10,0.15,0.20 .....,0.80,0.85,0.90,0.95,1.0。
滑動快 rate可能是這么變化的:0.3,0.6,0.9。
壓根就不會等于1或者等于0,那圖片的translate位置肯定就不對了。

出現(xiàn)這個問題我試過很多方法,比如速度跟蹤類(VelocityTracker)計算速度,當(dāng)速度大了再根據(jù)滑動方向直接置頂或者置底,獲取廣告item可見性置頂或者置底.....等等。有些方法可能有點(diǎn)用,但是太麻煩了,最后直接在for循環(huán)中用firstPosition和lastPosition,這樣,雖然會出現(xiàn)rate = - 0.2 這樣的負(fù)值,但是你只要給個判斷就可以了:

if (rate <= 0){
  rate = 0;
}
if (rate >= 1) {
  rate = 1;
 }

剛已經(jīng)通過recycleView的監(jiān)聽得到了廣告item位置 與 廣告有效移動距離,而 圖片有效移動距離呢,它在自定義imageView中的onDraw方法得到:

int maxDy = h - itemHeight;//圖片可以移動的最大距離為(圖片有效移動距離): (0 ~ -maxDy)

最后,調(diào)用canvas.translate(0, -rate * maxDy);方法就可以實(shí)現(xiàn)整個效果了。

相關(guān)文章

最新評論

连江县| 阿坝| 刚察县| 马公市| 积石山| 龙里县| 永州市| 赣榆县| 曲阳县| 鹿泉市| 绍兴市| 历史| 定边县| 莱州市| 九台市| 保康县| 察隅县| 西平县| 边坝县| 海林市| 安仁县| 鹤壁市| 博白县| 白玉县| 开鲁县| 瑞金市| 禹州市| 绥芬河市| 安多县| 冀州市| 清水县| 柏乡县| 罗城| 灵石县| 宣威市| 遂川县| 正定县| 米脂县| 肇东市| 万宁市| 琼中|