首页 > 代码库 > Android 相册图片选取+自定义裁剪方式(非系统裁剪)
Android 相册图片选取+自定义裁剪方式(非系统裁剪)
不多说,直接上代码(裁剪的代码摘自网络。)(项目可运行)
主要是系统自身的剪切方式在有些机型上会程序崩溃的问题。
1 package com.jichun.activity; 2 3 import java.io.FileNotFoundException; 4 5 import com.jichun.view.CropCanvas; 6 7 import android.app.Activity; 8 import android.content.ContentResolver; 9 import android.content.Intent;10 import android.graphics.Bitmap;11 import android.graphics.BitmapFactory;12 import android.net.Uri;13 import android.os.Bundle;14 import android.view.View;15 import android.view.View.OnClickListener;16 import android.widget.ImageButton;17 import android.widget.ImageView;18 19 public class MainActivity extends Activity {20 private CropCanvas canvas = null;21 22 /** Called when the activity is first created. */23 @Override24 public void onCreate(Bundle savedInstanceState) {25 super.onCreate(savedInstanceState);26 setContentView(R.layout.main);27 //创建确定按钮28 ImageButton confirmBtn = (ImageButton) findViewById(R.id.confirm_button);29 confirmBtn.setOnClickListener(new OnClickListener() {30 31 @Override32 public void onClick(View view) {33 confirmFunction();34 }35 });36 ImageButton exitBtn = (ImageButton) findViewById(R.id.exit_button);37 exitBtn.setOnClickListener(new OnClickListener() {38 39 @Override40 public void onClick(View view) {41 exitFunction(view);42 }43 });44 this.gallery();45 }46 47 /*48 * 从相册获取49 */50 public void gallery() {51 // 激活系统图库,选择一张图片52 Intent intent = new Intent(Intent.ACTION_PICK);53 intent.setType("image/*");54 // 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_GALLERY55 startActivityForResult(intent, 112);56 }57 58 @Override59 protected void onActivityResult(int requestCode, int resultCode, Intent data) {60 super.onActivityResult(requestCode, resultCode, data);61 if (requestCode == 112) {62 // 从相册返回的数据63 if (data != null) {64 // 得到图片的全路径65 Uri uri = data.getData();66 ContentResolver content_resolver = this.getContentResolver();67 try {68 Bitmap bmp = BitmapFactory.decodeStream(content_resolver.openInputStream(uri));69 canvas = (CropCanvas)findViewById(R.id.myCanvas);70 canvas.setBitmap(bmp);71 } catch (FileNotFoundException e) {72 // TODO Auto-generated catch block73 e.printStackTrace();74 }75 }76 }77 78 }79 80 public void confirmFunction(){81 canvas.setBitmap(canvas.getSubsetBitmap());82 }83 84 public void exitFunction(View view){85 this.finish();86 }87 }
1 package com.jichun.view; 2 3 import android.content.Context; 4 import android.graphics.Bitmap; 5 import android.graphics.Canvas; 6 import android.graphics.Color; 7 import android.graphics.Matrix; 8 import android.graphics.Paint; 9 import android.graphics.Rect; 10 import android.graphics.RectF; 11 import android.graphics.Bitmap.Config; 12 import android.graphics.drawable.BitmapDrawable; 13 import android.util.AttributeSet; 14 import android.view.MotionEvent; 15 import android.widget.ImageView; 16 17 public class CropCanvas extends ImageView { 18 19 private final static int PRESS_LB = 0;//表示左下角矩形框 20 private final static int PRESS_LT = 1;//表示左上角矩形框 21 private final static int PRESS_RB = 2;//表示右下角矩形框 22 private final static int PRESS_RT = 3;//表示右上角矩形框 23 24 private Bitmap bitMap = null; //原始图片 25 private RectF src = http://www.mamicode.com/null; //经过比例转换后的裁剪区域 26 private RectF dst = null; //图片显示区域(可被裁剪的区域大小) 27 private RectF ChooseArea = null; //选择需要裁剪的区域 28 private Paint mPaint = null; //画笔 29 private Matrix matrix = null; //矩阵 30 31 private int mx = 0; //存储触笔移动时,之前所在的触笔的x坐标 32 private int my = 0; //存储触笔移动时,之前所在的触笔的y坐标 33 private boolean touchFlag = false; //触笔是否在屏幕之上 34 private boolean cutFlag = false; //是否点击了menu上的裁剪按钮 35 private int recFlag = -1; //用来存储触笔点击了哪个小矩形框(改变选择区域大小的小矩形框) 36 private boolean firstFlag = false; 37 38 private RectF recLT = null; //左上角的小矩形框 39 private RectF recRT = null; //右上角的小矩形框 40 private RectF recLB = null; //左下角的小矩形框 41 private RectF recRB = null; //右下角的小矩形框 42 private static final int LEFT_AREA_ALPHA = 50 * 255 / 100; 43 private RectF leftRectL = null; 44 private RectF leftRectR = null; 45 private RectF leftRectT = null; 46 private RectF leftRectB = null; 47 private Paint leftAreaPaint = null; 48 49 public CropCanvas(Context context, AttributeSet attrs) { 50 super(context, attrs); 51 this.init(); 52 } 53 54 public CropCanvas(Context context) { 55 super(context); 56 this.init(); 57 } 58 59 public void init(){ 60 cutFlag = true; 61 recLT = new RectF(); 62 recLB = new RectF(); 63 recRT = new RectF(); 64 recRB = new RectF(); 65 dst = new RectF(); 66 mPaint = new Paint(); 67 mPaint.setColor(Color.RED); 68 mPaint.setStyle(Paint.Style.STROKE); //将画笔的风格改为空心 69 mPaint.setStrokeWidth(2); 70 ChooseArea = new RectF(); 71 this.setPressRecLoc(); 72 src = http://www.mamicode.com/null; 73 firstFlag = true; 74 75 //选择框之外的灰色区域,分成四个矩形框 76 77 leftAreaPaint = new Paint(); 78 leftAreaPaint.setStyle(Paint.Style.FILL); 79 leftAreaPaint.setAlpha(CropCanvas.LEFT_AREA_ALPHA); 80 } 81 82 public void setBitmap(Bitmap bitmap){ 83 BitmapDrawable bd = new BitmapDrawable(bitmap); 84 src = http://www.mamicode.com/new RectF(0,0,bd.getIntrinsicWidth(),bd.getIntrinsicHeight()); 85 this.bitMap = bitmap.copy(Config.ARGB_8888, true); 86 87 this.setImageBitmap(bitMap); 88 leftRectB = new RectF(); 89 leftRectL = new RectF(); 90 leftRectR = new RectF(); 91 leftRectT = new RectF(); 92 } 93 94 public void imageScale(){ 95 matrix = this.getImageMatrix(); 96 matrix.mapRect(dst, src); 97 int padding = this.getPaddingBottom(); 98 dst.set(dst.left+padding,dst.top+padding,dst.right+padding,dst.bottom+padding); 99 ChooseArea = new RectF(dst.left+40,dst.top+40,dst.right-40,dst.bottom-40);100 this.setPressRecLoc();101 this.invalidate();102 }103 104 //裁剪出选择区域里的图片105 //之前要做比例转换,因为,你选择的区域是针对比例转换后的图片106 //所以要使用ChooseArea的数值做比例转换,然后,使用这些数值重新设置rec的大小107 public Bitmap getSubsetBitmap(){108 float ratioWidth = bitMap.getWidth()/(float)(dst.right-dst.left);109 float ratioHeight = bitMap.getHeight()/(float)(dst.bottom - dst.top);110 int left = (int)((ChooseArea.left - dst.left) * ratioWidth);111 int right = (int)(left + (ChooseArea.right - ChooseArea.left) * ratioWidth);112 int top = (int)((ChooseArea.top - dst.top) * ratioHeight);113 int bottom = (int)(top + (ChooseArea.bottom - ChooseArea.top) * ratioHeight);114 src = http://www.mamicode.com/new RectF(left,top,right,bottom);115 firstFlag = true;116 set_LeftArea_Alpha();117 return Bitmap.createBitmap(bitMap, left, top, right-left, bottom-top);118 }119 120 //获得ChooseArea对象121 public RectF getChooseArea(){122 return ChooseArea;123 }124 125 //移动选择区域,选择区域是不能从图片区域里移出去的126 public void moveChooseArea(int move_x,int move_y){127 if(ChooseArea.left + move_x >= dst.left && ChooseArea.right + move_x <= dst.right128 && ChooseArea.top + move_y >= dst.top && ChooseArea.bottom + move_y <= dst.bottom){129 ChooseArea.set(ChooseArea.left + move_x,ChooseArea.top+move_y130 ,ChooseArea.right + move_x,ChooseArea.bottom+move_y);131 }else{132 if(ChooseArea.left + move_x < dst.left){133 ChooseArea.set(dst.left,ChooseArea.top134 ,ChooseArea.right+dst.left-ChooseArea.left,ChooseArea.bottom);135 }136 if(ChooseArea.right + move_x > dst.right){137 ChooseArea.set(ChooseArea.left+dst.right-ChooseArea.right,ChooseArea.top138 ,dst.right,ChooseArea.bottom);139 }140 141 if(ChooseArea.top + move_y < dst.top){142 ChooseArea.set(ChooseArea.left,dst.top143 ,ChooseArea.right,ChooseArea.bottom+dst.top-ChooseArea.top);144 }145 146 if(ChooseArea.bottom + move_y > dst.bottom){147 ChooseArea.set(ChooseArea.left,ChooseArea.top+dst.bottom-ChooseArea.bottom148 ,ChooseArea.right,dst.bottom);149 }150 }151 this.setPressRecLoc();152 mPaint.setColor(Color.GREEN);153 this.invalidate();154 }155 156 public boolean onTouchEvent(MotionEvent event){157 mPaint.setColor(Color.RED);158 159 //点击了裁剪按钮之后才会执行以下事件160 if(event.getAction() == MotionEvent.ACTION_DOWN && cutFlag){161 //System.out.println(event.getX() + "," + event.getY());162 //判断触笔是否在裁剪区域内,也就是ChooseArea内163 //如果是,整个区域随着鼠标移动而移动164 mx = (int)event.getX();165 my = (int)event.getY();166 if(this.judgeLocation(mx,my)){167 touchFlag = true;168 mPaint.setColor(Color.GREEN);169 this.invalidate();170 return true;171 }else{172 //不在裁剪区域内,就判断触笔是否在改变区域大小的小矩形框之内173 if(this.findPresseddst((int)event.getX(), (int)event.getY())){174 touchFlag = true;175 mPaint.setColor(Color.RED);176 return true;177 }178 }179 }180 181 if(event.getAction() == MotionEvent.ACTION_MOVE && touchFlag){182 //判断是否点击了哪个个小矩形框183 if(this.isOutOfArea((int)event.getX(), (int)event.getY())){184 return true;185 }186 187 //如果选择区域大小跟图像大小一样时,就不能移动188 if(ChooseArea.left == dst.left && ChooseArea.top == dst.top &&189 ChooseArea.right == dst.right && ChooseArea.bottom == dst.bottom){190 }else{191 this.moveChooseArea((int)event.getX() - mx, (int)event.getY() - my);192 mx = (int)event.getX();193 my = (int)event.getY();194 }195 }196 197 //触笔移出屏幕时,将一些变量设回初值198 if(event.getAction() == MotionEvent.ACTION_UP){199 recFlag = -1;200 this.invalidate();201 touchFlag = false;202 }203 204 return super.onTouchEvent(event);205 }206 207 208 209 //判断是否要超出图片区域,这个函数会调用下面四个press打头的函数210 //这个函数也会重绘整个画布,也就是选择区域会随着鼠标的移动改变211 private boolean isOutOfArea(int x,int y){212 switch(recFlag){213 case CropCanvas.PRESS_LB:214 this.pressLB(x - mx, y - my);215 break;216 case CropCanvas.PRESS_LT:217 this.pressLT(x - mx, y - my);218 break;219 case CropCanvas.PRESS_RB:220 this.pressRB(x - mx, y - my);221 break;222 case CropCanvas.PRESS_RT:223 this.pressRT(x - mx, y - my);224 break;225 default:return false;226 }227 mx = x;228 my = y;229 this.invalidate();230 return true;231 }232 233 //找到点击了哪个矩形框(改变选择区域大小的小矩形框)234 //这个是在MotionEvent.ACTION_DOWN这个动作时执行的235 //是为了在MotionEvent.ACTION_MOVE的时候,知道应该移动哪个小矩形框236 public boolean findPresseddst(int x,int y){237 boolean returnFlag = false;238 if(this.isInRect(x, y, recLB)){239 recFlag = CropCanvas.PRESS_LB;240 returnFlag = true;241 }else if(this.isInRect(x, y, recLT)){242 recFlag = CropCanvas.PRESS_LT;243 returnFlag = true;244 }else if(this.isInRect(x, y, recRB)){245 recFlag = CropCanvas.PRESS_RB;246 returnFlag = true;247 }else if(this.isInRect(x, y, recRT)){248 recFlag = CropCanvas.PRESS_RT;249 returnFlag = true;250 }251 252 return returnFlag;253 }254 255 public boolean isInRect(int x,int y,RectF rect){256 if(x >= rect.left -20 && x <= rect.right + 20 && y > rect.top - 20 && y < rect.bottom + 20){257 return true;258 }259 return false;260 }261 262 //点击角落矩形框改变选择区域大小时,不能超过图片所在的区域263 //下面以press打头的四个函数就是判断是否超出图片区域264 //如果超出了,就移动不了265 //不超出按照触笔移动的距离来移动小矩形框266 267 //pressLB是当点击左下角小矩形框改变大小时是否超出图片区域268 //如果超出就将left与bottom的值设为图片区域的left和bottom269 private void pressLB(int x,int y){270 float left = ChooseArea.left + x;271 float right = ChooseArea.right;272 float top = ChooseArea.top;273 float bottom = ChooseArea.bottom + y;274 if(left <= right - 30 && left >= dst.left && bottom <= dst.bottom && bottom >= top + 30){275 ChooseArea.set(left,top,right,bottom);276 }else{277 if(left + x < dst.left){278 left = dst.left;279 }280 281 if(bottom + y > dst.bottom){282 bottom = dst.bottom;283 }284 285 if(ChooseArea.left + x > ChooseArea.right - 30){286 left = ChooseArea.right - 30;287 }288 289 if(ChooseArea.bottom + y < ChooseArea.top + 30){290 bottom = ChooseArea.top + 30;291 }292 ChooseArea.set(left,top,right,bottom);293 }294 this.setPressRecLoc();295 }296 297 //pressLT是当点击左上角小矩形框改变大小时是否超出图片区域298 //如果超出就将left与top的值设为图片区域的left和top299 private void pressLT(int x,int y){300 float left = ChooseArea.left + x;301 float right = ChooseArea.right;302 float top = ChooseArea.top + y;303 float bottom = ChooseArea.bottom;304 if(left <= right - 30 && left >= dst.left && top <= bottom - 30 && top >= dst.top){305 ChooseArea.set(left,top,right,bottom);306 }else{307 if(left < dst.left){308 left = dst.left;309 }310 311 if(top < dst.top){312 top = dst.top;313 }314 315 if(left > right - 30){316 left = right - 30;317 }318 319 if(top > bottom - 30){320 top = bottom - 30;321 }322 ChooseArea.set(left,top,right,bottom);323 }324 this.setPressRecLoc();325 }326 327 //pressRT是当点击右上角小矩形框改变大小时是否超出图片区域328 //如果超出就将right与top的值设为图片区域的right和top329 private void pressRT(int x,int y){330 float left = ChooseArea.left;331 float right = ChooseArea.right + x;332 float top = ChooseArea.top + y;333 float bottom = ChooseArea.bottom;334 335 if(right <= dst.right && right >= left + 30 && top <= bottom - 30 && top >= dst.top){336 ChooseArea.set(left,top,right,bottom);337 }else{338 if(right > dst.right){339 right = dst.right;340 }341 342 if(top < dst.top){343 top = dst.top;344 }345 346 if(right < left + 30){347 right = left + 30;348 }349 350 if(top > bottom - 30){351 top = bottom - 30;352 }353 ChooseArea.set(left,top,right,bottom);354 }355 this.setPressRecLoc();356 }357 358 //pressRB是当点击右下角小矩形框改变大小时是否超出图片区域359 //如果超出就将right与bottom的值设为图片区域的right和bottom360 private void pressRB(int x,int y){361 float left = ChooseArea.left;362 float right = ChooseArea.right + x;363 float top = ChooseArea.top;364 float bottom = ChooseArea.bottom + y;365 366 if(right<= dst.right && right >= left + 30 && bottom <= dst.bottom && bottom >= top + 30){367 ChooseArea.set(left,top,right,bottom);368 }else{369 if(right > dst.right){370 right = dst.right;371 }372 373 if(bottom > dst.bottom){374 bottom = dst.bottom;375 }376 377 if(right < left + 30){378 right = left + 30;379 }380 381 if(bottom < top + 30){382 bottom = top + 30;383 }384 ChooseArea.set(left,top,right,bottom);385 }386 this.setPressRecLoc();387 }388 389 //每次改变选择区域矩形的大小或者移动,各角落上的小矩形也要改变它的Location390 private void setPressRecLoc(){391 recLT.set(ChooseArea.left-8,ChooseArea.top-8 , ChooseArea.left+8, ChooseArea.top+8);392 recLB.set(ChooseArea.left-8,ChooseArea.bottom-8 , ChooseArea.left+8, ChooseArea.bottom+8);393 recRT.set(ChooseArea.right-8,ChooseArea.top-8 , ChooseArea.right+8, ChooseArea.top+8);394 recRB.set(ChooseArea.right-8,ChooseArea.bottom-8 , ChooseArea.right+8, ChooseArea.bottom+8);395 }396 397 //判断触笔是否在选择区域内398 public boolean judgeLocation(float x,float y){399 float start_x = this.getChooseArea().left;400 float start_y = this.getChooseArea().top;401 float last_x = this.getChooseArea().right;402 float last_y = this.getChooseArea().bottom;403 //System.out.println("chubi:" + x + "," + y);404 //System.out.println(start_y + "," + last_y);405 if(x > start_x+10 && x < last_x-10 && y > start_y+10 && y < last_y-10){406 return true;407 }408 return false;409 }410 411 public void onDraw(Canvas canvas){412 super.onDraw(canvas);413 if(firstFlag){414 this.imageScale();415 firstFlag = false;416 mPaint.setColor(Color.RED);417 System.out.println("Width: " + (dst.right - dst.left));418 System.out.println("Height: " + (dst.bottom - dst.top));419 System.out.println("Width: " + this.getDrawable().getIntrinsicWidth());420 System.out.println("Height: " + this.getDrawable().getIntrinsicHeight());421 }else{422 set_LeftArea_Alpha();423 }424 canvas.drawRect(ChooseArea, mPaint);425 mPaint.setColor(Color.BLUE);426 canvas.drawRect(recLT, mPaint);427 canvas.drawRect(recLB, mPaint);428 canvas.drawRect(recRT, mPaint); 429 canvas.drawRect(recRB, mPaint);430 431 canvas.drawRect(leftRectL, leftAreaPaint);432 canvas.drawRect(leftRectR, leftAreaPaint);433 canvas.drawRect(leftRectT, leftAreaPaint);434 canvas.drawRect(leftRectB, leftAreaPaint);435 436 }437 438 public void set_LeftArea_Alpha(){439 leftRectL.set(dst.left, dst.top, ChooseArea.left, dst.bottom);440 leftRectR.set(ChooseArea.right,dst.top,dst.right,dst.bottom);441 leftRectT.set(ChooseArea.left, dst.top, ChooseArea.right, ChooseArea.top);442 leftRectB.set(ChooseArea.left,ChooseArea.bottom,ChooseArea.right,dst.bottom);443 } 444 }
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <LinearLayout android:layout_width="fill_parent" android:layout_height="150px" android:layout_alignParentTop="true" android:layout_weight="1" android:background="#191919" android:orientation="horizontal" > </LinearLayout> <com.jichun.view.CropCanvas android:id="@+id/myCanvas" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginBottom="5px" android:layout_marginTop="5px" android:layout_weight="1" android:background="#313131" android:padding="2dip" > </com.jichun.view.CropCanvas> <RelativeLayout android:layout_width="fill_parent" android:layout_height="150px" android:layout_weight="1" android:background="#191919" > <ImageButton android:id="@+id/confirm_button" android:layout_width="70px" android:layout_height="fill_parent" android:layout_alignParentRight="true" android:background="#00000000" android:src="@drawable/confirmxml" > </ImageButton> <ImageButton android:id="@+id/exit_button" android:layout_width="70px" android:layout_height="fill_parent" android:layout_alignParentLeft="true" android:background="#00000000" android:src="@drawable/exitxml" > </ImageButton> </RelativeLayout></LinearLayout>
1 <?xml version="1.0" encoding="utf-8" ?> 2 <selector xmlns:android="http://schemas.android.com/apk/res/android"> 3 <item android:state_window_focused="false" 4 android:drawable="@drawable/confirm" /> 5 6 <item android:state_focused="true" android:state_pressed="true" 7 android:drawable="@drawable/confirm_focus" /> 8 <item android:state_focused="false" android:state_pressed="true" 9 android:drawable="@drawable/confirm_focus" /> 10 11 <item android:state_focused="true" 12 android:drawable="@drawable/confirm_focus" /> 13 </selector>
完整项目下载链接:http://pan.baidu.com/s/1c08a4Re
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。