您的位置:首页 > 移动开发 > 微信开发

自定义View——类似微信裁剪控件

2016-04-28 13:47 585 查看
用微信的时候发现设置头像的时候总是有些莫名其妙的问题,就模仿着做了个自定义View。

效果:



直接上代码。。。有些注释

public class CutView extends View implements ScaleGestureDetector.OnScaleGestureListener{

private Rect mBmpRect;
private Paint mShadowPaint,mRectPaint;
private Bitmap mSourceBmp;
private Matrix mMatrix;
private boolean isInited;
private float cutRadio = 1f;

private ScaleGestureDetector scaleGestureDetector;

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

public CutView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
mSourceBmp = BitmapFactory.decodeResource(getResources(), R.mipmap.bg);
}

private void init(Context context){
setBackgroundColor(Color.BLACK);
mBmpRect = new Rect();
mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRectPaint.setColor(Color.WHITE);
mRectPaint.setStyle(Paint.Style.STROKE);
mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mShadowPaint.setColor(0xa0000000);
scaleGestureDetector = new ScaleGestureDetector(context,this);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = MeasureSpec.getSize(heightMeasureSpec);
//左右两边的padding设置
int padding = (int) (w * 0.065f);
//裁剪比例
int rectW = w - 2 * padding;
int rectH = (int) (rectW / cutRadio);

mBmpRect.set(padding,(h - rectH)/2,padding + rectW,(h - rectH)/2 + rectH);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (!isInited) {
mMatrix = new Matrix();

int dw = mSourceBmp.getWidth();
int dh = mSourceBmp.getHeight();

float scale = 0;
if (dw > dh) {
scale = mBmpRect.width() /(float) dw;
}else {
scale = mBmpRect.height() /(float) dh;
}

mMatrix.postTranslate(getWidth() / 2 - dw / 2, getHeight() / 2 - dh/2);
mMatrix.postScale(scale,scale,mBmpRect.left+mBmpRect.width()/2,mBmpRect.top+mBmpRect.height()/2);

isInited = true;
}
}

private float startX,startY;
private boolean isMultiPoint = false;
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getPointerCount()>1) {
scaleGestureDetector.onTouchEvent(event);
isMultiPoint = true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (checkIsInRect(event)) {
startX = event.getX();
startY = event.getY();
} else {
return false;
}
break;
case MotionEvent.ACTION_MOVE:
float offX = event.getX() - startX;
float offY = event.getY() - startY;

if (!isMultiPoint) {
mMatrix.postTranslate(offX, offY);
invalidate();
}

startX = event.getX();
startY = event.getY();
break;
case MotionEvent.ACTION_UP:
isMultiPoint = false;
break;
}
return true;
}

/*
检查触摸点是否在裁剪范围框内
*/
private boolean checkIsInRect(MotionEvent event){
int x = (int) event.getX();
int y = (int) event.getY();
return mBmpRect.contains(x,y);
}

/*
裁剪
*/
public Bitmap cut(){
setDrawingCacheEnabled(true);
Bitmap bmp = getDrawingCache();
return Bitmap.createBitmap(bmp, mBmpRect.left, mBmpRect.top, mBmpRect.width(), mBmpRect.height());
}

/*
旋转
*/
public void rotate(){
Point point = getCenterPoint();
mMatrix.postRotate(-90,point.x,point.y);
invalidate();
}

/*
水平翻转
*/
public void flip(){
Point point = getCenterPoint();
mMatrix.postScale(-1, 1,point.x,point.y);
invalidate();
}

private Point getCenterPoint(){
Point point = new Point();
RectF rectF = getBmpRect();
point.x = (int) (rectF.left + rectF.width()/2);
point.y = (int) (rectF.top + rectF.height()/2);
return point;
}
public void setCutRadio(float cutRadio) {
this.cutRadio = cutRadio;
}

public void setSourceBmp(Bitmap mSourceBmp) {
this.mSourceBmp = mSourceBmp;
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画出源图片
canvas.drawBitmap(mSourceBmp,mMatrix,null);
//画出阴影遮盖部分
canvas.drawRect(0, 0, getWidth(), mBmpRect.top, mShadowPaint);
canvas.drawRect(0, mBmpRect.top, mBmpRect.left, mBmpRect.bottom, mShadowPaint);
canvas.drawRect(mBmpRect.right, mBmpRect.top, getWidth(), mBmpRect.bottom, mShadowPaint);
canvas.drawRect(0,mBmpRect.bottom,getWidth(),getHeight(),mShadowPaint);
//画出中间裁剪部分的矩形,边缘留出1的距离为了截图的时候不被截取到
canvas.drawRect(mBmpRect.left-1,mBmpRect.top-1,mBmpRect.right+1,mBmpRect.bottom+1,mRectPaint);

}

@Override
public boolean onScale(ScaleGestureDetector detector) {
float scale = detector.getScaleFactor();

RectF rectF = getBmpRect();
if (rectF.contains(detector.getFocusX(),detector.getFocusY())) {
mMatrix.postScale(scale, scale, detector.getFocusX(), detector.getFocusY());
}else {
mMatrix.postScale(scale, scale,rectF.left+rectF.width()/2,rectF.top+rectF.height()/2);
}
invalidate();

return true;
}

@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}

@Override
public void onScaleEnd(ScaleGestureDetector detector) {

}

private RectF getBmpRect(){
Matrix matrix = mMatrix;
RectF rectF = new RectF();
rectF.set(0, 0, mSourceBmp.getWidth(), mSourceBmp.getHeight());
matrix.mapRect(rectF);
return rectF;
}
}


没有太大难度,图片是用canvas画上去的,图片的处理是利用matrix实现的,截图利用的是getDrawingCathe,其实也可以通过自己确定范围createBitmap,但是我因为项目需要背后的颜色,所以采用这种方式更为简便
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: