Android 知乎广告效果实现代码

Android 知乎广告效果实现代码,第1张

概述知乎的广告效果一直想写,无奈最近才有时间。先看效果:肯定要自定义view了,一个类似imageView的控件,还要给它一个值用来指定广告图片的显示位置。

知乎的广告效果一直想写,无奈最近才有时间。

先看效果:

肯定要自定义view了,一个类似imageVIEw的控件,还要给它一个值用来指定广告图片的显示位置。

问题:

1.图片如何在范围内(单个item范围)上下移动,如窗户一般,后面的图是可以动的,但是窗户是固定的。
2.图片移动的时机肯定和recycleVIEw滚动监听item有关,用哪些方法?

解决:

1.窗户问题首先想到imageVIEw的scaleType属性,而scaleType中只有matrix和center可以在不缩放图片的情况下显示一张大图中的部分,center始终显示在图片中间部分,不符合要求,matrix不指定显示位置。

2.recycleVIEw Item的滚动监听,刚好前段时间在仿写微博视频自动播放时接触过,recycleVIEw提供了一些譬如FindFirstVisibleItemposition(当前屏幕第一个item的position),FindFirstCompletelyVisibleItemposition(当前屏幕第一个完全显示item的position)等方法,可以利用这些方法,把当前的item找到,再利用instanceof关键字比较当前item是不是我的广告item,如果是再想办法让广告图片动起来。

步骤:

1.自定义一个广告imageVIEw,把他变成窗户:

继承imageVIEw,只需要重写他的2个方法,onSizeChanged和onDraw。
onSizeChanged用来得到控件高度
onDraw移动广告图片

int itemHeight = 0;  //自定义imageVIEw高度private float rate = 1; //初始化显示比率@OverrIDeprotected voID onSizeChanged(int w,int h,int olDW,int oldh) {  super.onSizeChanged(w,h,olDW,oldh);  itemHeight = h; //广告item的高度}@OverrIDeprotected 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,w,h);//设置图片显示的绝对范围  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中说几个点:

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

super.onDraw(canvas)是实现原本imageVIEw逻辑的地方,涉及自定义view绘制先后问题;假如我用canvas画了一个圆,画圆代码写在super之前: 这个圆会先绘制出来,再走super,就会出现imageVIEw把圆挡住的情况,画圆代码写在super之后:
先走super再画圆,圆就在imageVIEw的上面。参考上面代码中的super位置,先把图片的位置通过 canvas.translate方法移动之后,再利用super原本逻辑绘制出图片,就实现图片在窗口中移动的效果了。 (此番解释只针对继承已有的imagevIEw,textvIEw等,如果是继承VIEw,super位置就很随意了,因为super是个空实现)

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

这个方法给图片设定一个绝对位置范围~(或者说相对屏幕的显示范围)~,上面代码中的范围计算~(参数r,b)~其实就是 整个屏幕除开状态栏导航栏以外的范围~(recycleVIEw的范围)~。 int w = getWIDth()算出图片可以显示的最大宽度,再通过最大宽度 / 图片原本宽度 = 最大高度 / 图片原本高度 计算出最大高度 h。也就是int h = ....这一句。

通过onDraw方法,已经可以实现:一个imageVIEw控件,动态的去移动它的内部图片。这个自定义的imageVIEw就算是完成了。

2.获取recycleVIEw监听以及位置计算

写监听之前想想如何把recycleVIEw的item与自定义imageVIEw联系起来,通过 canvas.translate(dx,dy)让图片动起来,必须要求出dy:
可以看看效果,只要广告的item有一点不在屏幕内,那么其中的图片是不会移动的,那么我们广告item有效移动距离就是整个recycleVIEw的高度减去广告item的高度,如图绿色线:

而我们自定义imageVIEw中图片有效移动距离是整个图片的高度减去窗口的高度,如图绿色线:(红色框就相当于自定义imageVIEw窗口,整张图就是窗后可以translate的图片)

关系就出来了: 广告item位置 / 广告有效移动距离 = dy / 图片有效移动距离

重写RecyclerVIEw.OnScrollListener中的onScrolled方法,我们要得到:广告item位置 和 广告有效移动距离

@OverrIDepublic 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     //循环遍历当前屏幕中显示的所有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();      //调用自定义imageVIEw中的方法,实现图片的移动      zhiHuHolder.adImageVIEw.setDy(top,height);    }  }}

int top = itemVIEw.gettop(); top = 广告item位置;
广告有效移动距离 = recycleVIEw的高度 - 广告item的高度,这一点的实现放在了自定义imageVIEw的setDy方法中。
注意方法中的for循环

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位置肯定就不对了。

出现这个问题我试过很多方法,比如速度跟踪类(VeLocityTracker)计算速度,当速度大了再根据滑动方向直接置顶或者置底,获取广告item可见性置顶或者置底.....等等。有些方法可能有点用,但是太麻烦了,最后直接在for循环中用firstposition和lastposition,这样,虽然会出现rate = - 0.2 这样的负值,但是你只要给个判断就可以了:

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

刚已经通过recycleVIEw的监听得到了广告item位置 与 广告有效移动距离,而 图片有效移动距离呢,它在自定义imageVIEw中的onDraw方法得到:

int maxDy = h - itemHeight;//图片可以移动的最大距离为(图片有效移动距离): (0 ~ -maxDy)

最后,调用canvas.translate(0,-rate * maxDy);方法就可以实现整个效果了。

总结

以上是内存溢出为你收集整理的Android 知乎广告效果实现代码全部内容,希望文章能够帮你解决Android 知乎广告效果实现代码所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/1143031.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-31
下一篇2022-05-31

发表评论

登录后才能评论

评论列表(0条)

    保存