切换头像,拍照或者相册选择后剪裁
程序员文章站
2022-05-20 09:37:43
...
这个功能基本每个项目都会有,每次都要去翻看以前的项目,感觉不好,这里记录一下,以后需要的时候直接过来复制就行了,
1.首先是点击头像弹出一个选择框,让用户选择照相机或者打开相册
2,如果点击拍照就去调用系统照相机
case R.id.photo_take://照相的监听
try {
//调用系统照相机,注意,我这里没有适配6.0权限
Intent intent2 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//拍照后照片的地址和命名
intent2.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(new File(Environment.getExternalStorageDirectory(),
"head.jpg")));
startActivityForResult(intent2, TAKE_PHONE);//采用ForResult打开,回调到onActivityResult
} catch (Exception e) {
Log.e("duanlian", "onClick: " + e);
Toast.makeText(MainActivity.this, "请允许程序获取系统照相权限", Toast.LENGTH_SHORT).show();
}
break;
3.拍照完成后会回调到onActivityResult,然后拿到图片的地址,去调用系统的剪裁功能
case TAKE_PHONE: //照相之后回调到这里
//拿到照片的地址
File temp = new File(Environment.getExternalStorageDirectory() + "/head.jpg");
cropPhoto(Uri.fromFile(temp));//裁剪图片
break;
4,调用系统剪裁的代码
/**
* 调用系统的裁剪
*
* @param uri
*/
public void cropPhoto(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 160);
intent.putExtra("outputY", 160);
intent.putExtra("return-data", true);
startActivityForResult(intent, PHONE_CROP);//剪裁完成回调到onActivityResult
}
5,点击确定之后又回调到onActivityResult,获取到剪裁后的图片,就该干嘛就干嘛了
case PHONE_CROP://图片剪裁后回调到这里
if (data != null) {
Bundle extras = data.getExtras();
//拿到剪裁后的图片
head = extras.getParcelable("data");
if (head != null) {
setPicToView(head);//保存在SD卡中
ivHead.setImageBitmap(head);//用ImageView显示出来
//转换成字节码,上传到服务器
ByteArrayOutputStream output = new ByteArrayOutputStream();
head.compress(Bitmap.CompressFormat.JPEG, 100, output);
byte[] bytesOfBitmap = output.toByteArray();
// TODO: 2017/6/7 去上传到服务器
}
}
break;
6,然后就成功切换了头像
步骤大概就是这样的,调用系统相册和拍照差不多,也是获取到用户选择的图片去调用系统剪裁
完整的代码:注释比较详细,看看就懂了
package com.duanlian.changeheaddemo;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import de.hdodenhof.circleimageview.CircleImageView;
public class MainActivity extends AppCompatActivity {
private CircleImageView ivHead;
private ChangeHeadPopwindow mHeadPopwindow;//自定义的选择popupWindow
private static final int PHOTO_ALBUM = 1;//调用相册的请求码
private static final int TAKE_PHONE = 2;//照相的请求码
private static final int PHONE_CROP = 3;//剪裁完成请求码
//处理头像后得到的bitmap头像
private Bitmap head;
private static String path = "/sdcard/myHead/";//sd路径
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
ivHead = (CircleImageView) findViewById(R.id.circle_iv);
ivHead.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//调起选择框,选择从相册取还是拍照,传入上下文和点击监听
mHeadPopwindow = new ChangeHeadPopwindow(MainActivity.this, itemsOnClick);
mHeadPopwindow.showAtLocation(view, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
}
});
}
//为popupwindow弹出窗口实现监听类
private View.OnClickListener itemsOnClick = new View.OnClickListener() {
public void onClick(View v) {
mHeadPopwindow.dismiss();//不管是点击了哪个都让弹框消失
mHeadPopwindow.backgroundAlpha(MainActivity.this, 1f);//改变背景
switch (v.getId()) {
case R.id.photo_take://照相的监听
try {
//调用系统照相机,注意,我这里没有适配6.0权限
Intent intent2 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//拍照后照片的地址和命名
intent2.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(new File(Environment.getExternalStorageDirectory(),
"head.jpg")));
startActivityForResult(intent2, TAKE_PHONE);//采用ForResult打开,回调到onActivityResult
} catch (Exception e) {
Log.e("duanlian", "onClick: " + e);
Toast.makeText(MainActivity.this, "请允许程序获取系统照相权限", Toast.LENGTH_SHORT).show();
}
break;
case R.id.photo_album://相册
//调起系统相册
Intent intent1 = new Intent(Intent.ACTION_PICK, null);
intent1.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent1, PHOTO_ALBUM);
break;
default:
break;
}
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode==RESULT_OK) {
//判断请求码
switch (requestCode) {
case PHOTO_ALBUM://相册选择之后回调到这里
//取出图片后去剪裁
cropPhoto(data.getData());
break;
case TAKE_PHONE: //照相之后回调到这里
//拿到照片的地址
File temp = new File(Environment.getExternalStorageDirectory() + "/head.jpg");
cropPhoto(Uri.fromFile(temp));//裁剪图片
break;
case PHONE_CROP://图片剪裁后回调到这里
if (data != null) {
Bundle extras = data.getExtras();
//拿到剪裁后的图片
head = extras.getParcelable("data");
if (head != null) {
setPicToView(head);//保存在SD卡中
ivHead.setImageBitmap(head);//用ImageView显示出来
//转换成字节码,上传到服务器
ByteArrayOutputStream output = new ByteArrayOutputStream();
head.compress(Bitmap.CompressFormat.JPEG, 100, output);
byte[] bytesOfBitmap = output.toByteArray();
// TODO: 2017/6/7 去上传到服务器
}
}
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
/**
* 调用系统的裁剪
*
* @param uri
*/
public void cropPhoto(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 160);
intent.putExtra("outputY", 160);
intent.putExtra("return-data", true);
startActivityForResult(intent, PHONE_CROP);//剪裁完成回调到onActivityResult
}
/**
* 把bitmap写入sd卡
* @param mBitmap
*/
private void setPicToView(Bitmap mBitmap) {
String sdStatus = Environment.getExternalStorageState();
if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { // 检测sd是否可用
return;
}
FileOutputStream b = null;
File file = new File(path);
file.mkdirs();// 创建文件夹
//
String fileName = path + "head.jpg";//图片名字
Log.e("duanlian===", "setPicToView: " + fileName);
try {
b = new FileOutputStream(fileName);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, b);// 把数据写入文件
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
//关闭流
b.flush();
b.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
看不懂把demo下载下来直接复制代码就行了
demo下载地址:点击下载
Kotlin版本下载点击下载kotlin版
上一篇: 关于隐藏切换+瀑布流样式(二)
推荐阅读