美文网首页
仿知乎广告

仿知乎广告

作者: 陈沉成染 | 来源:发表于2019-05-25 16:37 被阅读0次

    仿知乎的广告栏学习

    Screenshot_2019-05-25-16-08-00.png Screenshot_2019-05-25-16-08-04.png Screenshot_2019-05-25-16-08-07.png Screenshot_2019-05-25-16-32-09.png

    思路
    自定义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 为了理清思路 我把一些参数显示出来

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        tools:context=".donghua.Rv_advertisement">
        <data>
    
        </data>
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
    
        <TextView
            android:id="@+id/text_dy"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="10sp"
            android:text="0"
            android:gravity="center"/>
    
        <TextView
            android:id="@+id/text_mdy"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="10sp"
            android:text="0"
            android:gravity="center"/>
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_advertisement"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        </android.support.v7.widget.RecyclerView>
    </LinearLayout>
    </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<String> 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

    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="200dp">
    
        <com.chen.testapplciation.donghua.AdimageView
            android:id="@+id/img_av"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/nav_bc_0"
            android:scaleType="centerCrop"
            />
    </FrameLayout>
    
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="100dp">
    
        <TextView
            android:layout_margin="12dp"
            android:id="@+id/id_tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="这是title"
            android:textSize="16dp"
            android:textStyle="bold" />
    
        <TextView
            android:id="@+id/id_tv_desc"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/id_tv_title"
            android:layout_marginLeft="12dp"
            android:layout_marginRight="12dp"
            android:layout_marginBottom="12dp"
            android:text="这是描述" />
    
    </RelativeLayout>
    
    

    其中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任意的一部分内容

    相关文章

      网友评论

          本文标题:仿知乎广告

          本文链接:https://www.haomeiwen.com/subject/yyuazqtx.html