一个简单的小功能,适合初学者,大神路过即可…
点击按钮弹出PopupWindow,打开相机或相册选择头像并裁剪后显示在ImageView上。
编辑用户头像,基本是个APP都要实现的功能,在6.0加入权限后变得稍微麻烦了点。在写项目的时候正好用到,找了下别人写的,改了改,记录下来,方便自己也方便他人。。。
参考文章:
1. http://www.jianshu.com/p/64baf3f9c38f Android 6.0后权限申请工具库的用法
2. http://blog.youkuaiyun.com/harvic880925/article/details/43163175 拍照、相册及裁剪的终极实现
3. 感谢两位的文章分享,我只是把两个功能合到一起了^_^
1.在Android6.0以后引入的权限机制,使用没什么难度啊,大神都介绍的很清楚了。要编辑头像,我们从相机或者相册选择,打开相机必须进行权限申请。这里用到了PermissionTools权限申请工具库。
PermissionTools的github地址:https://github.com/Jerey-Jobs/PermissionTools
PermissionTools的使用方法:
1.1 project’s build.gradle (工程下的 build.gradle)
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
1.2.module’s build.gradle (模块的build.gradle)
dependencies {
compile 'com.github.Jerey-Jobs:PermissionTools:1.5'
}
正式开始了:
新建项目,这个不用说了哈,在AndroidManifest.xml里面添加如下权限
分别的是 相机权限 及 读写权限
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
activity_main布局文件,就放一个Button用来点击弹出PopupWindow,一个ImageView用来显示选择的图片
<Button
android:id="@+id/bt_open"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="弹窗" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srcCompat="@mipmap/ic_launcher"
android:layout_weight="0.59" />
既然要弹出PopupWindow,当然要有个PopupWindow的布局啦,两个按钮,分别是打开相机,和从相册选择,新建XML文件view_popupwindow
<View
android:layout_width="match_parent"
android:layout_height="0.1px"
android:background="#888" />
<TextView
android:id="@+id/tv_pick_phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="16dp"
android:text="打开相机"
android:textColor="#118"
android:textSize="18sp" />
<View
android:layout_width="match_parent"
android:layout_height="0.1px"
android:background="#888" />
<TextView
android:id="@+id/tv_pick_zone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="16dp"
android:text="从手机相册选择"
android:textColor="#118"
android:textSize="18sp" />
下面就是MainActivity的代码了onCreate中
初始化控件,不用讲了
下面来用两个Uri,来存放图片
String path = getSDCardPath();
File file = new File(path + "/temp.jpg");
imageUri = Uri.fromFile(file);
File cropFile = new File(getSDCardPath() + "/temp_crop.jpg");
imageCropUri = Uri.fromFile(cropFile);
//getSDCardPath()
public static String getSDCardPath() {
String cmd = "cat /proc/mounts";
Runtime run = Runtime.getRuntime();// 返回与当前 Java 应用程序相关的运行时对象
try {
Process p = run.exec(cmd);// 启动另一个进程来执行命令
BufferedInputStream in = new BufferedInputStream(p.getInputStream());
BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
String lineStr;
while ((lineStr = inBr.readLine()) != null) {
// 获得命令执行后在控制台的输出信息
if (lineStr.contains("sdcard")
&& lineStr.contains(".android_secure")) {
String[] strArray = lineStr.split(" ");
if (strArray != null && strArray.length >= 5) {
String result = strArray[1].replace("/.android_secure",
"");
return result;
}
}
// 检查命令是否执行失败。
if (p.waitFor() != 0 && p.exitValue() == 1) {
// p.exitValue()==0表示正常结束,1:非正常结束
}
}
inBr.close();
in.close();
} catch (Exception e) {
return Environment.getExternalStorageDirectory().getPath();
}
return Environment.getExternalStorageDirectory().getPath();
}
//点击弹窗,需要获取用户授权,用户同意后则弹出PopupWindow,原谅我起了个通俗易懂的名字
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_open:
//调用方法,获取权限
xiangji(v);
break;
}
}
//获取权限方法
public void xiangji(final View v) {
permissionTools = new PermissionTools.Builder(this)
.setOnPermissionCallbacks(new PermissionCallbacks() {
//用户同意权限申请,执行此方法
@Override
public void onPermissionsGranted(int requestCode, List<String> perms) {
//权限申请通过,执行方法,弹出PopupWindow
openPopupWindow(v);
}
//用户不同意权限申请,执行此方法
@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
Toast.makeText(MainActivity.this, "权限申请被据绝",Toast.LENGTH_SHORT).show();
}
})
.setRequestCode(111)
.build();
//需要申请哪些权限,我这里同时申请了 相机权限 和 读写权限,可以同时多个,也可以单个,“,”隔开
permissionTools.requestPermissions(Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
//弹出PopupWindow
private void openPopupWindow(View v) {
if (popupWindow != null && popupWindow.isShowing()) {
return;
}
//设置PopupWindow的View
View view = LayoutInflater.from(this).inflate(R.layout.view_popupwindow, null);
popupWindow = new PopupWindow(view, RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
//设置背景,这个没什么效果,不添加会报错
popupWindow.setBackgroundDrawable(new BitmapDrawable());
//设置点击弹窗外隐藏自身
popupWindow.setFocusable(true);
popupWindow.setOutsideTouchable(true);
//设置动画
popupWindow.setAnimationStyle(R.style.PopupWindow);
//设置位置,这里需要用到传过来view了
//popupWindow.showAtLocation(v, Gravity.BOTTOM, 0, navigationHeight);
popupWindow.showAtLocation(v, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
//设置消失监听
popupWindow.setOnDismissListener(this);
//设置PopupWindow的View点击事件
setOnPopupViewClick(view);
//设置背景色
setBackgroundAlpha(0.5f);
}
//弹出动画 style文件中
<style name="PopupWindow">
<item name="android:windowEnterAnimation">@anim/window_in</item>
<item name="android:windowExitAnimation">@anim/window_out</item>
</style>
//设置屏幕背景透明效果
public void setBackgroundAlpha(float alpha) {
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = alpha;
getWindow().setAttributes(lp);
}
//popupWindow的View点击事件设置
private void setOnPopupViewClick(View view) {
TextView tv_pick_phone, tv_pick_zone;
tv_pick_phone = (TextView) view.findViewById(R.id.tv_pick_phone);
tv_pick_zone = (TextView) view.findViewById(R.id.tv_pick_zone);
tv_pick_phone.setOnClickListener(this);
tv_pick_zone.setOnClickListener(this);
}
//popupWindow点击事件
@Override
public void onClick(View v) {
switch (v.getId()) {
//这里是前面弹窗按钮的点击事件...
//打开相机
case R.id.tv_pick_phone:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 启动系统相机
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
//需要将拍照的相片返回,用startActivityForResult
startActivityForResult(intent, 1);
popupWindow.dismiss();
break;
//打开相册
case R.id.tv_pick_zone:
Intent i = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
// 设定结果返回
startActivityForResult(i, 2);
popupWindow.dismiss();
break;
}
}
//用来接收返回的照片
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == 1) {
//接收到返回的照片之后,启用裁剪功能
cropImg(imageUri);
} else if (requestCode == 2) {
//返回从相册选择的照片
Uri uri = data.getData();
cropImg(uri);
} else if (requestCode == 3) {
//接收到裁剪过后的照片,设置给imageview
Bundle extras = data.getExtras();
if (extras != null) {
try {
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageCropUri));
imageview.setImageBitmap(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
//裁剪照片
public void cropImg(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 700);
intent.putExtra("outputY", 700);
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageCropUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
//裁剪后返回给Activity
startActivityForResult(intent, 3);
}
@Override
public void onDismiss() {
setBackgroundAlpha(1);
}
//申请权限后回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
permissionTools.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
代码基本都分段写上去了,下面就不贴完整代码了。给出github地址,需要的可以自己下。
有问题欢迎指导