最近在做畢業設計,想有一個功能和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>
最后,再次對大家表示歉意,代碼有些地方講解不是很到位,后面我把畢設完全做出來后也會開源給大家,供大家一起交流使用,請持續關注~