最近在做毕业设计,想有一个功能和QQ一样可以裁剪头像并设置圆形头像,额,这是设计狮的一种潮流。
而纵观现在主流的APP,只要有用户系统这个功能,这个需求一般都是在(bu)劫(de)难(bu)逃(xue)!
图片裁剪实现方式有两种,一种是利用系统自带的裁剪工具,一种是使用开源工具Cropper。本节就为大家带来如何使用系统自带的裁剪工具进行图片裁剪~
还是先来个简单的运行图。(Ps,本人还没结婚,照片是我表哥~)
额,简单说下,我待会会把代码写成小demo分享给大家,在文章末尾会附上github链接,需要的可以自行下载~
下面来简单分析一下实现思路,我们首先照片肯定可以通过拍照和从相册选取,这个都可以向系统发送特定的Intent,响应对应的系统程序,然后在onActivityResult里面,获取我们的数据即可。而在onActivityResult里面,我们可以获取到两种形式的数据,Bitmap and uri。一般情况下我们是不会选择Bitmap的,因为大家都知道我们的手机里面的照片都太大了~强行使用bitmap,我只能说你,屌屌屌,sorry,我说的不是666,是傻屌的意思!
哈哈哈,让我爆粗口,我原本是拒绝的~只是希望警醒在看文章的你,那么就用uri吧~
那么然后呢?当然是对它做裁剪,完成后把这个裁剪后的bitmap对象设置给ImageView,保存起来,上传到服务器即可。
大致了解了流程,那么我们直接看代码吧~
先看看我们的圆形Image吧,我这个有点乱,因为考虑了很多我毕设的逻辑,所以做了一些修正,这个圆形Image相信网上会很多。
1 package com.example.nanchen.cropimagetest; 2 3 import android.content.Context; 4 import android.content.res.TypedArray; 5 import android.graphics.Bitmap; 6 import android.graphics.Bitmap.Config; 7 import android.graphics.Canvas; 8 import android.graphics.Color; 9 import android.graphics.ColorMatrix; 10 import android.graphics.ColorMatrixColorFilter; 11 import android.graphics.Paint; 12 import android.graphics.PorterDuff.Mode; 13 import android.graphics.PorterDuffXfermode; 14 import android.graphics.Rect; 15 import android.graphics.RectF; 16 import android.util.AttributeSet; 17 import android.view.MotionEvent; 18 import android.view.View; 19 import android.widget.ImageView; 20 21 /** 22 * @author nanchen 23 * @fileName CropImageTest 24 * @packageName com.example.nanchen.cropimagetest 25 * @date 2016/10/13 15:09 26 */ 27 28 public class RoundImageView extends ImageView { 29 30 /** 31 * 圆形ImageView,可设置最多两个宽度不同且颜色不同的圆形边框。 32 * 33 * @author Alan 34 */ 35 36 private static class imageview_level { 37 public final static int level0 = 0; 38 public final static int level1 = 1; 39 public final static int level2 = 2; 40 public final static int level3 = 3; 41 public final static int level4 = 4; 42 } 43 44 45 private Context mContext; 46 private int circleColor = Color.WHITE; 47 private int circleWidth = 0; 48 private int mLevel = imageview_level.level1; 49 50 public void setLevel(int level) { 51 mLevel = level; 52 } 53 public RoundImageView(Context context) { 54 super(context); 55 mContext = context; 56 } 57 58 public RoundImageView(Context context, AttributeSet attrs) { 59 super(context, attrs); 60 mContext = context; 61 setCustomAttributes(attrs); 62 } 63 64 public RoundImageView(Context context, AttributeSet attrs, int defStyle) { 65 super(context, attrs, defStyle); 66 mContext = context; 67 setCustomAttributes(attrs); 68 } 69 70 private void setCustomAttributes(AttributeSet attrs) { 71 TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.roundedimageview); 72 int width = a.getDimensionPixelSize(R.styleable.roundedimageview_border_thickness, 0); 73 setPadding(width, width, width, width); 74 mLevel = a.getInt(R.styleable.roundedimageview_image_mode, imageview_level.level1); 75 circleColor = a.getColor(R.styleable.roundedimageview_border_color, circleColor); 76 } 77 78 79 @Override 80 public void setImageBitmap(Bitmap bm) { 81 switch (this.mLevel) { 82 case imageview_level.level1 : 83 bm = RoundBitmap(bm); 84 case imageview_level.level2 : 85 if ((getPaddingLeft() == getPaddingRight()) && (getPaddingLeft() == getPaddingBottom()) 86 && (getPaddingLeft() == getPaddingTop())) { 87 this.circleWidth = getPaddingLeft(); 88 bm = RoundBitmap(bm); 89 } 90 break; 91 case imageview_level.level3 : 92 bm = ChamferBitmap(bm); 93 break; 94 case imageview_level.level4: 95 if ((getPaddingLeft() == getPaddingRight()) && (getPaddingLeft() == getPaddingBottom()) 96 && (getPaddingLeft() == getPaddingTop())) { 97 this.circleWidth = getPaddingLeft(); 98 bm = RoundBitmap(bm); 99 } 100 break; 101 default : 102 break; 103 } 104 super.setImageBitmap(bm); 105 } 106 107 @Override 108 protected void onDraw(Canvas canvas) { 109 switch (this.mLevel) { 110 case imageview_level.level2: 111 if (circleWidth > 0) { 112 drawCircleBorder(canvas, (getWidth() - this.circleWidth*2 + circleWidth) / 2, this.circleColor, getWidth(), 113 getHeight(), this.circleWidth); 114 } 115 break; 116 case imageview_level.level4: 117 if (circleWidth > 0){ 118 int paddingwidth = circleWidth; 119 120 drawCircleBorder(canvas, (getWidth()-paddingwidth*2 +circleWidth /2) / 2, this.circleColor, getWidth(), 121 getHeight(), this.circleWidth /2,Color.DKGRAY); 122 123 int tempwidth = circleWidth /2; 124 drawCircleBorder(canvas, (getWidth()-paddingwidth*2 +tempwidth) / 2, this.circleColor, getWidth(), 125 getHeight(), tempwidth,Color.DKGRAY); 126 127 } 128 break; 129 default: 130 break; 131 } 132 super.onDraw(canvas); 133 } 134 135 /** 136 * bitmap切成圆形 137 * 138 * @param bitmap 传入Bitmap对象 139 * @return 140 */ 141 private Bitmap RoundBitmap(Bitmap bitmap) { 142 Bitmap resultBitmap = null; 143 Canvas canvas = null; 144 int width = bitmap.getWidth(); 145 int height = bitmap.getHeight(); 146 float roundPx; 147 float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom; 148 if (width <= height) { 149 roundPx = width / 2; 150 top = 0; 151 bottom = width; 152 left = 0; 153 right = width; 154 height = width; 155 dst_left = 0; 156 dst_top = 0; 157 dst_right = width; 158 dst_bottom = width; 159 } else { 160 roundPx = height / 2; 161 float clip = (width - height) / 2; 162 left = clip; 163 right = width - clip; 164 top = 0; 165 bottom = height; 166 width = height; 167 dst_left = 0; 168 dst_top = 0; 169 dst_right = height; 170 dst_bottom = height; 171 } 172 if (width <= 0) { 173 width = 1; 174 } 175 if (height <= 0) { 176 height = 1; 177 } 178 179 try { 180 resultBitmap = Bitmap.createBitmap(width, height, Config.ARGB_4444); 181 } catch (Throwable e) { 182 e.printStackTrace(); 183 } 184 185 try { 186 canvas = new Canvas(resultBitmap); 187 } catch (Throwable e) { 188 e.printStackTrace(); 189 } 190 191 final int color = Color.RED; 192 final Paint paint = new Paint(); 193 final Rect src = new Rect((int) left, (int) top, (int) right, (int) bottom); 194 final Rect dst = new Rect((int) dst_left, (int) dst_top, (int) dst_right, (int) dst_bottom); 195 final RectF rectF = new RectF(dst); 196 paint.setAntiAlias(true); 197 canvas.drawARGB(0, 0, 0, 0); 198 // paint.setColor(color); 199 canvas.drawRoundRect(rectF, roundPx, roundPx, paint); 200 paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 201 canvas.drawBitmap(bitmap, src, dst, paint); 202 return resultBitmap; 203 } 204 205 /** 206 * bitmap倒角 207 * 208 * @param bitmap 传入Bitmap对象 209 * @return 210 */ 211 private Bitmap ChamferBitmap(Bitmap bitmap) { 212 Bitmap resultBitmap = null; 213 Canvas canvas = null; 214 int width = bitmap.getWidth(); 215 int height = bitmap.getHeight(); 216 float roundPx; 217 float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom; 218 if (width <= height) { 219 roundPx = dip2px(this.mContext, 4); // 8像素倒角 4是dp值 220 top = 0; 221 bottom = width; 222 left = 0; 223 right = width; 224 height = width; 225 dst_left = 0; 226 dst_top = 0; 227 dst_right = width; 228 dst_bottom = width; 229 } else { 230 roundPx = dip2px(this.mContext, 4); // 8像素倒角 4是dp值 231 float clip = (width - height) / 2; 232 left = clip; 233 right = width - clip; 234 top = 0; 235 bottom = height; 236 width = height; 237 dst_left = 0; 238 dst_top = 0; 239 dst_right = height; 240 dst_bottom = height; 241 } 242 if (width <= 0) { 243 width = 1; 244 } 245 if (height <= 0) { 246 height = 1; 247 } 248 249 try { 250 resultBitmap = Bitmap.createBitmap(width, height, Config.ARGB_4444); 251 } catch (Throwable e) { 252 e.printStackTrace(); 253 } 254 255 try { 256 canvas = new Canvas(resultBitmap); 257 } catch (Throwable e) { 258 e.printStackTrace(); 259 } 260 261 final int color = Color.RED; 262 final Paint paint = new Paint(); 263 final Rect src = new Rect((int) left, (int) top, (int) right, (int) bottom); 264 final Rect dst = new Rect((int) dst_left, (int) dst_top, (int) dst_right, (int) dst_bottom); 265 final RectF rectF = new RectF(dst); 266 paint.setAntiAlias(true); 267 canvas.drawARGB(0, 0, 0, 0); 268 // paint.setColor(color); 269 canvas.drawRoundRect(rectF, roundPx, roundPx, paint); 270 paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 271 canvas.drawBitmap(bitmap, src, dst, paint); 272 return resultBitmap; 273 } 274 275 /** 276 * 画布画圆 277 */ 278 private void drawCircleBorder(Canvas canvas, int radius, int color, int width, int height, int circleWidth) { 279 Paint paint = new Paint(); 280 /* 去锯齿 */ 281 paint.setAntiAlias(true); 282 paint.setFilterBitmap(true); 283 paint.setDither(true); 284 paint.setColor(color); 285 /* 设置paint的 style 为STROKE:空心 */ 286 paint.setStyle(Paint.Style.STROKE); 287 /* 设置paint的外框宽度 */ 288 paint.setStrokeWidth(circleWidth); 289 canvas.drawCircle(width / 2, height / 2, radius, paint); 290 } 291 292 private void drawCircleBorder(Canvas canvas, int radius, int color, int width, int height, int circleWidth,int shadowcolor){ 293 294 canvas.save(); //保存画布当前状态 295 canvas.rotate(45,width / 2, height / 2); //右下角45度阴影投射 296 Paint paint = new Paint(); 297 paint.setColor(0x09ffffff & shadowcolor ); //设置alpha值 298 for(int i=0;i<circleWidth*2;i++) //向下角角偏移投射多少次阴影层 299 { 300 canvas.drawCircle(width/2+i, height / 2, radius+2, paint); 301 } 302 canvas.restore(); 303 304 paint = new Paint(); 305 /* 去锯齿 */ 306 paint.setAntiAlias(true); 307 paint.setFilterBitmap(true); 308 paint.setDither(true); 309 paint.setColor(color); 310 /* 设置paint的 style 为STROKE:空心 */ 311 paint.setStyle(Paint.Style.STROKE); 312 /* 设置paint的外框宽度 */ 313 paint.setStrokeWidth(circleWidth); //二分之一实体 314 canvas.drawCircle(width / 2, height / 2, radius, paint); 315 } 316 317 public void setCircleWidth(int padding) { 318 setPadding(padding, padding, padding, padding); 319 } 320 321 public int getCircleColor() { 322 return circleColor; 323 } 324 325 public void setCircleColor(int circleColor) { 326 this.circleColor = circleColor; 327 } 328 329 // 执行完setImageBitmap后才能获得; 330 public int getCircleWidth() { 331 return this.circleWidth; 332 } 333 334 public OnTouchListener onTouchListener = new OnTouchListener() { 335 @Override 336 public boolean onTouch(View view, MotionEvent event) { 337 switch (event.getAction()) { 338 case MotionEvent.ACTION_UP: 339 changeLight((ImageView) view, 0); 340 // onclick 341 break; 342 case MotionEvent.ACTION_DOWN: 343 changeLight((ImageView) view, -60); 344 break; 345 case MotionEvent.ACTION_MOVE: 346 // changeLight((ImageView) view, 0); 347 break; 348 case MotionEvent.ACTION_CANCEL: 349 changeLight((ImageView) view, 0); 350 break; 351 default: 352 break; 353 } 354 return false; 355 } 356 }; 357 358 public void setColorFilter(boolean value){ 359 if(value){ 360 setOnTouchListener(onTouchListener); 361 }else{ 362 setOnTouchListener(null); 363 } 364 } 365 366 private void changeLight(ImageView imageview, int brightness) { 367 ColorMatrix matrix = new ColorMatrix(); 368 matrix.set(new float[] { 1, 0, 0, 0, brightness, 0, 1, 0, 0, brightness, 0, 0, 1, 0, brightness, 0, 0, 0, 1, 0 }); 369 imageview.setColorFilter(new ColorMatrixColorFilter(matrix)); 370 } 371 372 /** 373 * 根据手机的分辨率从 dp 的单位 转成为 px(像素) 374 */ 375 private int dip2px(Context context, float dpValue) { 376 final float scale = context.getApplicationContext().getResources().getDisplayMetrics().density; 377 return (int) (dpValue * scale + 0.5f); 378 } 379 380 381 }
自定义一个仿IOS的弹出框
1 package com.example.nanchen.cropimagetest; 2 3 import android.app.Activity; 4 import android.app.Dialog; 5 import android.os.Bundle; 6 import android.text.TextUtils; 7 import android.view.LayoutInflater; 8 import android.view.View; 9 import android.view.View.OnClickListener; 10 import android.view.ViewGroup; 11 import android.view.ViewGroup.LayoutParams; 12 import android.view.Window; 13 import android.view.WindowManager; 14 import android.widget.AdapterView; 15 import android.widget.AdapterView.OnItemClickListener; 16 import android.widget.BaseAdapter; 17 import android.widget.Button; 18 import android.widget.ListView; 19 import android.widget.TextView; 20 21 import java.util.List; 22 23 24 /** 25 * dialog 26 * 27 */ 28 public class SelectDialog extends Dialog implements OnClickListener,OnItemClickListener { 29 private SelectDialogListener mListener; 30 private Activity mActivity; 31 private Button mMBtn_Cancel; 32 private TextView mTv_Title; 33 private List<String> mName; 34 private String mTitle; 35 private boolean mUseCustomColor = false; 36 private int mFirstItemColor; 37 private int mOtherItemColor; 38 39 public interface SelectDialogListener { 40 public void onItemClick(AdapterView<?> parent, View view, int position, long id); 41 } 42 43 44 private SelectDialogCancelListener mCancelListener; 45 46 public interface SelectDialogCancelListener { 47 public void onCancelClick(View v); 48 } 49 50 public SelectDialog(Activity activity, int theme, 51 SelectDialogListener listener,List<String> names) { 52 super(activity, theme); 53 mActivity = activity; 54 mListener = listener; 55 this.mName=names; 56 57 // 设置是否点击外围解散 58 setCanceledOnTouchOutside(true); 59 } 60 61 /** 62 * @param activity 调用弹出菜单的activity 63 * @param theme 主题 64 * @param listener 菜单项单击事件 65 * @param cancelListener 取消事件 66 * @param names 菜单项名称 67 * 68 */ 69 public SelectDialog(Activity activity, int theme,SelectDialogListener listener,SelectDialogCancelListener cancelListener ,List<String> names) { 70 super(activity, theme); 71 mActivity = activity; 72 mListener = listener; 73 mCancelListener = cancelListener; 74 this.mName=names; 75 76 // 设置是否点击外围不解散 77 setCanceledOnTouchOutside(false); 78 } 79 80 /** 81 * @param activity 调用弹出菜单的activity 82 * @param theme 主题 83 * @param listener 菜单项单击事件 84 * @param names 菜单项名称 85 * @param title 菜单标题文字 86 * 87 */ 88 public SelectDialog(Activity activity, int theme,SelectDialogListener listener,List<String> names,String title) { 89 super(activity, theme); 90 mActivity = activity; 91 mListener = listener; 92 this.mName=names; 93 mTitle = title; 94 95 // 设置是否点击外围可解散 96 setCanceledOnTouchOutside(true); 97 } 98 99 public SelectDialog(Activity activity, int theme,SelectDialogListener listener,SelectDialogCancelListener cancelListener,List<String> names,String title) { 100 super(activity, theme); 101 mActivity = activity; 102 mListener = listener; 103 mCancelListener = cancelListener; 104 this.mName=names; 105 mTitle = title; 106 107 // 设置是否点击外围可解散 108 setCanceledOnTouchOutside(true); 109 } 110 111 @Override 112 protected void onCreate(Bundle savedInstanceState) { 113 super.onCreate(savedInstanceState); 114 View view = getLayoutInflater().inflate(R.layout.view_dialog_select, 115 null); 116 setContentView(view, new LayoutParams(LayoutParams.FILL_PARENT, 117 LayoutParams.WRAP_CONTENT)); 118 Window window = getWindow(); 119 // 设置显示动画 120 window.setWindowAnimations(R.style.main_menu_animstyle); 121 WindowManager.LayoutParams wl = window.getAttributes(); 122 wl.x = 0; 123 wl.y = mActivity.getWindowManager().getDefaultDisplay().getHeight(); 124 // 以下这两句是为了保证按钮可以水平满屏 125 wl.width = LayoutParams.MATCH_PARENT; 126 wl.height = LayoutParams.WRAP_CONTENT; 127 128 // 设置显示位置 129 onWindowAttributesChanged(wl); 130 131 //setCanceledOnTouchOutside(false); 132 initViews(); 133 } 134 135 private void initViews() { 136 DialogAdapter dialogAdapter=new DialogAdapter(mName); 137 ListView dialogList=(ListView) findViewById(R.id.dialog_list); 138 dialogList.setOnItemClickListener(this); 139 dialogList.setAdapter(dialogAdapter); 140 mMBtn_Cancel = (Button) findViewById(R.id.mBtn_Cancel); 141 mTv_Title = (TextView) findViewById(R.id.mTv_Title); 142 143 //mMBtn_Cancel.setOnClickListener(this); 144 145 mMBtn_Cancel.setOnClickListener(new View.OnClickListener() { 146 147 @Override 148 public void onClick(View v) { 149 // TODO Auto-generated method stub 150 if(mCancelListener != null){ 151 mCancelListener.onCancelClick(v); 152 } 153 dismiss(); 154 } 155 }); 156 157 if(!TextUtils.isEmpty(mTitle) && mTv_Title != null){ 158 mTv_Title.setVisibility(View.VISIBLE); 159 mTv_Title.setText(mTitle); 160 }else{ 161 mTv_Title.setVisibility(View.GONE); 162 } 163 } 164 165 @Override 166 public void onClick(View v) { 167 dismiss(); 168 169 } 170 171 @Override 172 public void onItemClick(AdapterView<?> parent, View view, int position, 173 long id) { 174 175 mListener.onItemClick(parent, view, position, id); 176 dismiss(); 177 } 178 private class DialogAdapter extends BaseAdapter { 179 private List<String> mStrings; 180 private Viewholder viewholder; 181 private LayoutInflater layoutInflater; 182 public DialogAdapter(List<String> strings) { 183 this.mStrings = strings; 184 this.layoutInflater=mActivity.getLayoutInflater(); 185 } 186 187 @Override 188 public int getCount() { 189 // TODO Auto-generated method stub 190 return mStrings.size(); 191 } 192 193 @Override 194 public Object getItem(int position) { 195 // TODO Auto-generated method stub 196 return mStrings.get(position); 197 } 198 199 @Override 200 public long getItemId(int position) { 201 // TODO Auto-generated method stub 202 return position; 203 } 204 205 @Override 206 public View getView(int position, View convertView, ViewGroup parent) { 207 if (null == convertView) { 208 viewholder=new Viewholder(); 209 convertView=layoutInflater.inflate(R.layout.view_dialog_item, null); 210 viewholder.dialogItemButton=(TextView) convertView.findViewById(R.id.dialog_item_bt); 211 convertView.setTag(viewholder); 212 }else{ 213 viewholder=(Viewholder) convertView.getTag(); 214 } 215 viewholder.dialogItemButton.setText(mStrings.get(position)); 216 if (!mUseCustomColor) { 217 mFirstItemColor = mActivity.getResources().getColor(R.color.dialog_blue); 218 mOtherItemColor = mActivity.getResources().getColor(R.color.dialog_blue); 219 } 220 if (1 == mStrings.size()) { 221 viewholder.dialogItemButton.setTextColor(mFirstItemColor); 222 viewholder.dialogItemButton.setBackgroundResource(R.drawable.dialog_item_bg_only); 223 } else if (position == 0) { 224 viewholder.dialogItemButton.setTextColor(mFirstItemColor); 225 viewholder.dialogItemButton.setBackgroundResource(R.drawable.dialog_item_bg_top); 226 } else if (position == mStrings.size() - 1) { 227 viewholder.dialogItemButton.setTextColor(mOtherItemColor); 228 viewholder.dialogItemButton.setBackgroundResource(R.drawable.dialog_item_bg_buttom); 229 } else { 230 viewholder.dialogItemButton.setTextColor(mOtherItemColor); 231 viewholder.dialogItemButton.setBackgroundResource(R.drawable.dialog_item_bg_center); 232 } 233 return convertView; 234 } 235 236 } 237 238 public static class Viewholder { 239 public TextView dialogItemButton; 240 } 241 242 /** 243 * 设置列表项的文本颜色 244 */ 245 public void setItemColor(int firstItemColor, int otherItemColor) { 246 mFirstItemColor = firstItemColor; 247 mOtherItemColor = otherItemColor; 248 mUseCustomColor = true; 249 } 250 251 }
由于图片文件一定在相册中,有可能你也会在文件系统中其他地方选择,这里我采用之前写的万能适配器!
由于楼主时间的确比较紧,所以代码都是直接copy上来的,有些地方没做完全优化还望大家见谅!
再看看Activity的代码和布局
1 package com.example.nanchen.cropimagetest; 2 3 import android.content.ComponentName; 4 import android.content.DialogInterface; 5 import android.content.DialogInterface.OnCancelListener; 6 import android.content.Intent; 7 import android.content.pm.ResolveInfo; 8 import android.graphics.Bitmap; 9 import android.graphics.Bitmap.CompressFormat; 10 import android.net.Uri; 11 import android.os.Bundle; 12 import android.os.Environment; 13 import android.provider.MediaStore; 14 import android.provider.MediaStore.Images.Media; 15 import android.support.v7.app.AlertDialog; 16 import android.support.v7.app.AlertDialog.Builder; 17 import android.support.v7.app.AppCompatActivity; 18 import android.view.View; 19 import android.widget.AdapterView; 20 21 import com.example.nanchen.cropimagetest.SelectDialog.SelectDialogListener; 22 23 import java.io.File; 24 import java.io.FileOutputStream; 25 import java.io.IOException; 26 import java.util.ArrayList; 27 import java.util.List; 28 29 public class MainActivity extends AppCompatActivity { 30 31 private RoundImageView mHeadImage; 32 33 @Override 34 protected void onCreate(Bundle savedInstanceState) { 35 super.onCreate(savedInstanceState); 36 setContentView(R.layout.activity_main); 37 38 mHeadImage = (RoundImageView) findViewById(R.id.main_roundImage); 39 } 40 41 private final int PHOTO_PICKED_FROM_CAMERA = 1; // 用来标识头像来自系统拍照 42 private final int PHOTO_PICKED_FROM_FILE = 2; // 用来标识从相册获取头像 43 private final int CROP_FROM_CAMERA = 3; 44 45 private void getIconFromPhoto(){ 46 Intent intent = new Intent(Intent.ACTION_GET_CONTENT, Media.EXTERNAL_CONTENT_URI); 47 intent.setType("image/*"); 48 startActivityForResult(intent, PHOTO_PICKED_FROM_FILE); 49 } 50 51 private void selectPhoto() { 52 List<String> list = new ArrayList<>(); 53 list.add("拍照"); 54 list.add("相册"); 55 showDialog(new SelectDialogListener() { 56 @Override 57 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 58 switch (position){ 59 case 0: 60 getIconFromCamera(); 61 break; 62 case 1: 63 getIconFromPhoto(); // 从系统相册获取 64 break; 65 default: 66 break; 67 } 68 } 69 },list); 70 71 } 72 73 private Uri imgUri; // 由于android手机的图片基本都会很大,所以建议用Uri,而不用Bitmap 74 75 /** 76 * 调用系统相机拍照 77 */ 78 private void getIconFromCamera() { 79 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 80 imgUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), 81 "avatar_"+String.valueOf(System.currentTimeMillis())+".png")); 82 intent.putExtra(MediaStore.EXTRA_OUTPUT,imgUri); 83 startActivityForResult(intent,PHOTO_PICKED_FROM_CAMERA); 84 } 85 86 private SelectDialog showDialog(SelectDialogListener listener, List<String> list){ 87 SelectDialog dialog = new SelectDialog(this, 88 R.style.transparentFrameWindowStyle,listener,list); 89 dialog.show(); 90 return dialog; 91 } 92 93 94 /** 95 * 尝试裁剪图片 96 */ 97 private void doCrop(){ 98 final ArrayList<CropOption> cropOptions = new ArrayList<>(); 99 final Intent intent = new Intent("com.android.camera.action.CROP"); 100 intent.setType("image/*"); 101 List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent,0); 102 int size = list.size(); 103 if (size == 0){ 104 UIUtil.showToast(this,"当前不支持裁剪图片!"); 105 return; 106 } 107 intent.setData(imgUri); 108 intent.putExtra("outputX",300); 109 intent.putExtra("outputY",300); 110 intent.putExtra("aspectX",1); 111 intent.putExtra("aspectY",1); 112 intent.putExtra("scale",true); 113 intent.putExtra("return-data",true); 114 115 // only one 116 if (size == 1){ 117 Intent intent1 = new Intent(intent); 118 ResolveInfo res = list.get(0); 119 intent1.setComponent(new ComponentName(res.activityInfo.packageName,res.activityInfo.name)); 120 startActivityForResult(intent1,CROP_FROM_CAMERA); 121 }else { 122 // 很多可支持裁剪的app 123 for (ResolveInfo res : list) { 124 CropOption co = new CropOption(); 125 co.title = getPackageManager().getApplicationLabel(res.activityInfo.applicationInfo); 126 co.icon = getPackageManager().getApplicationIcon(res.activityInfo.applicationInfo); 127 co.appIntent = new Intent(intent); 128 co.appIntent.setComponent(new ComponentName(res.activityInfo.packageName,res.activityInfo.name)); 129 cropOptions.add(co); 130 } 131 132 CommonAdapter<CropOption> adapter = new CommonAdapter<CropOption>(this,cropOptions,R.layout.layout_crop_selector) { 133 @Override 134 public void convert(ViewHolder holder, CropOption item) { 135 holder.setImageDrawable(R.id.iv_icon,item.icon); 136 holder.setText(R.id.tv_name,item.title); 137 } 138 }; 139 140 AlertDialog.Builder builder = new Builder(this); 141 builder.setTitle("choose a app"); 142 builder.setAdapter(adapter, new DialogInterface.OnClickListener() { 143 @Override 144 public void onClick(DialogInterface dialog, int which) { 145 startActivityForResult(cropOptions.get(which).appIntent,CROP_FROM_CAMERA); 146 } 147 }); 148 builder.setOnCancelListener(new OnCancelListener() { 149 @Override 150 public void onCancel(DialogInterface dialog) { 151 if (imgUri != null){ 152 getContentResolver().delete(imgUri,null,null); 153 imgUri = null; 154 } 155 } 156 }); 157 AlertDialog dialog = builder.create(); 158 dialog.show(); 159 160 } 161 } 162 163 164 @Override 165 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 166 super.onActivityResult(requestCode, resultCode, data); 167 if (resultCode != RESULT_OK){ 168 return; 169 } 170 switch (requestCode) { 171 case PHOTO_PICKED_FROM_CAMERA: 172 doCrop(); 173 break; 174 case PHOTO_PICKED_FROM_FILE: 175 imgUri = data.getData(); 176 doCrop(); 177 break; 178 case CROP_FROM_CAMERA: 179 if (data != null){ 180 setCropImg(data); 181 } 182 break; 183 default: 184 break; 185 } 186 } 187 188 private void setCropImg(Intent picData){ 189 Bundle bundle = picData.getExtras(); 190 if (bundle != null){ 191 Bitmap mBitmap = bundle.getParcelable("data"); 192 mHeadImage.setImageBitmap(mBitmap); 193 saveBitmap(Environment.getExternalStorageDirectory() + "/crop_" 194 +System.currentTimeMillis() + ".png",mBitmap); 195 } 196 } 197 198 private void saveBitmap(String fileName,Bitmap bitmap){ 199 File file = new File(fileName); 200 FileOutputStream fout = null; 201 try { 202 file.createNewFile(); 203 fout = new FileOutputStream(file); 204 bitmap.compress(CompressFormat.PNG,100,fout); 205 fout.flush(); 206 } catch (IOException e) { 207 e.printStackTrace(); 208 } finally { 209 try { 210 if (fout!=null){ 211 fout.close(); 212 } 213 UIUtil.showToast(MainActivity.this,"保存成功!"); 214 } catch (IOException e) { 215 e.printStackTrace(); 216 } 217 } 218 } 219 220 public void btnClick(View view) { 221 selectPhoto(); 222 } 223 }
布局:
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:id="@+id/activity_main" 6 android:layout_width="match_parent" 7 android:layout_height="match_parent" 8 tools:context="com.example.nanchen.cropimagetest.MainActivity"> 9 10 11 <com.example.nanchen.cropimagetest.RoundImageView 12 android:id="@+id/main_roundImage" 13 android:layout_width="100dp" 14 android:layout_height="100dp" 15 android:layout_alignParentTop="true" 16 android:layout_centerInParent="true" 17 android:src="@drawable/default_avatar"/> 18 19 <Button 20 android:id="@+id/main_btn" 21 android:layout_width="match_parent" 22 android:layout_height="wrap_content" 23 android:layout_below="@+id/main_roundImage" 24 android:onClick="btnClick" 25 android:text="设置头像"/> 26 </RelativeLayout>
最后,再次对大家表示歉意,代码有些地方讲解不是很到位,后面我把毕设完全做出来后也会开源给大家,供大家一起交流使用,请持续关注~