android UI——具有裁剪功能的imageview

从事android工作已经有半年了,积累了不少经验,现在来博客将一些自己的代码和知识整理下,也看能不能帮助下别人吧,自己也是一致靠着前辈们的努力一点一点积攒知识的。

这次我就来说下如何去实现一个裁剪图片控件。正如很多程序中有的那样,用户可以通过操作一个视图框对加载的图片进行裁剪,而如何实现这样的控件呢?

很简单,实际上就是重写一个ImageView类,然后在原有的view上绘制线条,并记录矩形区域,标示需要裁剪的范围。

之后通过canvas,将原bitmap绘制在指定的区域中,获取到所需要的bitmap

代码比较简单,如下所示。

public class CropImageView extends ImageView {
private final static int PRESS_LEFT = 0x00;
private final static int PRESS_UP = 0x01;
private final static int PRESS_RIGHT = 0x02;
private final static int PRESS_DOWN = 0x03;
// 源图像
private Bitmap bitmap;
Paint mPaint;
// 变换矩阵
Matrix matrix;
// 要裁剪的矩形区域
Rect mCurrentRect;
// 上下左右四条边的触摸区域
Rect[] rect = new Rect[4];
private final static int PADDING = 30;
int min_width = 0;
int max_width = 1280;
int min_height = 0;
int max_height = 800;
//标识当前触摸的边
int touch_edge;
//上一次触摸的坐标
Pos last_touch;
public CropImageView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mCurrentRect = new Rect();
touch_edge = -1;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
int action = event.getAction();
Pos pos = new Pos(event.getX(), event.getY());
switch (action) {
case MotionEvent.ACTION_DOWN:
for (int i = 0; i < rect.length; i++) {
if (rect[i].contains(pos.x, pos.y)) {
touch_edge = i;
break;
}
}
break;
case MotionEvent.ACTION_MOVE:
// 移动幅度过小或者没有触到边界则不进行修改
if (touch_edge == -1
|| (pos.x == last_touch.x && pos.y == last_touch.y))
break;
switch (touch_edge) {
case PRESS_LEFT:
mCurrentRect.left = Math.min(
max_width,
Math.max(min_width, mCurrentRect.left - last_touch.x
+ pos.x));
rect[touch_edge].left = mCurrentRect.left - PADDING;
rect[touch_edge].right = mCurrentRect.left + PADDING;
break;
case PRESS_UP:
mCurrentRect.top = Math.min(
max_height,
Math.max(min_height, mCurrentRect.top - last_touch.y
+ pos.y));
rect[touch_edge].top = mCurrentRect.top - PADDING;
rect[touch_edge].bottom = mCurrentRect.top + PADDING;
break;
case PRESS_RIGHT:
mCurrentRect.right = Math.min(
max_width,
Math.max(min_width, mCurrentRect.right - last_touch.x
+ pos.x));
rect[touch_edge].left = mCurrentRect.right - PADDING;
rect[touch_edge].right = mCurrentRect.right + PADDING;
break;
case PRESS_DOWN:
mCurrentRect.bottom = Math.min(
max_height,
Math.max(min_height, mCurrentRect.bottom - last_touch.y
+ pos.y));
rect[touch_edge].top = mCurrentRect.bottom - PADDING;
rect[touch_edge].bottom = mCurrentRect.bottom + PADDING;
break;
}
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_edge = -1;
break;
}
last_touch = pos;
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制矩形区域
drawRect(canvas);
}
private void drawRect(Canvas canvas) {
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeMiter(6);
mPaint.setStrokeWidth(3);
mPaint.setColor(Color.RED);
canvas.drawRect(mCurrentRect, mPaint);
}
public Bitmap applyCrop() {
return Bitmap.createBitmap(bitmap, mCurrentRect.left, mCurrentRect.top,
mCurrentRect.right - mCurrentRect.left, mCurrentRect.bottom
- mCurrentRect.top, matrix, false);
}
public void setBitmap(Bitmap pBitmap) {
this.bitmap = pBitmap;
this.setImageBitmap(bitmap);
if (pBitmap == null)
return;
float scale = bitmap.getHeight() / (float) getHeight();
min_width = (int) (getWidth() - bitmap.getWidth() / scale) / 2;
max_width = (int) (getWidth() + bitmap.getWidth() / scale) / 2;
min_height = 0;
max_height = getHeight();
mCurrentRect = new Rect(min_width + PADDING, min_height + PADDING,
max_width - PADDING, max_height - PADDING);
// 初始化四条边的矩形区域,宽度为10
rect[PRESS_LEFT] = new Rect(mCurrentRect.left - PADDING,
mCurrentRect.top, mCurrentRect.left + PADDING,
mCurrentRect.bottom);
rect[PRESS_UP] = new Rect(mCurrentRect.left,
mCurrentRect.top - PADDING, mCurrentRect.right,
mCurrentRect.top + PADDING);
rect[PRESS_RIGHT] = new Rect(mCurrentRect.right - PADDING,
mCurrentRect.top, mCurrentRect.right + PADDING,
mCurrentRect.bottom);
rect[PRESS_DOWN] = new Rect(mCurrentRect.left, mCurrentRect.bottom
- PADDING, mCurrentRect.right, mCurrentRect.bottom + PADDING);
}
public String saveBitmap() {
String path = null;
float scale = bitmap.getHeight() / (float) getHeight();
Bitmap bmp = Bitmap.createScaledBitmap(bitmap,
(int) (bitmap.getWidth() / scale),
(int) (bitmap.getHeight() / scale), false);
if (bmp != null && mCurrentRect != null) {
Bitmap bmpDest = Bitmap
.createBitmap(bmp, mCurrentRect.left - min_width,
mCurrentRect.top, mCurrentRect.right
- mCurrentRect.left, mCurrentRect.bottom
- mCurrentRect.top);
bmp = bmpDest;
}
// 将bmp保存到临时文件
try {
File folder = new File(IConstant.SAVE_PATH);
if (!folder.exists())
folder.mkdir();
File tmpFile = File.createTempFile("result", ".jpg", folder);
tmpFile.deleteOnExit();
FileOutputStream os = new FileOutputStream(tmpFile);
bmp.compress(CompressFormat.JPEG, 100, os);
os.close();
path = tmpFile.getAbsolutePath();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return path;
}
class Pos {
public int x;
public int y;
public Pos(int px, int py) {
this.x = px;
this.y = py;
}
public Pos(float px, float py) {
this((int) px, (int) py);
}
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值