自定义View实战六:实现圆形、圆角图片

  • @return

*/

@Nullable

@Override

protected Parcelable onSaveInstanceState() {

Bundle bundle = new Bundle();

bundle.putParcelable(STATE_INSTANCE, super.onSaveInstanceState());

bundle.putInt(STATE_TYPE, mType);

bundle.putInt(STATE_BORDER_RADIUS, mBorderRadius);

return bundle;

}

/**

  • 状态恢复

  • @param state

*/

@Override

protected void onRestoreInstanceState(Parcelable state) {

if (state instanceof Bundle) {

Bundle bundle = (Bundle) state;

super.onRestoreInstanceState(bundle.getParcelable(STATE_INSTANCE));

this.mType = bundle.getInt(STATE_TYPE);

this.mBorderRadius = bundle.getInt(STATE_BORDER_RADIUS);

} else {

super.onRestoreInstanceState(state);

}

}

/**

  • 对外公开的方法:动态修改圆角大小

*/

public void setBorderRadius(int borderRadius) {

int pxVal = dp2px(borderRadius);

if (this.mBorderRadius != pxVal) {

this.mBorderRadius = pxVal;

invalidate();

}

}

/**

  • 对外公开的方法:动态修改type

*/

public void setType(int type) {

if (this.mType != type) {

this.mType = type;

if (this.mType != TYPE_ROUND && this.mType != TYPE_CIRCLE) {

this.mType = TYPE_CIRCLE;

}

requestLayout();

}

}

/**

  • 对外公开的方法:改变type

*/

public void changeType() {

if (this.mType == TYPE_ROUND) {

this.mType = TYPE_CIRCLE;

} else if (this.mType == TYPE_CIRCLE) {

this.mType = TYPE_ROUND;

}

requestLayout();

}

public int dp2px(int dpVal) {

return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,

getResources().getDisplayMetrics());

}

/**

  • 初始化BitmapShader

*/

private void setUpShader() {

Drawable drawable = getDrawable();

if (drawable == null) return;

Bitmap bitmap = drawableToBitmap(drawable);

//将bitmap作为着色器,就是在指定区域绘制bitmap

//Shader在三维软件中我们称之为着色器,其作用嘛就像它的名字一样是来给图像着色的或者更通俗的说法是上色

mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

float scale = 1.0f;

if (mType == TYPE_CIRCLE) {

//拿到bitmap宽或高的最小值

int bitmapSize = Math.min(bitmap.getWidth(), bitmap.getHeight());

scale = mWidth * 1.0f / bitmapSize;

} else if (mType == TYPE_ROUND) {

//如果图片的宽或高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们

// view的宽高,所以我们这里取大值

scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(), getHeight() * 1.0f / bitmap.getHeight());

}

//shader的变换矩阵,我们这里主要用于放大或缩小

mMatrix.setScale(scale, scale);

//设置变换矩阵

mBitmapShader.setLocalMatrix(mMatrix);

//设置shader

mBitmapPaint.setShader(mBitmapShader);

}

/**

  • drawable转bitmap

*/

private Bitmap drawableToBitmap(Drawable drawable) {

if (drawable instanceof BitmapDrawable) {

BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;

return bitmapDrawable.getBitmap();

}

int width = drawable.getIntrinsicWidth();

int height = drawable.getIntrinsicHeight();

Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(bitmap);

drawable.setBounds(0, 0, width, height);

drawable.draw(canvas);

return bitmap;

}

}

1.2、RoundImageViewActivity.java


public class RoundImageViewActivity extends AppCompatActivity {

@BindView(R.id.round_image_view01)

RoundImageView roundImageView01;

@BindView(R.id.round_image_view02)

RoundImageView roundImageView02;

@BindView(R.id.round_image_view03)

RoundImageView roundImageView03;

@BindView(R.id.round_image_view04)

RoundImageView roundImageView04;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_round_image_view);

ButterKnife.bind(this);

}

@OnClick({R.id.round_image_view01, R.id.round_image_view02, R.id.round_image_view03, R.id.round_image_view04})

public void onViewClicked(View view) {

switch (view.getId()) {

case R.id.round_image_view01:

roundImageView01.changeType();

break;

case R.id.round_image_view02:

roundImageView02.setType(RoundImageView.TYPE_CIRCLE);

break;

case R.id.round_image_view03:

break;

case R.id.round_image_view04:

roundImageView04.setBorderRadius(90);

break;

}

}

}

1.3、activity_round_image_view.xml


<ScrollView xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:app=“http://schemas.android.com/apk/res-auto”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:background=“@color/light_blue_2e”

<LinearLayout

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:orientation=“vertical”>

<com.gs.common3.aView.customView.roundIV.RoundImageView

android:id=“@+id/round_image_view01”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:src=“@mipmap/keji01”/>

<com.gs.common3.aView.customView.roundIV.RoundImageView

android:id=“@+id/round_image_view02”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_marginTop=“10dp”

android:src=“@mipmap/keji01”

app:borderRadius=“60dp”

app:type=“round”/>

<com.gs.common3.aView.customView.roundIV.RoundImageView

android:id=“@+id/round_image_view03”

android:layout_width=“200dp”

android:layout_height=“200dp”

android:layout_margin=“10dp”

android:src=“@mipmap/keji02”/>

<com.gs.common3.aView.customView.roundIV.RoundImageView

android:id=“@+id/round_image_view04”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_margin=“10dp”

android:src=“@mipmap/keji02”

app:borderRadius=“20dp”

app:type=“round”/>

2、文章二:

======

按照文章二编码:

效果如下:有问题。

2.1、RoundIVByXfermode.java


public class RoundIVByXfermode extends AppCompatImageView {

private Paint mPaint;

private Xfermode mXfermode;

private Bitmap mMaskBitmap;

private WeakReference mWeakBitmap;

//图片的类型,圆形or圆角

private int type;

public static final int TYPE_CIRCLE = 0;

public static final int TYPE_ROUND = 1;

//圆角大小的默认值

private static final int BORDER_RADIUS_DEFAULT = 10;

//圆角的大小

private int mBorderRadius;

public RoundIVByXfermode(Context context) {

this(context, null);

mPaint = new Paint();

mPaint.setAntiAlias(true);

}

public RoundIVByXfermode(Context context, AttributeSet attrs) {

super(context, attrs);

mPaint = new Paint();

mPaint.setAntiAlias(true);

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundIVByXfermode);

mBorderRadius = (int) typedArray.getDimension(R.styleable.RoundIVByXfermode_borderRadius,

TypedValue.applyDimension(

TypedValue.COMPLEX_UNIT_DIP, BORDER_RADIUS_DEFAULT,

getResources().getDisplayMetrics()));//默认为10dp

type = typedArray.getInt(R.styleable.RoundIVByXfermode_type, TYPE_CIRCLE);//默认为circle

typedArray.recycle();

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//如果类型是圆形,则强制改变view的宽高一致,以最小值为准

if (type == TYPE_CIRCLE) {

int width = Math.min(getMeasuredWidth(), getMeasuredHeight());

setMeasuredDimension(width, width);

}

}

@SuppressLint(“DrawAllocation”)

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//在缓存中取出bitmap

Bitmap bitmap = mWeakBitmap == null ? null : mWeakBitmap.get();

if (bitmap == null || bitmap.isRecycled()) {

//拿到drawable

Drawable drawable = getDrawable();

//获取drawable的宽和高

int dWidth = drawable.getIntrinsicWidth();

int dHeight = drawable.getIntrinsicHeight();

if (drawable != null) {

//创建bitmap

bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);

float scale = 1.0f;

//创建画布

Canvas drawCanvas = new Canvas(bitmap);

//按照bitmap的宽高,以及view的宽高,计算缩放比例;因为设置的src宽高比例可能和

// imageview的宽高比例不同,这里我们不希望图片失真;

if (type == TYPE_ROUND) {

// 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,

// 一定要大于我们view的宽高;所以我们这里取大值;

scale = Math.max(getWidth() * 1.0f / dWidth, getHeight() * 1.0f / dHeight);

} else {

scale = getWidth() * 1.0f / Math.min(dWidth, dHeight);

}

//根据缩放比例,设置bounds,相当于缩放图片了

drawable.setBounds(0, 0, (int) scale * dWidth,

(int) scale * dHeight);

drawable.draw(drawCanvas);

if (mMaskBitmap == null || mMaskBitmap.isRecycled()) {

mMaskBitmap = getBitmap();

}

//draw bitmap

mPaint.reset();

mPaint.setFilterBitmap(false);

mPaint.setXfermode(mXfermode);

//绘制形状

drawCanvas.drawBitmap(mMaskBitmap, 0, 0, mPaint);

mPaint.setXfermode(null);

//将准备好的bitmap绘制出来

canvas.drawBitmap(bitmap, 0, 0, null);

//bitmap缓存起来,避免每次调用onDraw,分配内存

mWeakBitmap = new WeakReference(bitmap);

}

}

//如果bitmap还在,直接绘制即可

if (bitmap != null) {

mPaint.setXfermode(null);

canvas.drawBitmap(bitmap, 0.0f, 0.0f, mPaint);

}

}

/**

  • 主要是因为我们缓存了,当调用invalidate时,将缓存清除。

*/

@Override

public void invalidate() {

mWeakBitmap = null;

if (mMaskBitmap != null) {

mMaskBitmap.recycle();

mMaskBitmap = null;

}

super.invalidate();

}

/**

  • 绘制形状

*/

private Bitmap getBitmap() {

Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(bitmap);

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

paint.setColor(Color.BLACK);

if (type == TYPE_ROUND) {

canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()),

mBorderRadius, mBorderRadius, paint);

} else {

canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2, paint);

}

return bitmap;

}

}

2.2、activity_round_i_by_xfer.xml


<?xml version="1.0" encoding="utf-8"?>

<ScrollView xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:app=“http://schemas.android.com/apk/res-auto”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”>

<LinearLayout

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:orientation=“vertical”>

<com.gs.common3.aView.customView.roundIV.RoundIVByXfermode

android:id=“@+id/riv01”

android:layout_width=“130dp”

android:layout_height=“130dp”

android:layout_margin=“10dp”

android:src=“@mipmap/keji01” />

<com.gs.common3.aView.customView.roundIV.RoundIVByXfermode

android:id=“@+id/riv02”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_margin=“10dp”

android:src=“@mipmap/keji01”

app:borderRadius=“30dp” />

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值