目前幾乎所有的APP在用戶註冊時都會有設置頭像的需求,大致分為三種情況: (1)通過獲取本地相冊的圖片,經過裁剪後作為頭像。 (2)通過啟動手機相機,現拍圖片然後裁剪作為頭像。 (3)在APP中添加一些自帶的頭像資源,供用戶選擇(不夠人性化,目前很少使用)。 這次我們簡單介紹下通過獲取本地相冊以及相 ...
目前幾乎所有的APP在用戶註冊時都會有設置頭像的需求,大致分為三種情況:
(1)通過獲取本地相冊的圖片,經過裁剪後作為頭像。
(2)通過啟動手機相機,現拍圖片然後裁剪作為頭像。
(3)在APP中添加一些自帶的頭像資源,供用戶選擇(不夠人性化,目前很少使用)。
這次我們簡單介紹下通過獲取本地相冊以及相機拍攝的方法設置頭像,實現思路如下:
(1)通過startActivityForResult方法,分別傳遞調用系統相冊的Intent和調用相機拍照的Intent來做選擇
(2)調用Android系統中自帶的圖片剪裁,實現圖片的剪裁併在onActivityResult方法中獲取數據。
關於如何處理Activity的返回結果,請參照往期博文《Android中Activity處理返回結果的實現方式》。
本次演示效果如下(分別為從本地相冊獲取以及從相機拍攝獲取頭像):
簡單佈局文件這裡不再做贅述,本次試驗使用隱式intent調用相機以及本地相冊,未在配置清單上添加許可權,依然可以調用。java實現代碼如下:
1 import android.content.Intent; 2 import android.graphics.Bitmap; 3 import android.net.Uri; 4 import android.os.Bundle; 5 import android.os.Environment; 6 import android.provider.MediaStore; 7 import android.support.v7.app.AppCompatActivity; 8 import android.view.View; 9 import android.widget.Button; 10 import android.widget.ImageView; 11 import android.widget.Toast; 12 import java.io.File; 13 14 public class MainActivity extends AppCompatActivity implements View.OnClickListener { 15 private Button buttonLocal, buttonCamera; 16 private ImageView imageView; 17 //相機拍攝的頭像文件(本次演示存放在SD卡根目錄下) 18 private static final File USER_ICON = new File(Environment.getExternalStorageDirectory(), "user_icon.jpg"); 19 //請求識別碼(分別為本地相冊、相機、圖片裁剪) 20 private static final int CODE_PHOTO_REQUEST = 1; 21 private static final int CODE_CAMERA_REQUEST = 2; 22 private static final int CODE_PHOTO_CLIP = 3; 23 @Override 24 protected void onCreate(Bundle savedInstanceState) { 25 super.onCreate(savedInstanceState); 26 setContentView(R.layout.activity_main); 27 buttonLocal = (Button) findViewById(R.id.buttonLocal); 28 buttonCamera = (Button) findViewById(R.id.buttonCamera); 29 imageView = (ImageView) findViewById(R.id.imageView); 30 buttonLocal.setOnClickListener(this); 31 buttonCamera.setOnClickListener(this); 32 } 33 //設置點擊事件 34 @Override 35 public void onClick(View view) { 36 switch (view.getId()) { 37 case R.id.buttonLocal: 38 //調用獲取本地圖片的方法 39 getPicFromLocal(); 40 break; 41 case R.id.buttonCamera: 42 //調用相機拍照的方法 43 getPicFromCamera(); 44 break; 45 default: 46 break; 47 } 48 } 49 /** 50 * 從本機相冊獲取圖片 51 */ 52 private void getPicFromLocal() { 53 Intent intent = new Intent(); 54 // 獲取本地相冊方法一 55 intent.setAction(Intent.ACTION_GET_CONTENT); 56 intent.setType("image/*"); 57 //獲取本地相冊方法二 58 // intent.setAction(Intent.ACTION_PICK); 59 // intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 60 // "image/*"); 61 startActivityForResult(intent, CODE_PHOTO_REQUEST); 62 } 63 /** 64 * 通過相機拍攝獲取圖片, 65 * 並存入設置的路徑中 66 */ 67 private void getPicFromCamera() { 68 Intent intent = new Intent(); 69 intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); 70 // 下麵這句指定調用相機拍照後的照片存儲的路徑 71 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(USER_ICON)); 72 startActivityForResult(intent, CODE_CAMERA_REQUEST); 73 } 74 /** 75 * 圖片裁剪 76 * 77 * @param uri 78 */ 79 private void photoClip(Uri uri) { 80 // 調用系統中自帶的圖片剪裁 81 Intent intent = new Intent(); 82 intent.setAction("com.android.camera.action.CROP"); 83 intent.setDataAndType(uri, "image/*"); 84 // 下麵這個crop=true是設置在開啟的Intent中設置顯示的VIEW可裁剪 85 intent.putExtra("crop", "true"); 86 // aspectX aspectY 是寬高的比例 87 intent.putExtra("aspectX", 1); 88 intent.putExtra("aspectY", 1); 89 /*outputX outputY 是裁剪圖片寬高 90 *這裡僅僅是頭像展示,不建議將值設置過高 91 * 否則超過binder機制的緩存大小的1M限制 92 * 報TransactionTooLargeException 93 */ 94 intent.putExtra("outputX", 150); 95 intent.putExtra("outputY", 150); 96 intent.putExtra("return-data", true); 97 startActivityForResult(intent, CODE_PHOTO_CLIP); 98 } 99 /** 100 * 提取保存裁剪之後的圖片數據,並設置頭像部分的View 101 */ 102 private void setImageToHeadView(Intent intent) { 103 Bundle extras = intent.getExtras(); 104 if (extras != null) { 105 Bitmap photo = extras.getParcelable("data"); 106 imageView.setImageBitmap(photo); 107 } 108 } 109 @Override 110 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 111 // 用戶沒有進行有效的設置操作,返回 112 if (resultCode == RESULT_CANCELED) { 113 Toast.makeText(MainActivity.this, "取消", Toast.LENGTH_LONG).show(); 114 return; 115 } 116 switch (requestCode) { 117 case CODE_CAMERA_REQUEST: 118 if (USER_ICON.exists()) { 119 photoClip(Uri.fromFile(USER_ICON)); 120 } 121 break; 122 case CODE_PHOTO_REQUEST: 123 if (data != null) { 124 photoClip(data.getData()); 125 } 126 break; 127 case CODE_PHOTO_CLIP: 128 if (data != null) { 129 setImageToHeadView(data); 130 } 131 break; 132 } 133 super.onActivityResult(requestCode, resultCode, data); 134 } 135 }
這裡要註意的是在裁剪圖片時,長和寬不要設置太大,否則超過binder機制的緩存大小的限制(受手機配置影響).報TransactionTooLargeException,在代碼中已經做了詳細標註,請各位看官在實現的時候萬萬註意。