Android頭像上傳功能的實(shí)現(xiàn)代碼(獲取頭像加剪切)
因?yàn)轫?xiàng)目中需要用到頭像上傳的功能,所以就下個(gè)Ddmo先來實(shí)現(xiàn)下。
demo我是類似仿微信的,在一個(gè)GridView中展示所有的圖片,其中第一個(gè)item可以去照相;獲取到圖片后再進(jìn)行剪切。
圖片的剪切是從網(wǎng)上找的感覺不錯(cuò)就用,暫時(shí)也沒有測(cè)試。
獲取圖片可以用:https://github.com/lovetuzitong/MultiImageSelector來實(shí)現(xiàn)
這里的圓形圖像是用https://github.com/hdodenhof/CircleImageView來實(shí)現(xiàn)的
Demo寫的比較粗糙,效果只是在4.4的手機(jī)和7.0的模擬器跑了一遍,所以可能會(huì)出現(xiàn)問題的。
如下是demo的效果圖:


如下是選擇圖片中的代碼
通過LoaderManager來獲取到所有的圖片,然后第一個(gè)進(jìn)行拍照的處理
package com.item.demo.photo.activity;
import android.Manifest;
import android.app.LoaderManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ImageView;
import com.item.demo.photo.BuildConfig;
import com.item.demo.photo.R;
import com.item.demo.photo.adapter.MyPhotoAdapter;
import com.item.demo.photo.uilts.Image;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* 圖片選擇界面
*/
public class MyPhotoActivity extends AppCompatActivity {
private static final int REQUEST_CAPTURE = 100;
//private static final int REQUEST_PICK = 101;
private static final int REQUEST_CROP_PHOTO = 102;
public static final int FINSH_RESULT = 104;//截圖后的返回
private static final int LOADER_ID = 0x0100;
private LoadCallBack mLoad = new LoadCallBack();
private MyPhotoAdapter mAdapter;
private List<Image> images = new ArrayList<>();
//調(diào)用照相機(jī)返回圖片文件
private File tempFile;
private static final int MIN_IMAGE_FILE_SIZE = 10 * 1024; // 最小的圖片大小
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_photo);
GridView gv_photo = (GridView)findViewById(R.id.gv_photo);
ImageView img_back = (ImageView)findViewById(R.id.iv_back);
images.add(new Image());
mAdapter = new MyPhotoAdapter(this,images);
gv_photo.setAdapter(mAdapter);
gv_photo.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
if(i == 0){
//第一個(gè)就去照相
if(hasPermission(new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE})){
gotoCamera();
}else {
requestPermission(0x02,new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE});
}
}else {
//這里點(diǎn)擊獲取到圖片地址然后裁剪
gotoClipActivity(Uri.parse(images.get(i).getPath()));
}
}
});
img_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
}
@Override
protected void onStart() {
super.onStart();
if(hasPermission(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE})){
getLoaderManager().initLoader(LOADER_ID,null,mLoad);
}else {
requestPermission(0x01,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE});
}
}
private class LoadCallBack implements LoaderManager.LoaderCallbacks<Cursor>{
private final String[] IMAGE_PROJECTION = new String[]{
MediaStore.Images.Media._ID,//Id
MediaStore.Images.Media.DATA,//圖片路徑
MediaStore.Images.Media.DATE_ADDED//圖片的創(chuàng)建時(shí)間
};
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
//創(chuàng)建一個(gè)Loader
if(id == LOADER_ID){
//如果是我們的ID則進(jìn)行初始化
return new CursorLoader(getBaseContext(),
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
IMAGE_PROJECTION,
null,
null,
IMAGE_PROJECTION[2] + " DESC");
}
return null;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
//當(dāng)Loader加載完成時(shí)
List<Image> images = new ArrayList<>();
//判斷是否有數(shù)據(jù)
if(data != null){
int count = data.getCount();
if(count > 0){
data.moveToFirst();
// 得到對(duì)應(yīng)的列的Index坐標(biāo)
int indexId = data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]);
int indexPath = data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]);
int indexDate = data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]);
do {
// 循環(huán)讀取,直到?jīng)]有下一條數(shù)據(jù)
int id = data.getInt(indexId);
String path = data.getString(indexPath);
long dateTime = data.getLong(indexDate);
File file = new File(path);
if (!file.exists() || file.length() < MIN_IMAGE_FILE_SIZE) {
// 如果沒有圖片,或者圖片大小太小,則跳過
continue;
}
// 添加一條新的數(shù)據(jù)
Image image = new Image();
image.setId(id);
image.setPath(path);
image.setDate(dateTime);
images.add(image);
} while (data.moveToNext());
}
}
updateSource(images);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
updateSource(null);
}
}
/**
* 通知Adapter數(shù)據(jù)更改的方法
* @param images 新的數(shù)據(jù)
*/
private void updateSource(List<Image> images){
this.images.clear();
this.images.add(new Image());
if(images == null || images.size() == 0) return;
this.images.addAll(images);
mAdapter.notifyDataSetChanged();
}
/**
*權(quán)限的返回
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch(requestCode){
case 0x02:
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
gotoCamera();
}
break;
case 0x01:
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
getLoaderManager().initLoader(LOADER_ID,null,mLoad);
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
case REQUEST_CAPTURE://系統(tǒng)相機(jī)返回
if(resultCode == RESULT_OK){
Log.d("jiejie","--------相機(jī)---------" + Uri.fromFile(tempFile).toString());
Log.d("jiejie","--------path----------" + getRealFilePathFromUri(MyPhotoActivity.this,Uri.fromFile(tempFile)));
gotoClipActivity(Uri.fromFile(tempFile));
}
break;
case REQUEST_CROP_PHOTO:
if(resultCode == RESULT_OK){
if(data != null){
Uri uri = data.getData();
Log.d("jiejie","-------------" + data.getData().getPath());
String cropImagePath = getRealFilePathFromUri(MyPhotoActivity.this,uri);
Log.d("jiejie","------crop--------" + cropImagePath);
Intent intent = new Intent();
intent.putExtra("image",cropImagePath);
setResult(FINSH_RESULT,intent);
MyPhotoActivity.this.finish();
}
}
break;
}
}
/**
* 跳轉(zhuǎn)到系統(tǒng)照相機(jī)
*/
private void gotoCamera(){
String SDState = Environment.getExternalStorageState();
//判斷SD卡是否存在
if(SDState.equals(Environment.MEDIA_MOUNTED)){
tempFile = new File(checkDirPath(Environment.getExternalStorageDirectory().getPath()+ "/image/"), System.currentTimeMillis() + ".jpg");
//隱式的打開調(diào)用系統(tǒng)相冊(cè)
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
//如果是7.0及以上的系統(tǒng)使用FileProvider的方式創(chuàng)建一個(gè)Uri
Uri contentUri = FileProvider.getUriForFile(MyPhotoActivity.this, BuildConfig.APPLICATION_ID + ".fileProvider", tempFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
}else {
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
}
startActivityForResult(intent,REQUEST_CAPTURE);
}
}
/**
* 打開截圖的界面
* @param uri
*/
private void gotoClipActivity(Uri uri){
if(uri == null){
return;
}
Intent intent = new Intent(this,ClipImageActivity.class);
intent.putExtra("type",1);
intent.setData(uri);
startActivityForResult(intent,REQUEST_CROP_PHOTO);
}
/**
* 檢查文件是否存在
*/
private static String checkDirPath(String dirPath) {
if (TextUtils.isEmpty(dirPath)) {
return "";
}
File dir = new File(dirPath);
if (!dir.exists()) {
dir.mkdirs();
}
return dirPath;
}
/**
* 判斷是否有指定的權(quán)限
*/
public boolean hasPermission(String... permissions) {
for (String permisson : permissions) {
if (ContextCompat.checkSelfPermission(this, permisson)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
/**
* 申請(qǐng)指定的權(quán)限.
*/
public void requestPermission(int code, String... permissions) {
if (Build.VERSION.SDK_INT >= 23) {
requestPermissions(permissions, code);
}
}
/**
* 根據(jù)Uri返回文件絕對(duì)路徑
* 兼容了file:///開頭的 和 content://開頭的情況
*/
public static String getRealFilePathFromUri(final Context context, final Uri uri) {
if (null == uri) return null;
final String scheme = uri.getScheme();
String data = null;
if (scheme == null)
data = uri.getPath();
else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
data = uri.getPath();
} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
if (null != cursor) {
if (cursor.moveToFirst()) {
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
if (index > -1) {
data = cursor.getString(index);
}
}
cursor.close();
}
}
return data;
}
}
其中處理動(dòng)態(tài)的權(quán)限還需要添加7.0的照相處理
在清單文件中加如下配置:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.item.demo.photo.fileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
圖片的剪切
package com.item.demo.photo.activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.item.demo.photo.R;
import com.item.demo.photo.view.ClipViewLayout;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
/**
* 圖片剪切
*/
public class ClipImageActivity extends AppCompatActivity implements View.OnClickListener {
private ClipViewLayout clipViewLayout1;
private ClipViewLayout clipViewLayout2;
private ImageView back;
private TextView tv_ok;
//類別 1:圓形 2:方形
private int type;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clip_image);
type = getIntent().getIntExtra("type",1);
initView();
}
private void initView() {
clipViewLayout1 = (ClipViewLayout)findViewById(R.id.clipViewLayout1);
clipViewLayout2 = (ClipViewLayout)findViewById(R.id.clipViewLayout2);
back = (ImageView)findViewById(R.id.iv_back);
tv_ok = (TextView)findViewById(R.id.tv_ok);
back.setOnClickListener(this);
tv_ok.setOnClickListener(this);
}
@Override
protected void onResume() {
super.onResume();
if(type == 1){
clipViewLayout1.setVisibility(View.VISIBLE);
clipViewLayout2.setVisibility(View.GONE);
//設(shè)置圖片資源
clipViewLayout1.setImageSrc(getIntent().getData());
}else {
clipViewLayout2.setVisibility(View.VISIBLE);
clipViewLayout1.setVisibility(View.GONE);
clipViewLayout2.setImageSrc(getIntent().getData());
}
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.iv_back:
finish();
break;
case R.id.tv_ok:
generateUriAndReturn();
break;
}
}
/**
* 生成Uri并且通過setResult返回給打開的Activity
*/
private void generateUriAndReturn() {
//調(diào)用返回剪切圖
Bitmap zoomedCropBitmap;
if (type == 1) {
zoomedCropBitmap = clipViewLayout1.clip();
} else {
zoomedCropBitmap = clipViewLayout2.clip();
}
if (zoomedCropBitmap == null) {
Log.e("android", "zoomedCropBitmap == null");
return;
}
Uri mSaveUri = Uri.fromFile(new File(getCacheDir(), "cropped_" + System.currentTimeMillis() + ".jpg"));
if (mSaveUri != null) {
OutputStream outputStream = null;
try {
outputStream = getContentResolver().openOutputStream(mSaveUri);
if (outputStream != null) {
zoomedCropBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
}
} catch (IOException ex) {
Log.e("android", "Cannot open file: " + mSaveUri, ex);
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Intent intent = new Intent();
intent.setData(mSaveUri);
setResult(RESULT_OK, intent);
finish();
}
}
}
總結(jié)
以上所述是小編給大家介紹的Android頭像上傳功能的實(shí)現(xiàn)代碼(獲取頭像加剪切),希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Android利用HorizontalScrollView仿ViewPager設(shè)計(jì)簡單相冊(cè)
這篇文章主要介紹了Android利用HorizontalScrollView仿ViewPager設(shè)計(jì)簡單相冊(cè)的相關(guān)資料,需要的朋友可以參考下2016-05-05
Android仿微信實(shí)現(xiàn)評(píng)論功能
這篇文章主要為大家詳細(xì)介紹了Android仿微信實(shí)現(xiàn)評(píng)論功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11
Android 圖片特效如何實(shí)現(xiàn)及總結(jié)
這篇文章主要介紹了Android 圖形特效如何實(shí)現(xiàn)及總結(jié)的相關(guān)資料,這里對(duì)Android圖像特效的實(shí)現(xiàn)比如:旋轉(zhuǎn),放大,縮小,傾斜等,需要的朋友可以參考下2016-12-12
android實(shí)現(xiàn)icon動(dòng)態(tài)旋轉(zhuǎn)效果
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)icon動(dòng)態(tài)旋轉(zhuǎn)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07
詳解如何實(shí)現(xiàn)一個(gè)Kotlin函數(shù)類型
這篇文章主要為大家詳細(xì)介紹了如何實(shí)現(xiàn)一個(gè)Kotlin函數(shù)類型,文中的實(shí)現(xiàn)方法講解詳細(xì),具有一定的借鑒價(jià)值,需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-10-10
Android開發(fā)之SeekBar基本使用及各種美觀樣式示例
這篇文章主要介紹了Android開發(fā)之SeekBar基本使用及各種美觀樣式,結(jié)合實(shí)例形式分析了Android SeekBar控件的功能及樣式改變相關(guān)操作技巧,需要的朋友可以參考下2019-03-03
Android自定義加載loading view動(dòng)畫組件
這篇文章主要為大家詳細(xì)介紹了Android自定義加載loading view動(dòng)畫組件的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08
Android初學(xué)者必須知道的10個(gè)技術(shù)
本篇內(nèi)容給大家整理10個(gè)作為Android初學(xué)者必須要了解和會(huì)用的技術(shù)以及詳細(xì)代碼分析,需要的朋友收藏下慢慢學(xué)習(xí)吧。2017-12-12

