点击上方“程序员大咖”,选择“置顶公众号”

关键时刻,第一时间送达!

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

先看效果:

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

问题:

1.图片如何在范围内(单个item范围)上下移动,如窗户一般,后面的图是可以动的,但是窗户是固定的。

2.图片移动的时机肯定和recycleView滚动监听item有关,用哪些方法?

解决:

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

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

步骤:

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

继承imageView,只需要重写他的2个方法,onSizeChangedonDraw
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, 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原本逻辑绘制出图片,就实现图片在窗口中移动的效果了。

  • 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(); 广告item位置 = top, 广告有效移动距离 = recycleView的高度 - 广告item的高度,这一点的实现放在了自定义imageView的setDy方法中。

注意方法中的for循环

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

使用的是firstPosition和lastPosition,也就是//第一个显示的item和//最后一个显示的item。
知乎广告的效果是 广告item 完全显示才会去translate图片,一开始我使用的是first和last,他们正好也是完全显示的意思,for循环少走一两次挺好的;但是在验证效果的时候发现一个尴尬的问题:recycleView滑动速度过快,会出现广告item不能translate至底部或者顶部的情况;日志监视了一下,原因就是滑动过快。在代码中的表现是什么呢?自定义imageView中setDy()方法的rate变化异常。

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

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);方法就可以实现整个效果了。

  • 作者:达峰a

  • https://www.jianshu.com/p/5b3d8ff8ab64

  • 程序员大咖整理发布,转载请联系作者获得授权

【点击成为源码大神】

Android知乎广告效果相关推荐

  1. 知乎广告效果怎么样?有哪些优势呢?

    随着移动互联网的不断发展,在当下流量越来越贵的背景下,知乎平台以其独特的优势,特别失在内容营销方面独树一帜,相比较其它平台有着明显的优势,主要体现在 1.转化率高 因为知乎作为国内领先的互动问答平台, ...

  2. 纯CSS 实现知乎滑动广告效果

    放个好看的头图先 最近的时候刷知乎看到了这种广告效果 emmmmm- 简书把图片转成了黑白,忽视这个细节吧. 效果分析 广告图片在信息流下面一层 在信息流的列表中留一个缝隙,就能看到下面一层的图片了 ...

  3. Android TextView竖直滚动文字广告效果

    项目需要 TextView 单行竖直滚动文字广告效果,很简单的功能在网上找了很多没有想要的效果.开始找到的<android TextView 垂直自动滚动>,歌词效果,对代码处理一下变成单 ...

  4. android TextView向上滚动(模仿滚动文字广告效果)

    android文字向上滚动效果没有自带的控件,这就需要开发者根据算法精确按照时间和坐标来实现TextView控件的向上移动,从网上找过几个框架,基本都会有bug,于是自己写了一个自定义控件,来实现Te ...

  5. android qq广告效果,手机怎么利用腾讯广告做品牌营销?

    原标题:手机怎么利用腾讯广告做品牌营销? 1."换机"成市场主导,手机品牌何去何从 止戈蓝海割据战,开启阵营争夺战 当手机逐渐成为人们生活的必需品,国内手机市场亦日趋饱和.2018 ...

  6. Android之——史上最简单图片轮播广告效果实现

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/48049913 如今的Android开发需求越来越来多,实现效果越来越酷炫,很多An ...

  7. 如何才能不看知乎广告?手机浏览器安装Edge扩展程序教程

    title: 如何才能不看知乎广告?手机浏览器安装Edge扩展程序教程 tags: 知乎 简书 掘金 categories: 极客 知乎App的广告真的是越来越多了,问题与问题之间插广告,每个回答必插 ...

  8. 移动广告效果监测,App推广广告投放归因工具

    Xinstall移动广告实时监控投放效果,精准监测各渠道曝光量.点击量.下载量.转化率等全链路核心数据,提供多平台数据聚合查看功能.报表加密分享功能.防作弊保护功能.帮助移动广告主量化移动端推广活动效 ...

  9. Android图片轮播效果

    适配器 import android.support.v4.view.PagerAdapter; import android.util.Log; import android.view.View; ...

最新文章

  1. python检索字符串_python查找字符串所有子串
  2. 3D场景高级合成技术学习
  3. mac txt 换行符_推荐两款免费的网页代码编辑器(Win和Mac系统)
  4. 【每日一题】 面试题 17.14. 最小K个数
  5. 更改UISwitch大小
  6. 文件分布式存储实现例程
  7. Linux下的各文件夹的作用(转)
  8. 通俗地讲清楚fit_transform()和transform()的区别
  9. airflow mysql_Airflow 使用及原理分析
  10. 使用docker 起容器配置负载均衡(加权)
  11. java导致native非法指令,Java代码引起的NATIVE野指针问题(上)
  12. continue 与break 的区别
  13. linux命令大全(持续更新)
  14. IOS学习之斯坦福大学IOS开发课程笔记(第六课)
  15. Struts2之命名空间与Action的三种创建方式
  16. Autodesk 3DSMax 2012 安装说明
  17. 基于STM32cubemx的STM32F107vct6的代码生成,实验四串口与DMA
  18. Debian 10 开启和停止 ufw防火墙
  19. 浏览器html中加入word,web网页中加载word
  20. 微信支付——委托代扣介绍

热门文章

  1. App 界的一股清流 音视频应有尽有 完全按照 Material design 规范设计的 App
  2. 【opencv-python不规则多边形 ROI提取】
  3. Java 将word文档转成html内容,输出到富文本
  4. linux如何查找下一个
  5. 中国现代书画家——鞠宗霖
  6. 做有责任的企业!拉卡拉获“2018年度责任品牌奖”
  7. 嵌入式设备的switch 以及PHY 芯片调试和选型 (1)
  8. 真正带你搞懂RecyclerView的缓存机制,Android岗
  9. MySQL给表和字段添加注释
  10. 干货 | 区块链的技术世界观