Android自定View:可以设置宽高比例和圆角图片的ImageView

昨天有个朋友让我折腾一个这样的ImageView,
他说“我想要一个既可以圆角又可以设置宽高比的imageview”
所以我就折腾了下。

大概是这样的
效果图

1.attributes

这里说一下:如果参考边是:宽,那么你高度的设置其实是没有效果的
因为,代码里面 我直接把高度重新计算了

<declare-styleable name="SakuraImage">
   <!--参考边-->
   <attr name="refer" format="enum">
        <enum name="" value="1"/>
        <enum name="" value="2"/>
    </attr>
    <!--长宽比例-->
    <attr name="ratio" format="float"/>
    <!--圆弧度-->
    <attr name="radius" format="float"/>
</declare-styleable>

2.xml

<mos.kos.cache.widget.SakuraImage
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:scaleType="centerCrop"
    android:src="@drawable/image"
    sakura:radius="20"
    sakura:ratio="1"
    sakura:refer=""/>

3.Code

3.1.长宽按比例设置

这一步主要是在onMeasure里面完成的
具体的看下面的代码和代码里的注释

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (ratio > 0) {
        //参考边为:宽
        if (referEdge == 1) {
            ratioW = MeasureSpec.getSize(widthMeasureSpec);
            ratioH = (int) (ratioW * ratio);//根据宽来计算高
		//参考边为:高
        } else {
            ratioH = MeasureSpec.getSize(heightMeasureSpec);
            ratioW = (int) (ratioH * ratio);//根据高来计算宽
        }
        //丢给父类处理
        super.onMeasure(MeasureSpec.makeMeasureSpec(ratioW, MeasureSpec.EXACTLY),
            MeasureSpec.makeMeasureSpec(ratioH, MeasureSpec.EXACTLY));
    } else {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    Logger.v("宽高1:ratioW=" + ratioW + ",ratioH=" + ratioH);
}
3.2.设置带圆弧的图片

这里稍微麻烦一点,不过主要还是在onDraw里面处理的

  • 1.先找到图片的锚点
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    rectF.top = 0;
    rectF.left = 0;
    rectF.right = getWidth(); // 宽度
    rectF.bottom = getHeight(); // 高度
    setBitmapShader();
}
  • 2.关键的一步:设置图片的透明区域Shader

下面是一段伪代码,把这一块的关键点都整到一起的

//先整一个画笔
Paint bmpPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
bmpPaint.setStyle(Paint.Style.FILL);
bmpPaint.setAntiAlias(true);
        
//这里的bmp是搞到的Bitmap图片
BitmapShader bmpShader = new BitmapShader(bmp, 
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//bmpShader 就是圆弧所裁剪调的透明区域
bmpPaint.setShader(bmpShader);

//这个矩阵主要是对裁剪后的图片做缩放、还有位置的处理
matrix.set(null);//设为默认值,固定为CENTER_CROP
// 缩放
float scale = Math.max(getWidth() * 1f / bmp.getWidth(), getHeight() * 1f / bmp.getHeight());
// 居中
float dx = (getWidth() - bmp.getWidth() * scale) / 2;
float dy = (getHeight() - bmp.getHeight() * scale) / 2;
matrix.setScale(scale, scale);
matrix.postTranslate(dx, dy);
bmpShader.setLocalMatrix(matrix);
invalidate();//刷新
  • 3.最后绘制

这里我踩了个坑,记录一下:
绘制的时候最好用Canvas 的路径绘制canvas.drawPath(),就是第1步打的那4个锚点,这样也是最简单的

我之前尝试过直接用画布来绘制矩形canvas.drawRoundRect(或者绘制图形canvas.drawBitmap(
虽然也成功了,但是效果不怎么理想。

@Override
protected void onDraw(Canvas canvas) {
    if (bmp != null) {
        path.reset();
        path.addRoundRect(rectF, radius, radius, Path.Direction.CW);
        canvas.drawPath(path, bmpPaint);
    }
}

最后丢再几张效果图

  • 1.宽高比为1的时候
    这里写图片描述
  • 2.这里是以宽为参考边
    这里写图片描述
  • 3.这里是以高为参考边
    这里写图片描述

源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值