1. 程式人生 > >android UI——具有裁剪功能的imageview

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);
}
}
}