您的位置:首页 > 产品设计 > UI/UE

自定义ImageView IM聊天 图片圆角 三角角标

2018-03-29 16:17 316 查看

自定义ImageView IM聊天 图片圆角 三角角标

先看下效果图



矩形圆角大小可自行设置 三角角标可设置左右 上下距离可设置 三角的大小可看源码 着需求而定

这里采用的是BitmapShader,BitmapShader是Shader的子类,Shader在三维软件中我们称之为着色器,所以通俗的理解,Shader的作用是给图像着色或者上色,BitmapShader允许我们载入一张图片来给图像着色,具体不做过多的解释,结尾贴出关于Shader的具体使用的文章

所以其实根据上面对于BitmapShader的描述,其实就可以对圆角ImageView有一定的思路了吧,画一个圆角矩形,然后把本来画上去的图像着色到圆角矩形上,这样就实现了圆角的ImageView

圆角核心代码

//绘制圆角
mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
float scale = 1.0f;
if (!(bitmap.getWidth() == (getWidth() - cornerMarkWidth) && bitmap.getHeight() == getHeight())) {
// 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值;
if (AngleLocation == 1 || AngleLocation == 2) {
scale = Math.max((getWidth() - cornerMarkWidth) * 1.0f / bitmap.getWidth(),
getHeight() * 1.0f / bitmap.getHeight());
} else {
scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(),
getHeight() * 1.0f / bitmap.getHeight());
}
}
// shader的变换矩阵,我们这里主要用于放大或者缩小
mMatrix.setScale(scale, scale);
// 设置变换矩阵
mBitmapShader.setLocalMatrix(mMatrix);
// 设置shader
rectF.left = getPaddingLeft();
rectF.right = getWidth() - getPaddingRight();
if (AngleLocation == 1) {//画在左边
rectF.left = getPaddingLeft() + cornerMarkWidth;
} else if (AngleLocation == 2) {//右边
rectF.right = getWidth() - getPaddingRight() - cornerMarkWidth;
}
rectF.top = getPaddingTop();
rectF.bottom = getHeight() - getPaddingBottom();
mPaint.setShader(mBitmapShader);
canvas.drawRoundRect(rectF, circleRadius, circleRadius,
mPaint);


下面就是画三角 分在左边和右边 代码如下

//绘制凸出三角
if (AngleLocation == 2) {
path.moveTo(rectF.right, rectF.top + mAnglePaddingTop);
path.lineTo(rectF.right + cornerMarkWidth, rectF.top + mAnglePaddingTop + cornerMarkHeight / 2);
path.lineTo(rectF.right, rectF.top + mAnglePaddingTop + cornerMarkHeight);
path.lineTo(rectF.right, rectF.top + mAnglePaddingTop);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
canvas.drawPath(path, mPaint);
} else if (AngleLocation == 1) {
path.moveTo(rectF.left, rectF.top + mAnglePaddingTop);
path.lineTo(rectF.left - cornerMarkWidth, rectF.top + mAnglePaddingTop + cornerMarkHeight / 2);
path.lineTo(rectF.left, rectF.top + mAnglePaddingTop + cornerMarkHeight);
path.lineTo(rectF.left, rectF.top + mAnglePaddingTop);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
canvas.drawPath(path, mPaint);
}


这是自定义的属性 也可以自己添加三角的高度 和宽度

<declare-styleable name="IMImageView">
<!--圆角半径-->
<attr name="circleRadius" format="dimension" />
<!--左边三角 还是右边三角-->
<attr name="AngleLocation"  >
<enum name="Left" value="1" />
<enum name="Right" value="2" />
<enum name="Gone" value="3" />
</attr>
<!--三角距离顶部位置-->
<attr name="anglePaddingTop" format="dimension" />
</declare-styleable>


下面是全部的代码

package xxx.xxxx.view.im;

package xxx.xxxx.view.im;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;

import xxxx.xxxx.xxxx.R;
import xxxx.xxxx.xxxx.view.ImageView;

/**
* Created by ZhangYan on 2018/3/28.
*/

public class IMImageView extends ImageView {
private final Context context;
private float mCircleRadius;
// 1 左边 2 右边 3 隐藏
private int AngleLocation;
//三角距离自身顶部的距离
private float mAnglePaddingTop;
private Paint mPaint;
private BitmapShader mBitmapShader;
private Matrix mMatrix;
private RectF mRectF;
//角标的宽度
private int mCornerMarkWidth = 20;
//角标的高度
private int mCornerMarkHeight = 40;
private Path mPath;

public IMImageView(Context context) {
this(context, null);
}

public IMImageView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public IMImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init(attrs);
}

private void init(AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.IMImageView);
mCircleRadius = typedArray.getDimensionPixelOffset(R.styleable.IMImageView_circleRadius, 10);
AngleLocation = typedArray.getInt(R.styleable.IMImageView_AngleLocation, 1);
mAnglePaddingTop = typedArray.getDimension(R.styleable.IMImageView_anglePaddingTop, 10f);
typedArray.recycle();
mMatrix = new Matrix();
mPaint = new Paint();
mRectF = new RectF();
mPaint.setAntiAlias(true);
mPath = new Path();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (AngleLocation == 1 || AngleLocation == 2) {
int size = MeasureSpec.getSize(widthMeasureSpec);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(size + mCornerMarkWidth, MeasureSpec.getMode(widthMeasureSpec));
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}

@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
Bitmap bitmap = drawableToBitmap(getDrawable());
if (bitmap == null) {
return;
}

//绘制圆角
mBitmapShader = new BitmapShader
4000
(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
float scale = 1.0f;
if (!(bitmap.getWidth() == (getWidth() - mCornerMarkWidth) && bitmap.getHeight() == getHeight())) {
// 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值;
if (AngleLocation == 1 || AngleLocation == 2) {
scale = Math.max((getWidth() - mCornerMarkWidth) * 1.0f / bitmap.getWidth(),
getHeight() * 1.0f / bitmap.getHeight());
} else {
scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(),
getHeight() * 1.0f / bitmap.getHeight());
}
}
// shader的变换矩阵,我们这里主要用于放大或者缩小
mMatrix.setScale(scale, scale);
// 设置变换矩阵
mBitmapShader.setLocalMatrix(mMatrix);
// 设置shader
mRectF.left = getPaddingLeft();
mRectF.right = getWidth() - getPaddingRight();
if (AngleLocation == 1) {//画在左边
mRectF.left = getPaddingLeft() + mCornerMarkWidth;
} else if (AngleLocation == 2) {//右边
mRectF.right = getWidth() - getPaddingRight() - mCornerMarkWidth;
}
mRectF.top = getPaddingTop();
mRectF.bottom = getHeight() - getPaddingBottom();
mPaint.setShader(mBitmapShader);
canvas.drawRoundRect(mRectF, mCircleRadius, mCircleRadius,
mPaint);
//绘制凸出三角
if (AngleLocation == 2) {
mPath.moveTo(mRectF.right, mRectF.top + mAnglePaddingTop);
mPath.lineTo(mRectF.right + mCornerMarkWidth, mRectF.top + mAnglePaddingTop + mCornerMarkHeight / 2);
mPath.lineTo(mRectF.right, mRectF.top + mAnglePaddingTop + mCornerMarkHeight);
mPath.lineTo(mRectF.right, mRectF.top + mAnglePaddingTop);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
canvas.drawPath(mPath, mPaint);
} else if (AngleLocation == 1) {
mPath.moveTo(mRectF.left, mRectF.top + mAnglePaddingTop);
mPath.lineTo(mRectF.left - mCornerMarkWidth, mRectF.top + mAnglePaddingTop + mCornerMarkHeight / 2);
mPath.lineTo(mRectF.left, mRectF.top + mAnglePaddingTop + mCornerMarkHeight);
mPath.lineTo(mRectF.left, mRectF.top + mAnglePaddingTop);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
canvas.drawPath(mPath, mPaint);
}

}

private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
return null;
} else if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else {
try {
Bitmap bitmap;
if (drawable instanceof ColorDrawable) {
bitmap = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}

Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (Exception var4) {
var4.printStackTrace();
return null;
}
}
}
}


使用

<xxxx.xxxx.view.im.IMImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:anglePaddingTop="@dimen/x20"
app:AngleLocation="Right"
app:circleRadius="@dimen/x10"
android:src="@drawable/img_default_page"
android:scaleType="fitXY"
/>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息