仿知乎的广告栏学习
思路
自定义View 继承自imgView
然后通过canvas 对图片进行局部绘制
进行局部的绘制就需要获取itemview的位置
Activity的代码
import android.databinding.DataBindingUtil;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import com.chen.testapplciation.R;
import com.chen.testapplciation.databinding.ActivityRvAdvertisementBinding;
public class Rv_advertisement extends AppCompatActivity {
ActivityRvAdvertisementBinding binding;
LinearLayoutManager mLinearLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLinearLayoutManager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
binding = DataBindingUtil.setContentView(this,R.layout.activity_rv_advertisement);
binding.rvAdvertisement.setAdapter(new MyAdapter());
binding.rvAdvertisement.setLayoutManager(mLinearLayoutManager);
binding.rvAdvertisement.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int fpos = mLinearLayoutManager.findFirstVisibleItemPosition();
int lpos =mLinearLayoutManager.findLastVisibleItemPosition();
for (int i = fpos; i < lpos; i++) {
View view = mLinearLayoutManager.findViewByPosition(i);
AdimageView adimageView = view.findViewById(R.id.img_av);
if (adimageView != null){
adimageView.setTextView(binding.textMdy);
int dy1 = mLinearLayoutManager.getHeight() - view.getTop();
binding.textDy.setText("itemview顶部到底部的高"+dy1+" \n" + "recyclerview=" +mLinearLayoutManager.getHeight() + " \n"+"图片item到顶部的距离"+view.getTop());
adimageView.setDy(dy1);
}
}
}
});
}
}
我直接用的 databinding
来获取Recycleview
layout 为了理清思路 我把一些参数显示出来
adapter
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.chen.testapplciation.R;
import java.util.ArrayList;
public class MyAdapter extends RecyclerView.Adapter {
ArrayList data = new ArrayList<>();
@Override
public int getItemViewType(int position) {
if (position%10 ==0){
return 1;
}
return 0;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
if (i ==0){
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.rv_item_textview,viewGroup,false);
return new ViewHolder(view);
}else {
View view =LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.rv_item_advertisement,viewGroup,false);
return new AdtViewHolder(view);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
AdimageView adimageView = viewHolder.itemView.findViewById(R.id.img_av);
if (adimageView != null){
adimageView.setnotvisible();
}
}
@Override
public int getItemCount() {
return 100;
}
static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
}
}
static class AdtViewHolder extends RecyclerView.ViewHolder {
public AdtViewHolder(@NonNull View itemView) {
super(itemView);
}
}
}
adapter 就两个Viewholder
一种显示图片
一种显示文字
onBindViewHolder
因为recyclerview
复用viewholder
。所以一定 要初始化一下viewholder
俩个viewholder的layout
其中adimgview 就是自定义的view
Adimgview代码
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;
public class AdimageView extends AppCompatImageView {
private RectF mBitmapRectF;
private Bitmap mBitmap;
private TextView mTextView;
private int mMinDy = 0;
public void setTextView(TextView textView) {
mTextView = textView;
}
public AdimageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
int showwidth;
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
showwidth = w;
mMinDy = h;
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
mBitmap = drawableToBitamp(drawable);
mBitmapRectF = new RectF(0, 0, w, mBitmap.getHeight() * w / mBitmap.getWidth());
}
private Bitmap drawableToBitamp(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) drawable;
return bd.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;
}
private int mDy;
public void setDy(int dy) {
if (getDrawable() == null) {
return;
}
mDy = dy - mMinDy;
if (mDy <= 0) {
mDy = 0;
}
if (mDy > mBitmapRectF.height() - mMinDy) {
mDy = (int) (mBitmapRectF.height() - mMinDy);
}
mTextView.setText("绘制偏移量"+mDy+"\n "+"imgageview显示的高度=" +mMinDy +"\n"+" 图片的缩小后的高度"+height );
invalidate();
}
int bitmapheight ;
int bitmapwidth ;
int height =0;
public void setnotvisible() {
mDy =0;
}
@Override
protected void onDraw(Canvas canvas) {
if (mBitmap == null) {
return;
}
bitmapheight = mBitmap.getHeight();
bitmapwidth= mBitmap.getWidth();
height = bitmapheight *showwidth/bitmapwidth;
canvas.save();
canvas.translate(0,-mDy);
canvas.drawBitmap(mBitmap, null, mBitmapRectF, null);
canvas.restore();
}
}
再梳理一下过程
在Activity中给recyclerview的LinearLayoutManager 绑定一个监听(onScroollListener()
),
监听滚动
找到可显示的item中的 有 AdimgView的item,然后recyclerview的高度减去itemview顶部的高度得到
itemview顶部到底部的高度,
将次高度传入adimgview中
这个高度减去adimgview自身的高度。就是canvas 作图的偏移量
然后通过这个偏移量canva 画出bitmap任意的一部分内容