本文主要包括以下内容:

使用Xfermode设置圆角图片

使用BitmapShader设置圆角图片

滑动旋转缩放的bimp图片

图片颜色处理(滑动)

图片 + 文字

其中1,2是两种不同方式处理图片圆角的情况。3,是通过Matrix进行图片缩放,旋转等。4,是通过Matrix操作图片的处理,包括去饱和,四角黑影,中心突出等。5,图片加文字组合显示。

如果暂时感觉这些看不懂:

先看看这两篇:

1、使用Xfermode设置圆角图片主要代码

package com.example.customimage.view;

import com.example.customimage.R;

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.Bitmap;

import android.graphics.Bitmap.Config;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Paint;

import android.graphics.PorterDuff;

import android.graphics.PorterDuffXfermode;

import android.graphics.RectF;

import android.util.AttributeSet;

import android.util.Log;

import android.util.TypedValue;

import android.view.View;

/**

* 自定义View,实现圆角,圆形等效果

*/

public class XfermodeImageView extends View

{

//类型

private int type;

private static final int TYPE_CIRCLE = 0; //圆形

private static final int TYPE_RECT = 1; //矩形圆角

//原始图片

private Bitmap mSrc;

//矩形圆角的幅度

private int mRadius;

//控件的宽度

private int mWidth;

// 控件的高度

private int mHeight;

public XfermodeImageView(Context context, AttributeSet attrs)

{

this(context, attrs, 0);

}

public XfermodeImageView(Context context)

{

this(context, null);

}

/**

* 初始化一些自定义的参数

*

* @param context

* @param attrs

* @param defStyle

*/

public XfermodeImageView(Context context, AttributeSet attrs, int defStyle)

{

super(context, attrs, defStyle);

TypedArray a = context.getTheme().obtainStyledAttributes(attrs,

R.styleable.XfermodeImageView, defStyle, 0);

int n = a.getIndexCount();

for (int i = 0; i < n; i++)

{

int attr = a.getIndex(i);

switch (attr)

{

//原始图片,在布局里面获取

case R.styleable.XfermodeImageView_src:

mSrc = BitmapFactory.decodeResource(getResources(),

a.getResourceId(attr, 0));

break;

//类型属性选择

case R.styleable.XfermodeImageView_type:

//自定义类型属性,0是圆形,1是矩形圆角

type = a.getInt(attr, 0);// 默认为Circle

break;

//矩形圆角幅度的获取,默认是10dp

case R.styleable.XfermodeImageView_borderRadius:

mRadius = a.getDimensionPixelSize(attr, (int) TypedValue

.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f,

getResources().getDisplayMetrics()));

Log.i("Show", String.valueOf(mRadius));

break;

}

}

a.recycle();

}

/**

* 计算控件的高度和宽度

*/

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

{

// 设置宽度

int specMode = MeasureSpec.getMode(widthMeasureSpec);

int specSize = MeasureSpec.getSize(widthMeasureSpec);

//match_parent或者设置的精确值获取

//MeasureSpec.EXACTLY

if (specMode == MeasureSpec.EXACTLY)

{

mWidth = specSize;

}

else

{

// 由图片决定的宽

//getPaddingLeft(),getPaddingRight()这两个值是控件属性的向内偏移的距离值,所以的一起计算

//区别于layout_marginLeft,两个控件的左间距值设置

int desireByImg = getPaddingLeft() + getPaddingRight()

+ mSrc.getWidth();

// wrap_content

if (specMode == MeasureSpec.AT_MOST)

{

//所以最小的值,宽度的话是左右内偏移距离之和

mWidth = Math.min(desireByImg, specSize);

} else

mWidth = desireByImg;

}

// 设置高度,部分解释同上

specMode = MeasureSpec.getMode(heightMeasureSpec);

specSize = MeasureSpec.getSize(heightMeasureSpec);

//match_parent或者设置的精确值获取

//MeasureSpec.EXACTLY

if (specMode == MeasureSpec.EXACTLY)

{

mHeight = specSize;

} else

{

int desire = getPaddingTop() + getPaddingBottom()

+ mSrc.getHeight();

// wrap_content

if (specMode == MeasureSpec.AT_MOST)

{

mHeight = Math.min(desire, specSize);

} else

mHeight = desire;

}

//计算好的宽度以及高度是值,设置进去

setMeasuredDimension(mWidth, mHeight);

}

/**

* 绘制image控件

*/

@Override

protected void onDraw(Canvas canvas)

{

switch (type)

{

// 如果是TYPE_CIRCLE绘制圆形

case TYPE_CIRCLE:

//圆形宽度和高度应该一致的,所以也要比较一下大小,取小的值

int min = Math.min(mWidth, mHeight);

// 圆形宽度和高度如果不一致,按小的值进行压缩

mSrc = Bitmap.createScaledBitmap(mSrc, min, min, false);

//绘制圆形

canvas.drawBitmap(createCircleImage(mSrc, min), 0, 0, null);

break;

case TYPE_RECT:

canvas.drawBitmap(createRoundConerImage(mSrc), 0, 0, null);

break;

}

}

/**

* 根据原图和变长绘制圆形图片

*

* @param source

* @param min

* @return

*/

private Bitmap createCircleImage(Bitmap source, int min)

{

final Paint paint = new Paint();

//防止边缘的抗锯齿

paint.setAntiAlias(true);

Bitmap target = Bitmap.createBitmap(min, min, Config.ARGB_8888);

// 产生一个同样大小的画布

Canvas canvas = new Canvas(target);

// 首先绘制圆形,除以2就是半径了

//最主要设置第三个参数为min/2,圆角幅度那么大就是圆形了

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

// 使用SRC_IN,参考上面的说明---上下层都显示。下层居上显示

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

// 绘制图片

canvas.drawBitmap(source, 0, 0, paint);

return target;

}

/**

* 根据原图添加圆角

*

* @param source

* @return

*/

private Bitmap createRoundConerImage(Bitmap source)

{

final Paint paint = new Paint();

paint.setAntiAlias(true);

Bitmap target = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);

Canvas canvas = new Canvas(target);

//绘制矩形

RectF rect = new RectF(0, 0, source.getWidth(), source.getHeight());

//设置圆角幅度

canvas.drawRoundRect(rect, mRadius, mRadius, paint);

// 使用SRC_IN,参考上面的说明---上下层都显示。下层居上显示

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

canvas.drawBitmap(source, 0, 0, paint);

return target;

}

}

2、使用BitmapShader设置圆角图片

package com.example.customimage.view;

import com.example.customimage.R;

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.RectF;

import android.graphics.Shader.TileMode;

import android.graphics.drawable.BitmapDrawable;

import android.graphics.drawable.Drawable;

import android.os.Bundle;

import android.os.Parcelable;

import android.util.AttributeSet;

import android.util.Log;

import android.util.TypedValue;

import android.widget.ImageView;

/**

*

*/

public class BitmapShaderImageView extends ImageView

{

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

private int type;

public static final int TYPE_CIRCLE = 0;

public static final int TYPE_RECT = 1;

//圆角大小的默认值

private static final int BODER_RADIUS_DEFAULT = 10;

//圆角的大小

private int mBorderRadius;

// 绘图的Paint

private Paint mBitmapPaint;

//圆角的半径

private int mRadius;

// 3x3 矩阵,主要用于缩小放大

private Matrix mMatrix;

// 渲染图像,使用图像为绘制图形着色

private BitmapShader mBitmapShader;

// view的宽度

private int mWidth;

//矩形

private RectF mRoundRect;

public BitmapShaderImageView(Context context)

{

this(context, null);

}

public BitmapShaderImageView(Context context, AttributeSet attrs)

{

super(context, attrs);

mMatrix = new Matrix();

mBitmapPaint = new Paint();

mBitmapPaint.setAntiAlias(true);

TypedArray a = context.obtainStyledAttributes(attrs,

R.styleable.BitmapShaderImageView);

//矩形圆角幅度的获取,默认是10dp

mBorderRadius = a.getDimensionPixelSize(

R.styleable.BitmapShaderImageView_borderRadius, (int) TypedValue

.applyDimension(TypedValue.COMPLEX_UNIT_DIP,

BODER_RADIUS_DEFAULT, getResources()

.getDisplayMetrics()));

//自定义类型属性,0是圆形,1是矩形圆角

type = a.getInt(R.styleable.BitmapShaderImageView_type, TYPE_CIRCLE);

a.recycle();

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

{

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

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

if (type == TYPE_CIRCLE)

{

mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());

//圆形的半径

mRadius = mWidth / 2;

setMeasuredDimension(mWidth, mWidth);

}

}

// 初始化BitmapShader,获取到图片资源

// 等待画布的准备好,然后在画布上加上Paint就是了

//就是说图片的载体是Paint

private void setUpShader()

{

Drawable drawable = getDrawable();

if (drawable == null)

{

return;

}

Bitmap bmp = drawableToBitamp(drawable);

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

//TileMode.CLAMP 拉伸

mBitmapShader = new BitmapShader(bmp, TileMode.CLAMP, TileMode.CLAMP);

float scale = 1.0f;

if (type == TYPE_CIRCLE)

{

// 拿到bitmap宽或高的小值

int bSize = Math.min(bmp.getWidth(), bmp.getHeight());

scale = mWidth * 1.0f / bSize;

} else if (type == TYPE_RECT)

{

if (!(bmp.getWidth() == getWidth() && bmp.getHeight() == getHeight()))

{

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

scale = Math.max(getWidth() * 1.0f / bmp.getWidth(),

getHeight() * 1.0f / bmp.getHeight());

}

}

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

// scale * scale 的矩阵

mMatrix.setScale(scale, scale);

// 设置变换矩阵

mBitmapShader.setLocalMatrix(mMatrix);

// 设置shader

mBitmapPaint.setShader(mBitmapShader);

}

@Override

protected void onDraw(Canvas canvas)

{

if (getDrawable() == null)

{

return;

}

setUpShader();

if (type == TYPE_RECT)

{

//绘制矩形

canvas.drawRoundRect(mRoundRect, mBorderRadius, mBorderRadius,

mBitmapPaint);

} else

{

//绘制圆形

canvas.drawCircle(mRadius, mRadius, mRadius, mBitmapPaint);

}

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh)

{

super.onSizeChanged(w, h, oldw, oldh);

// 圆角图片的范围

if (type == TYPE_RECT)

mRoundRect = new RectF(0, 0, w, h);

}

//drawable转bitmap

private Bitmap drawableToBitamp(Drawable drawable)

{

//从控件的src获取背景,也是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 static final String STATE_INSTANCE = "state_instance";

private static final String STATE_TYPE = "state_type";

private static final String STATE_BORDER_RADIUS = "state_border_radius";

//屏幕旋转后,取出保存的值

@Override

protected Parcelable onSaveInstanceState()

{

Bundle bundle = new Bundle();

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

bundle.putInt(STATE_TYPE, type);

bundle.putInt(STATE_BORDER_RADIUS, mBorderRadius);

return bundle;

}

//屏幕旋转,变量的保存,因为外面设置值,如果不保存,一旋转就变成个xml里面设置的值

@Override

protected void onRestoreInstanceState(Parcelable state)

{

if (state instanceof Bundle)

{

Bundle bundle = (Bundle) state;

super.onRestoreInstanceState(((Bundle) state)

.getParcelable(STATE_INSTANCE));

this.type = 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();

}

}

//设置是圆形还是矩形圆角

public void setType(int type)

{

if (this.type != type)

{

this.type = type;

if (this.type != TYPE_RECT && this.type != TYPE_CIRCLE)

{

this.type = TYPE_CIRCLE;

}

requestLayout();

}

}

//dp转px

public int dp2px(int dpVal)

{

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

dpVal, getResources().getDisplayMetrics());

}

}

3、滑动旋转缩放的bimp图片

package com.example.customimage.view;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Canvas;

import android.graphics.Matrix;

import android.graphics.Paint;

import android.graphics.PaintFlagsDrawFilter;

import android.graphics.PointF;

import android.graphics.drawable.BitmapDrawable;

import android.graphics.drawable.Drawable;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.widget.ImageView;

public class MatrixImageView extends ImageView {

private static final int MODE_NONE = 0x00123;// 默认的触摸模式

private static final int MODE_DRAG = 0x00321;// 拖拽模式

private static final int MODE_ZOOM = 0x00132;// 缩放or旋转模式

private int mode;// 当前的触摸模式

private float preMove = 1F;// 上一次手指移动的距离

private float saveRotate = 0F;// 保存了的角度值

private float rotate = 0F;// 旋转的角度

private float[] preEventCoor;// 上一次各触摸点的坐标集合

private PointF startPointF, midPointF;// 起点、中点对象

private Matrix currentMatrix, savedMatrix;// 当前和保存了的Matrix对象

//原始图片

private Bitmap mSrc;

//控件的宽度

private int mWidth;

// 控件的高度

private int mHeight;

private PaintFlagsDrawFilter mDrawFilter;

public MatrixImageView(Context context, AttributeSet attrs) {

super(context, attrs);

// 初始化

init();

}

/**

* 初始化

*/

private void init() {

// 实例化对象

currentMatrix = new Matrix();

savedMatrix = new Matrix();

startPointF = new PointF();

midPointF = new PointF();

mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);

// 模式初始化

mode = MODE_NONE;

Drawable drawable = getDrawable();

mSrc = drawableToBitamp(drawable);

}

/**

* 计算控件的高度和宽度

*/

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

{

// 设置宽度

int specMode = MeasureSpec.getMode(widthMeasureSpec);

int specSize = MeasureSpec.getSize(widthMeasureSpec);

//match_parent或者设置的精确值获取

//MeasureSpec.EXACTLY

if (specMode == MeasureSpec.EXACTLY)

{

mWidth = specSize;

}

else

{

// 由图片决定的宽

//getPaddingLeft(),getPaddingRight()这两个值是控件属性的向内偏移的距离值,所以的一起计算

//区别于layout_marginLeft,两个控件的左间距值设置

int desireByImg = getPaddingLeft() + getPaddingRight()

+ mSrc.getWidth();

// wrap_content

if (specMode == MeasureSpec.AT_MOST)

{

//所以最小的值,宽度的话是左右内偏移距离之和

mWidth = Math.min(desireByImg, specSize);

} else

mWidth = desireByImg;

}

// 设置高度,部分解释同上

specMode = MeasureSpec.getMode(heightMeasureSpec);

specSize = MeasureSpec.getSize(heightMeasureSpec);

//match_parent或者设置的精确值获取

//MeasureSpec.EXACTLY

if (specMode == MeasureSpec.EXACTLY)

{

mHeight = specSize;

} else

{

int desire = getPaddingTop() + getPaddingBottom()

+ mSrc.getHeight();

// wrap_content

if (specMode == MeasureSpec.AT_MOST)

{

mHeight = Math.min(desire, specSize);

} else

mHeight = desire;

}

//计算好的宽度以及高度是值,设置进去

setMeasuredDimension(mWidth, mHeight);

}

//drawable转bitmap

private Bitmap drawableToBitamp(Drawable drawable)

{

//从控件的src获取背景,也是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;

}

final Paint paint = new Paint();

@Override

protected void onDraw(Canvas canvas) {

//消除锯齿, 图片旋转后的锯齿消除不成功,实在不行图片边缘加一些白色像素点

canvas.setDrawFilter(mDrawFilter);

//画经过Matrix变化后的图

canvas.drawBitmap(mSrc, currentMatrix, null);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction() & MotionEvent.ACTION_MASK) {

case MotionEvent.ACTION_DOWN:// 单点接触屏幕时

savedMatrix.set(currentMatrix);

startPointF.set(event.getX(), event.getY());

//单点触摸是移动模式

mode = MODE_DRAG;

preEventCoor = null;

break;

case MotionEvent.ACTION_POINTER_DOWN:// 第二个点接触屏幕时

preMove = calSpacing(event);

if (preMove > 10F) {

savedMatrix.set(currentMatrix);

// 计算两个触摸点的中点坐标

calMidPoint(midPointF, event);

//两点是旋转或者缩放模式

mode = MODE_ZOOM;

}

preEventCoor = new float[4];

preEventCoor[0] = event.getX(0);

preEventCoor[1] = event.getX(1);

preEventCoor[2] = event.getY(0);

preEventCoor[3] = event.getY(1);

saveRotate = calRotation(event);

break;

case MotionEvent.ACTION_UP:// 单点离开屏幕时

case MotionEvent.ACTION_POINTER_UP:// 第二个点离开屏幕时

mode = MODE_NONE;

preEventCoor = null;

break;

case MotionEvent.ACTION_MOVE:// 触摸点移动时

/*

* 单点触控拖拽平移

*/

if (mode == MODE_DRAG) {

currentMatrix.set(savedMatrix);

float dx = event.getX() - startPointF.x;

float dy = event.getY() - startPointF.y;

currentMatrix.postTranslate(dx, dy);

}

/*

* 两点触控拖放旋转

*/

else if (mode == MODE_ZOOM && event.getPointerCount() == 2) {

float currentMove = calSpacing(event);

currentMatrix.set(savedMatrix);

/*

* 指尖移动距离大于10F缩放

*/

if (currentMove > 10F) {

float scale = currentMove / preMove;

currentMatrix.postScale(scale, scale, midPointF.x, midPointF.y);

}

/*

* 保持两点时旋转

*/

if (preEventCoor != null) {

rotate = calRotation(event);

r = rotate - saveRotate;

currentMatrix.postRotate(r, getMeasuredWidth() / 2, getMeasuredHeight() / 2);

}

}

break;

}

setImageMatrix(currentMatrix);

return true;

}

float r;

/**

* 计算两个触摸点间的距离

*/

private float calSpacing(MotionEvent event) {

float x = event.getX(0) - event.getX(1);

float y = event.getY(0) - event.getY(1);

return (float) Math.sqrt(x * x + y * y);

}

/**

* 计算两个触摸点的中点坐标

*/

private void calMidPoint(PointF point, MotionEvent event) {

float x = event.getX(0) + event.getX(1);

float y = event.getY(0) + event.getY(1);

point.set(x / 2, y / 2);

}

/**

* 计算旋转角度

*

* @param 事件对象

* @return 角度值

*/

private float calRotation(MotionEvent event) {

double deltaX = (event.getX(0) - event.getX(1));

double deltaY = (event.getY(0) - event.getY(1));

double radius = Math.atan2(deltaY, deltaX);

return (float) Math.toDegrees(radius);

}

}

4、图片颜色处理(滑动)

package com.example.customimage.view;

import com.example.customimage.R;

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.ColorMatrixColorFilter;

import android.graphics.Matrix;

import android.graphics.Paint;

import android.graphics.PorterDuff.Mode;

import android.graphics.PorterDuffXfermode;

import android.graphics.RadialGradient;

import android.graphics.Shader.TileMode;

import android.util.AttributeSet;

import android.view.View;

public class DreamEffectView extends View {

private Paint mBitmapPaint, mShaderPaint;// 位图画笔和Shader图形的画笔

private PorterDuffXfermode mXfermode;// 图形混合模式

private int x, y;// 位图起点坐标

//控件的宽度

private int mWidth;

// 控件的高度

private int mHeight;

//原始图片

private Bitmap mSrc;

//生成暗角的图片

private Bitmap darkCornerBitmap;

public final static int BITMAP_NULL = 0; //原图

private final static int BITMAP_DEAST = 1; //去饱和

private final static int BITMAP_CENTER = 2; //中心突出

private final static int BITMAP_DARKCORNER = 3; //四角黑暗

private int mnSelectMode = 0;

public DreamEffectView(Context context, AttributeSet attrs)

{

this(context, attrs, 0);

}

public DreamEffectView(Context context)

{

this(context, null);

}

public DreamEffectView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs,defStyle);

TypedArray a = context.getTheme().obtainStyledAttributes(attrs,

R.styleable.DreamEffectView, defStyle, 0);

int n = a.getIndexCount();

for (int i = 0; i < n; i++)

{

int attr = a.getIndex(i);

switch (attr)

{

//原始图片,在布局里面获取

case R.styleable.DreamEffectView_src:

mSrc = BitmapFactory.decodeResource(getResources(),

a.getResourceId(attr, 0));

break;

case R.styleable.DreamEffectView_mode:

mnSelectMode = a.getInt(attr, 0);

break;

}

}

a.recycle();

// 实例化混合模式

mXfermode = new PorterDuffXfermode(Mode.SCREEN);

// 初始化画笔

initPaint();

}

/**

* 计算控件的高度和宽度

*/

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

{

// 设置宽度

int specMode = MeasureSpec.getMode(widthMeasureSpec);

int specSize = MeasureSpec.getSize(widthMeasureSpec);

if (specMode == MeasureSpec.EXACTLY)

{

mWidth = specSize;

}

else

{

int desireByImg = getPaddingLeft() + getPaddingRight()

+ mSrc.getWidth();

// wrap_content

if (specMode == MeasureSpec.AT_MOST)

{

//所以最小的值,宽度的话是左右内偏移距离之和

mWidth = Math.min(desireByImg, specSize);

} else

mWidth = desireByImg;

}

// 设置高度,部分解释同上

specMode = MeasureSpec.getMode(heightMeasureSpec);

specSize = MeasureSpec.getSize(heightMeasureSpec);

if (specMode == MeasureSpec.EXACTLY)

{

mHeight = specSize;

} else

{

int desire = getPaddingTop() + getPaddingBottom()

+ mSrc.getHeight();

// wrap_content

if (specMode == MeasureSpec.AT_MOST)

{

mHeight = Math.min(desire, specSize);

} else

mHeight = desire;

}

x = mWidth / 2 - mSrc.getWidth() / 2;

y = mHeight / 2 - mSrc.getHeight() / 2;

//计算好的宽度以及高度是值,设置进去

setMeasuredDimension(mWidth, mHeight);

}

/**

* 初始化画笔

*/

private void initPaint() {

// 实例化画笔

mBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

// 实例化Shader图形的画笔

mShaderPaint = new Paint();

switch (mnSelectMode) {

case BITMAP_NULL:

break;

case BITMAP_DEAST:

// 去饱和、提亮、色相矫正

mBitmapPaint.setColorFilter(new ColorMatrixColorFilter(

new float[] { 0.8587F, 0.2940F, -0.0927F, 0, 6.79F, 0.0821F, 0.9145F, 0.0634F, 0, 6.79F,

0.2019F, 0.1097F, 0.7483F, 0, 6.79F, 0, 0, 0, 1, 0 }));

break;

case BITMAP_CENTER:

// 去饱和、提亮、色相矫正

mBitmapPaint.setColorFilter(new ColorMatrixColorFilter(

new float[] { 0.8587F, 0.2940F, -0.0927F, 0, 6.79F, 0.0821F, 0.9145F, 0.0634F, 0, 6.79F,

0.2019F, 0.1097F, 0.7483F, 0, 6.79F, 0, 0, 0, 1, 0 }));

// 设置径向渐变,渐变中心当然是图片的中心也是屏幕中心,渐变半径我们直接拿图片的高度但是要稍微小一点

// 中心颜色为透明而边缘颜色为黑色

mShaderPaint.setShader(new RadialGradient(mWidth / 2, mWidth / 2, mSrc.getHeight() * 7 / 8, Color.TRANSPARENT,

Color.BLACK, TileMode.CLAMP));

break;

case BITMAP_DARKCORNER:

// 去饱和、提亮、色相矫正

mBitmapPaint.setColorFilter(new ColorMatrixColorFilter(

new float[] { 0.8587F, 0.2940F, -0.0927F, 0, 6.79F, 0.0821F, 0.9145F, 0.0634F, 0, 6.79F,

0.2019F, 0.1097F, 0.7483F, 0, 6.79F, 0, 0, 0, 1, 0 }));

// 根据我们源图的大小生成暗角Bitmap

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

// 将该暗角Bitmap注入Canvas

Canvas canvas = new Canvas(darkCornerBitmap);

// 计算径向渐变半径

float radiu = canvas.getHeight() * (2F / 3F);

// 实例化径向渐变

RadialGradient radialGradient = new RadialGradient(canvas.getWidth() / 2F, canvas.getHeight() / 2F, radiu, new int[] { 0, 0, 0xAA000000 }, new float[] { 0F, 0.7F, 1.0F }, TileMode.CLAMP);

// 实例化一个矩阵

Matrix matrix = new Matrix();

// 设置矩阵的缩放

matrix.setScale(canvas.getWidth() / (radiu * 2F), 1.0F);

// 设置矩阵的预平移

matrix.preTranslate(((radiu * 2F) - canvas.getWidth()) / 2F, 0);

// 将该矩阵注入径向渐变

radialGradient.setLocalMatrix(matrix);

// 设置画笔Shader

mShaderPaint.setShader(radialGradient);

// 绘制矩形

canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mShaderPaint);

break;

default:

break;

}

}

@Override

protected void onDraw(Canvas canvas) {

canvas.drawColor(Color.BLACK);

// 新建图层

int sc = canvas.saveLayer(x, y, x + mSrc.getWidth(), y + mSrc.getHeight(), null, Canvas.ALL_SAVE_FLAG);

// 绘制混合颜色

canvas.drawColor(0xcc1c093e);

// 设置混合模式

mBitmapPaint.setXfermode(mXfermode);

// 绘制位图

canvas.drawBitmap(mSrc, x, y, mBitmapPaint);

// 还原混合模式

mBitmapPaint.setXfermode(null);

// 还原画布

canvas.restoreToCount(sc);

switch (mnSelectMode) {

case BITMAP_NULL:

break;

case BITMAP_DEAST:

break;

case BITMAP_CENTER:

// 绘制一个跟图片大小一样的矩形

canvas.drawRect(x, y, x + mSrc.getWidth(), y + mSrc.getHeight(),mShaderPaint);

break;

case BITMAP_DARKCORNER:

// 绘制我们画好的径向渐变图

canvas.drawBitmap(darkCornerBitmap, x, y, null);

break;

default:

break;

}

}

}

1)、实现 去饱和、提亮、色相矫正 效果的部分代码

mBitmapPaint.setColorFilter(new ColorMatrixColorFilter(

new float[] { 0.8587F, 0.2940F, -0.0927F, 0, 6.79F, 0.0821F, 0.9145F, 0.0634F, 0, 6.79F,

0.2019F, 0.1097F, 0.7483F, 0, 6.79F, 0, 0, 0, 1, 0 }));

2)、实现中心颜色为透明而边缘颜色为黑色效果的部分代码

mShaderPaint.setShader(new RadialGradient(mWidth / 2, mWidth / 2, mSrc.getHeight() * 7 / 8, Color.TRANSPARENT,

Color.BLACK, TileMode.CLAMP));

3)、实现四角黑暗效果的部分代码

// 根据我们源图的大小生成暗角Bitmap

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

// 将该暗角Bitmap注入Canvas

Canvas canvas = new Canvas(darkCornerBitmap);

// 计算径向渐变半径

float radiu = canvas.getHeight() * (2F / 3F);

// 实例化径向渐变

RadialGradient radialGradient = new RadialGradient(canvas.getWidth() / 2F, canvas.getHeight() / 2F, radiu, new int[] { 0, 0, 0xAA000000 }, new float[] { 0F, 0.7F, 1.0F }, TileMode.CLAMP);

// 实例化一个矩阵

Matrix matrix = new Matrix();

// 设置矩阵的缩放

matrix.setScale(canvas.getWidth() / (radiu * 2F), 1.0F);

// 设置矩阵的预平移

matrix.preTranslate(((radiu * 2F) - canvas.getWidth()) / 2F, 0);

// 将该矩阵注入径向渐变

radialGradient.setLocalMatrix(matrix);

// 设置画笔Shader

mShaderPaint.setShader(radialGradient);

// 绘制矩形

canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mShaderPaint);

5、图片 + 文字

package com.example.customimage.view;

import com.example.customimage.R;

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.PorterDuff;

import android.graphics.PorterDuffXfermode;

import android.graphics.RectF;

import android.graphics.Bitmap.Config;

import android.graphics.Paint.Style;

import android.graphics.Rect;

import android.text.TextPaint;

import android.text.TextUtils;

import android.util.AttributeSet;

import android.util.Log;

import android.util.TypedValue;

import android.view.View;

public class ImageViewText extends View{

//类型

private int type;

private static final int TYPE_CIRCLE = 0; //圆形

private static final int TYPE_RECT = 1; //矩形圆角

//原始图片

private Bitmap mImage;

//控件的宽度

private int mWidth;

// 控件的高度

private int mHeight;

//矩形圆角的幅度

private int mRadius;

//图片下面的文字

private String mTitle;

private int mTextColor;

private int mTextSize;

private Rect rect;

private Paint mPaint;

private Rect mTextBound;

public ImageViewText(Context context, AttributeSet attrs)

{

this(context, attrs, 0);

}

public ImageViewText(Context context)

{

this(context, null);

}

/**

* 初始化所特有自定义类型

*

* @param context

* @param attrs

* @param defStyle

*/

public ImageViewText(Context context, AttributeSet attrs, int defStyle)

{

super(context, attrs, defStyle);

TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ImageViewText, defStyle, 0);

int n = a.getIndexCount();

for (int i = 0; i < n; i++)

{

int attr = a.getIndex(i);

switch (attr)

{

//获取图片

case R.styleable.ImageViewText_image:

mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));

break;

//获取圆形还是方形

case R.styleable.ImageViewText_type:

type = a.getInt(attr, 0);

break;

//获取文字

case R.styleable.ImageViewText_titleText:

mTitle = a.getString(attr);

break;

//获取文字的图片

case R.styleable.ImageViewText_titleTextColor:

mTextColor = a.getColor(attr, Color.BLACK);

break;

//获取文字的大小

case R.styleable.ImageViewText_titleTextSize:

mTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,

16, getResources().getDisplayMetrics()));

break;

//矩形圆角幅度的获取,默认是10dp

case R.styleable.ImageViewText_borderRadius:

mRadius = a.getDimensionPixelSize(attr, (int) TypedValue

.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f,

getResources().getDisplayMetrics()));

break;

}

}

a.recycle();

rect = new Rect();

mPaint = new Paint();

mTextBound = new Rect();

mPaint.setTextSize(mTextSize);

// 计算了描绘字体需要的范围

mPaint.getTextBounds(mTitle, 0, mTitle.length(), mTextBound);

}

//测量控件的大小

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

{

//设置宽度

int specMode = MeasureSpec.getMode(widthMeasureSpec);

int specSize = MeasureSpec.getSize(widthMeasureSpec);

// match_parent , accurate 大小

if (specMode == MeasureSpec.EXACTLY)

{

mWidth = specSize;

} else

{

// 由图片决定的宽

int desireByImg = getPaddingLeft() + getPaddingRight() + mImage.getWidth();

// 由字体决定的宽

int desireByTitle = getPaddingLeft() + getPaddingRight() + mTextBound.width();

//wrap_content 大小

if (specMode == MeasureSpec.AT_MOST)

{

//取小的值

int desire = Math.max(desireByImg, desireByTitle);

mWidth = Math.min(desire, specSize);

}

}

//设置高度

specMode = MeasureSpec.getMode(heightMeasureSpec);

// match_parent , accurate 大小

if (specMode == MeasureSpec.EXACTLY)

{

mHeight = specSize;

} else

{

//wrap_content 大小

mHeight = getPaddingTop() + getPaddingBottom() + mImage.getHeight() + mTextBound.height();

}

//测量好的大小设置进去

setMeasuredDimension(mWidth, mHeight);

}

@Override

protected void onDraw(Canvas canvas)

{

// 边框

mPaint.setStrokeWidth(4);

mPaint.setStyle(Paint.Style.STROKE);

mPaint.setColor(Color.CYAN);

canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);

mPaint.setColor(mTextColor);

mPaint.setStyle(Style.FILL);

//当前设置的宽度小于字体需要的宽度,将字体改为

//绘制文字

if (mTextBound.width() > mWidth)

{

TextPaint paint = new TextPaint(mPaint);

String msg = TextUtils.ellipsize(mTitle, paint, (float) mWidth - getPaddingLeft() - getPaddingRight(),

TextUtils.TruncateAt.END).toString();

canvas.drawText(msg, getPaddingLeft(), mHeight - getPaddingBottom(), mPaint);

} else

{

//正常情况,将字体居中

canvas.drawText(mTitle, mWidth / 2 - mTextBound.width() * 1.0f / 2, mHeight - getPaddingBottom(), mPaint);

}

//计算居中的矩形范围

rect.left = mWidth / 2 - mImage.getWidth() / 2 + getPaddingLeft();

rect.right = mWidth / 2 + mImage.getWidth() / 2 + getPaddingRight();

rect.top = (mHeight - mTextBound.height()) / 2 - mImage.getHeight() / 2 + getPaddingTop();

rect.bottom = (mHeight - mTextBound.height()) / 2 + mImage.getHeight() / 2 + getPaddingBottom();

switch (type)

{

// 如果是TYPE_CIRCLE绘制圆形

case TYPE_CIRCLE:

//圆形宽度和高度应该一致的,所以也要比较一下大小,取小的值

int min = Math.min(mWidth, mHeight);

// 圆形宽度和高度如果不一致,按小的值进行压缩

mImage = Bitmap.createScaledBitmap(mImage, min, min, false);

//绘制圆形

canvas.drawBitmap(createCircleImage(mImage, min), null, rect, null);

break;

case TYPE_RECT:

canvas.drawBitmap(createRoundConerImage(mImage), null, rect, null);

break;

}

}

/**

* 根据原图和变长绘制圆形图片

*

* @param source

* @param min

* @return

*/

private Bitmap createCircleImage(Bitmap source, int min)

{

final Paint paint = new Paint();

//防止边缘的抗锯齿

paint.setAntiAlias(true);

Bitmap target = Bitmap.createBitmap(min, min, Config.ARGB_8888);

// 产生一个同样大小的画布

Canvas canvas = new Canvas(target);

// 首先绘制圆形,除以2就是半径了

//最主要设置第三个参数为min/2,圆角幅度那么大就是圆形了

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

// 使用SRC_IN,参考上面的说明---上下层都显示。下层居上显示

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

// 绘制图片

canvas.drawBitmap(source, 0, 0, paint);

return target;

}

/**

* 根据原图添加圆角

*

* @param source

* @return

*/

private Bitmap createRoundConerImage(Bitmap source)

{

final Paint paint = new Paint();

paint.setAntiAlias(true);

Bitmap target = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);

Canvas canvas = new Canvas(target);

//绘制矩形

RectF rect = new RectF(0, 0, source.getWidth(), source.getHeight());

//设置圆角幅度

canvas.drawRoundRect(rect, mRadius, mRadius, paint);

// 使用SRC_IN,参考上面的说明---上下层都显示。下层居上显示

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

canvas.drawBitmap(source, 0, 0, paint);

return target;

}

}

是不是很全的Android自定义图片集合,希望大家喜欢。

android 自定义图片,Android自定义图片集合相关推荐

  1. Android应用--简、美音乐播放器获取专辑图片(自定义列表适配器)

    Android应用--简.美音乐播放器获取专辑图片(自定义列表适配器) 2013年7月3日简.美音乐播放器开发 第二阶段已增加功能: 1.歌词滚动显示 2.来电监听 3.音量控制 4.左右滑动切换歌词 ...

  2. android如何自定义viewpager,Android自定义ViewPager实现个性化的图片切换效果

    第一次见到ViewPager这个控件,瞬间爱不释手,做东西的主界面通通ViewPager,以及图片切换也抛弃了ImageSwitch之类的,开始让ViewPager来做.时间长了,ViewPager的 ...

  3. Android --- 自定义ImageView 实现圆形图片

    自定义ImageView实现圆形图片,主要是在onDraw()方法中实现绘制圆形图片,在onMeasure()中测量圆形的半径并设置View的宽高.效果如下图 代码如下 public class Ci ...

  4. 自定义背景android,Android自定义Button并设置不同背景图片的方法

    本文实例讲述了Android自定义Button并设置不同背景图片的方法.分享给大家供大家参考,具体如下: 1.自定义MyButton类 public class MyButton extends Bu ...

  5. Android 自定义View消除锯齿实现图片旋转,添加边框及文字说明

    先看看图片的效果,左边是原图,右边是旋转之后的图:   之所以把这个写出来是因为在一个项目中需要用到这样的效果,我试过用FrameLayout布局如上的画面,然后旋转FrameLayout,随之而来也 ...

  6. Android 自定义ImageView加载图片

    自定义imageview功能: 可以实现设置图片显示的时候,依据本身的比例进行图片的缩放 加载图片效果: 使用ImageLoader来加载 图片: 首先将ImageLoader的jar包关联到项目中 ...

  7. android自定义图片加载,Android自定义ProgressDialog加载图片

    为了提高用户体验,我们肯定希望该Dialog能更加炫酷,让用户看着更舒服.那如何做呢,当然是我们自己定义一个ProgressDialog了. 一.使用系统加载框 mDialog = new Progr ...

  8. Android 自定义拍照,解决图片旋转,拍照参数设置兼容问题

    Android 自定义拍照,解决图片旋转,拍照参数设置兼容问题 参考文章: (1)Android 自定义拍照,解决图片旋转,拍照参数设置兼容问题 (2)https://www.cnblogs.com/ ...

  9. imageview 自定义 android,Android自定义ImageView实现在图片上添加图层效果

    首先我们先看下效果图 实现思路 这是两张前后对比图,右边第二张图里面的已抢光标签图片当已经没有商品的时候就会显示了,在每个图片的中心位置,第一想法是在ImageView的外层再套一层RelativeL ...

  10. Android学习之复选框checkbox自定义样式以及调整图片大小

    1.自定义样式: 下载复选框样式图:https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.2 图片重命名为英文(否则找不到)并 ...

最新文章

  1. 高性能HTTP加速器varnish实践
  2. django 与 百度 ueditor 富文本编辑器集成
  3. android 微信跨境支付,微信跨境支付.pdf
  4. MBProgressHUD
  5. Eclipse新建web项目正常启动tomcat不报错,但不能访问项目的解决方法
  6. 常用的python测试脚本_详解Python的单元测试
  7. java sql 创建触发器_SQL Server创建触发器
  8. JavaScript 操作剪贴板
  9. 线上支付之----网关支付、银联代扣通道、快捷支付、银行卡支付等网上常见支付方式接口说明!!
  10. oracle 建表id自增长_oracle建表设置主键自增
  11. 在deepin 上安装佳能MF 4700打印机驱动
  12. robotium android,Robotium 测试Android apk安装包
  13. 老路MBA商学课|第002课:比较优势|我做的比你好,就应该我做吗?
  14. 批量添加搜狗域名绑站工具
  15. 什么是网络空间测绘?到底有什么作用?
  16. Mac 增加国内节假日安排
  17. springboot整合手机验证码
  18. 企业想要制作电商类App软件
  19. h264编码算法流程
  20. python 自动化运维——实战 (一)

热门文章

  1. HTML5新特性history
  2. 直坐标机械手的优缺点都有哪些?
  3. 详解 Web Worker,不再止步于会用
  4. MySQL Manual
  5. 如何两台电脑共享文件?
  6. 结对编程的合作情况,以及结对编程的优缺点
  7. import和export在浏览器中的使用方式
  8. xadmin里面的设置
  9. 国务院建议探索区块链等技术缩短承兑期限 | 产业区块链发展周报
  10. OpenVpnCentos8部署