Android自定义imageview实现的视频和图片的展示

本文介绍了一种自定义ImageView的方法,用于在Android应用中优雅地展示图片和视频。通过继承AppCompatImageView并重写onDraw和onMeasure方法,实现了图片按比例缩放及视频播放按钮的绘制,提升了用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

    项目中用到了im即时通讯功能,需要在聊天中展示图片和视频,对于图片和视频,都可以用glide进行加载,如果是图片,则直接展示,如果是视频,展示的时候在表面绘制一个播放按钮,如果采用原生的imageview,效果是这样的:

                                             (蓝色底代表imageview控件的大小,黑线用来分割三个imageview)

可以看到,这样的布局看起来非常别扭,如果是视频还要在上面绘制一个播放按钮。为了让布局更加优美,因此采用了自定义的imageview来实现这个功能,先放上效果图:

实现原理:

1. 继承 AppCompatImageView,重写onDraw方法,判断是图片还是视频,如果是视频,直接展示,如果是图片,那么在图片上面绘制一个播放按钮。

2. 图片绘制完毕后,重写onMeasure方法,根据图片实际大小,参考layout_width,layout_height进行计算,使图片等比缩放,重新计算ImageView的大小,最后调用setMeasuredDimension保存

 

核心代码如下:

package com.jaden.imageviewplay;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.LinearLayout;

/**
 * Created Date: 2018/12/12
 * Description: 实现带播放按钮的imageview
 */
public class ImageViewPlay extends AppCompatImageView {
    public static final int TYPE_IMAGE = 1;
    public static final int TYPE_VIDEO = 2;

    private int type = TYPE_IMAGE;
    private int playBtnRes = R.drawable.play_btn;
    private Bitmap playBtnBitmap;



    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Rect src = new Rect();
    RectF dest = new RectF();

    public ImageViewPlay(Context context) {
        super(context);
    }

    public ImageViewPlay(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ImageViewPlay);
        playBtnRes = ta.getResourceId(R.styleable.ImageViewPlay_ivp_play_btn_res, playBtnRes);
        playBtnBitmap = BitmapFactory.decodeResource(getResources(), playBtnRes);
    }

    public ImageViewPlay(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
    *description: 设置图片类型,如果是TYPE_IMAGE,显示图片,如果是TYPE_VIDEO,显示图片,并且在图片正中心绘制一个播放按钮
    **/
    public void setType(int type){
        this.type = type;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(type == TYPE_VIDEO){ //如果是TYPE_VIDEO,显示图片,并且在图片正中心绘制一个播放按钮
            Drawable drawable = getDrawable();
            if (drawable != null) {
                int viewW = drawable.getIntrinsicWidth(); //获取图片的宽
                int viewH = drawable.getIntrinsicHeight(); //获取图片的高
                int btnW = playBtnBitmap.getWidth(); //获取播放按钮的宽
                int btnH = playBtnBitmap.getHeight(); //获取播放按钮的高
                float[] result = measureViewSize(viewW, viewH);
                if(result[0] > 0 && result[1] > 0){ //先根据比例缩放图标,确保绘制的时候再次回归缩放,保持播放的图片大小不变
                    btnW *= (viewW / result[0]);
                    btnH *= (viewH / result[1]);
                }
                float left = (viewW - btnW) / 2.0f;
                float top = (viewH - btnH) / 2.0f;
                src.set(0, 0, btnW, btnH);
                dest.set(left, top, left+btnW, top+btnH);
                canvas.save();
                canvas.concat(getImageMatrix());
                canvas.drawBitmap(playBtnBitmap, src, dest, mPaint);
                canvas.restore();
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Drawable drawable = getDrawable();
        if (drawable != null) { //重新计算view
            int viewW = drawable.getIntrinsicWidth();
            int viewH = drawable.getIntrinsicHeight();
            if(viewW > 0 && viewH > 0) {
                float[] result = measureViewSize(viewW, viewH);
                setMeasuredDimension((int)result[0], (int) result[1]);
            }
        }
    }

    /**
    *description: 根据传入的图片宽高,计算出最终的imageview的宽高,长宽等比缩放
    **/
    private float[] measureViewSize(int w, int h) {
        ViewGroup.LayoutParams lp = getLayoutParams();
        float maxW = lp.width;
        float maxH = lp.height;
        float showWidth = w;
        float showHeight = h;
        float scale = (1.0f * maxW) / maxH;
        float s = 1.0f * w / h;
        if (w < maxW && h < maxH) { //不进行缩放
            showWidth = w;
            showHeight = h;
        } else if (s > scale) { //宽取最大,高进行缩小
            showWidth = maxW;
            showHeight = (int) (h * (showWidth * 1.0 / w));
        } else if (s <= scale) {//高取最大,宽进行缩小
            showHeight = maxH;
            showWidth = (int) (w * (showHeight * 1.0 / h));
        }
        float[] result = new float[2];
        result[0] = showWidth;
        result[1] = showHeight;
        return result;
    }
}

完整项目见GitHub

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值