一、先贴上鸿洋大神的网址:
二、所学所获
1.思路:
1、根据View在ListView或RecyclerView中的滑动,根据滑动的dY值显示ImageView的不同部分。
2、ImageView显示不同部分使用画布的translate方法进行。
2.学习知识点:
(1) ImageView中获取图片,使用getDrawable();
(2)从drawable转化成bitmap的方法:
1、获取drawable的宽高,drawable.getIntrinsicWidth 和 drawable.getIntrinsicHeight;
2、新建一个Bitmap,通过Bitmap.create();传入drawable的宽高
3、新建一个Canvas,传入这个Bitmap
4、drawable调用setBound方法,目的是取drawable画在画布上的大小
5、drawble.draw(canvas),这样drawable就画在了bitmap上
(3)获取RecyclerView的高度,需要调用它的LayoutManager.getHeight
(4)画布的偏移方法translate
(5)画布在偏移前调用save方法,然后再偏移translate,最后在restore,这样画布就还原到了save之前的状态!
三、实现方法:
1、自定义一个ImageView继承AppCompatImageView,这样就不用去担心获取不到图片了
2、利用onSizeChange去获取ImageView的宽高,并且给图片设置一个最小的偏移Y值就是ImageView的高度
3、获取图片的尺寸大小,用RectF去获取
这样就得到了:1、图片显示的最小高度(ImageView的高度)
2、Bitmap的尺寸,放在RectF中了
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
minY = h;
mBitmap = drawable2Bitmap();
mBitmapRectf = new RectF(0,0,w,((float)mBitmap.getHeight()) / mBitmap.getWidth() * w);
}
private Bitmap drawable2Bitmap(){
Drawable drawable = getDrawable();
if(drawable == null){
return null;
}
if(drawable instanceof BitmapDrawable){
return ((BitmapDrawable) drawable).getBitmap();
}
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0,0,w,h);
drawable.draw(canvas);
return bitmap;
}
4、对外暴露一个设置偏移量的接口,这里算法有很多,我选择的是获取控件相对于父布局顶部的距离:
public void setDy(float dy, float maxHeight){
//dy为RecyclerView.height - view.getTop,这样往上滑的时候dy越来越大
//从底部往上时,还没有完全显示时,不偏移
if(dy < minY){
mDy = 0;
} else if(dy > maxHeight){ //滑动到RecyclerView顶部了也就不再偏移了(再偏移就出去了!)
mDy = mBitmapRectf.height() - minY;
} else {
//计算从图片完全显示到图片滑到顶部的百分比,这样刚好滑到最上面时,图片偏移到最大
mDy = (dy - minY) / (maxHeight - minY) * (mBitmapRectf.height() - minY);
if(mDy > mBitmapRectf.height() - minY){
mDy = mBitmapRectf.height() - minY;
}
}
invalidate();
}
5、在onDraw方法中偏移:
@Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
if(getDrawable() == null) return;
canvas.save();
canvas.translate(0, -mDy);
canvas.drawBitmap(mBitmap,null,mBitmapRectf,null);
canvas.restore();
}
6、在RecyclerView的滑动监听中监听滑动事件:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int first = mManager.findFirstVisibleItemPosition();
int last = mManager.findLastVisibleItemPosition();
for (int i = first; i <= last ; i++){
View view = mManager.findViewByPosition(i);
AdImageView adImageView = (AdImageView) view.findViewById(R.id.imageView);
if(adImageView.getVisibility() == View.VISIBLE){
adImageView.setDy(mManager.getHeight() - view.getTop(), mManager.getHeight());
}
}
}
});
最后贴上AdImageView的完整代码:
public class AdImageView extends AppCompatImageView{
private int minY;
private Bitmap mBitmap;
private RectF mBitmapRectf;
private float mDy;
public AdImageView(Context context) {
this(context,null);
}
public AdImageView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public AdImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
minY = h;
mBitmap = drawable2Bitmap();
mBitmapRectf = new RectF(0,0,w,((float)mBitmap.getHeight()) / mBitmap.getWidth() * w);
}
private Bitmap drawable2Bitmap(){
Drawable drawable = getDrawable();
if(drawable == null){
return null;
}
if(drawable instanceof BitmapDrawable){
return ((BitmapDrawable) drawable).getBitmap();
}
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0,0,w,h);
drawable.draw(canvas);
return bitmap;
}
public void setDy(float dy, float maxHeight){
//dy为RecyclerView.height - view.getTop,这样往上滑的时候dy越来越大
//从底部往上时,还没有完全显示时,不偏移
if(dy < minY){
mDy = 0;
} else if(dy > maxHeight){ //滑动到RecyclerView顶部了也就不再偏移了(再偏移就出去了!)
mDy = mBitmapRectf.height() - minY;
} else {
//计算从图片完全显示到图片滑到顶部的百分比,这样刚好滑到最上面时,图片偏移到最大
mDy = (dy - minY) / (maxHeight - minY) * (mBitmapRectf.height() - minY);
if(mDy > mBitmapRectf.height() - minY){
mDy = mBitmapRectf.height() - minY;
}
}
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
if(getDrawable() == null) return;
canvas.save();
canvas.translate(0, -mDy);
canvas.drawBitmap(mBitmap,null,mBitmapRectf,null);
canvas.restore();
}
}