//第一步 权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
//第二步 依赖,我使用了一个圆形图片库:
//圆形图片
implementation 'de.hdodenhof:circleimageview:2.1.0'
//第三步 我的Activity布局,就是一个圆形图片:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainPopActivity">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/mCircleImageView"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:src="@mipmap/ic_launcher_round" />
</RelativeLayout>
//第四步 Activity代码:
public class MainPopActivity extends AppCompatActivity implements View.OnClickListener {
//相册请求码
private static final int ALBUM_REQUEST_CODE = 1;
//相机请求码
private static final int CAMERA_REQUEST_CODE = 2;
//剪裁请求码
private static final int CROP_SMALL_PICTURE = 3;
//调用照相机返回图片文件
private File tempFile;
//最后显示的图片文件
private String mFile;
private Button mPhotograph;
private Button mAlbum;
private Button mCancel;
private PopupWindow window;
private CircleImageView mCircleImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_pop);
popUp();
initView();
readPictures(); //读取图片,读取上次保存的图片
}
//初始化控件,图片点击事件
private void initView() {
mCircleImageView = (CircleImageView) findViewById(R.id.mCircleImageView);
mCircleImageView.setOnClickListener(this);
mPhotograph.setOnClickListener(this);
mAlbum.setOnClickListener(this);
mCancel.setOnClickListener(this);
}
//读取图片,设置了图片之后,下次再进来还会有,读取上次保存的图片
private void readPictures() {
Bitmap bitmap = BitmapFactory.decodeFile(getPath());
if (null != bitmap) {
mCircleImageView.setImageBitmap(bitmap);
} else {
mCircleImageView.setImageResource(R.mipmap.ic_launcher);
}
}
//初始化popwindow
private void popUp() {
View inflate = LayoutInflater.from(this).inflate(R.layout.pop_layout, null);
window = new PopupWindow(inflate, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
mPhotograph = inflate.findViewById(R.id.mPhotograph);
window.setAnimationStyle(R.style.popwin_anim_style);//动画
mAlbum = inflate.findViewById(R.id.mAlbum);
mCancel = inflate.findViewById(R.id.mCancel);
// window.setBackgroundDrawable(new BitmapDrawable());//设置PopupWindow的背景
// window.setOutsideTouchable(false);
window.setFocusable(true);
//设置背景颜色变正常
window.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 1f;
getWindow().setAttributes(lp);
}
});
}
@Override
public void onClick(View v) {
// 设置背景颜色变暗
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 0.7f;
getWindow().setAttributes(lp);
switch (v.getId()) {
case R.id.mCircleImageView: //图片点击事件,打开popwindow
//第一个参数是要将PopupWindow放到的View,第二个参数是位置,第三第四是偏移值
window.showAtLocation(mCircleImageView, Gravity.BOTTOM, 0, 0);
break;
case R.id.mPhotograph://拍照
getPicFromCamera();
window.dismiss();
break;
case R.id.mAlbum://相册
getPicFromAlbm();
window.dismiss();
break;
case R.id.mCancel://取消
window.dismiss();
break;
}
}
//拍照和选择相册的回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case CAMERA_REQUEST_CODE: //调用相机后返回
if (resultCode == RESULT_OK) {
//用相机返回的照片去调用剪裁也需要对Uri进行处理
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri contentUri = FileProvider.getUriForFile(this, getPackageName() + ".provider", tempFile);
startPhotoZoom(contentUri);//开始对图片进行裁剪处理
} else {
startPhotoZoom(Uri.fromFile(tempFile));//开始对图片进行裁剪处理
}
}
break;
case ALBUM_REQUEST_CODE: //调用相册后返回
if (resultCode == RESULT_OK) {
Uri uri = data.getData();
startPhotoZoom(uri); // 开始对图片进行裁剪处理
}
break;
case CROP_SMALL_PICTURE: //调用剪裁后返回
Bitmap bitmap = BitmapFactory.decodeFile(getPath());
if (null != bitmap) { // 让刚才选择裁剪得到的图片显示在界面上,清晰
mCircleImageView.setImageBitmap(bitmap);
} else {
if (data != null) {// 让刚才选择裁剪得到的图片显示在界面上,模糊
Bitmap photo = BitmapFactory.decodeFile(mFile);
mCircleImageView.setImageBitmap(photo);
} else {
Log.e("data", "data=null");
}
}
break;
}
}
/**
* 裁剪图片方法实现
*
* @param uri
*/
protected void startPhotoZoom(Uri uri) {
if (uri == null) {
Log.i("tag", "The uri is not exist.");
}
Intent intent = new Intent("com.android.camera.action.CROP");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setDataAndType(uri, "image/*");
// 设置裁剪
intent.putExtra("crop", "true");
intent.putExtra("scale", true);
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 720);
intent.putExtra("outputY", 720);
//设置了true的话直接返回bitmap,可能会很占内存
intent.putExtra("return-data", false);
//不启用人脸识别
intent.putExtra("noFaceDetection", true);
File out = new File(getPath());
if (!out.getParentFile().exists()) {
out.getParentFile().mkdirs();
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(intent, CROP_SMALL_PICTURE);
}
//裁剪后的地址,保存到本地
public String getPath() {
if (mFile == null) {
mFile = Environment.getExternalStorageDirectory() + "/" + "MyPicture/" + "temp.png";
}
return mFile;
}
/**
* 从相机获取图片
*/
private void getPicFromCamera() {
//用于保存调用相机拍照后所生成的文件
// tempFile = new File(Environment.getExternalStorageDirectory().getPath(), System.currentTimeMillis() + ".png");
tempFile = new File(Environment.getExternalStorageDirectory().getPath(), "/temp.png");
//跳转到调用系统相机
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//判断版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //如果在Android7.0以上,使用FileProvider获取Uri
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(this, getPackageName() + ".provider", tempFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
Log.e("getPicFromCamera", contentUri.toString());
} else { //否则使用Uri.fromFile(file)方法获取Uri
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
}
startActivityForResult(intent, CAMERA_REQUEST_CODE);
}
/**
* 从相册获取图片
*/
private void getPicFromAlbm() {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, ALBUM_REQUEST_CODE);
}
}
//第五步 我的popwindow布局 pop_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/mPop"
>
<Button
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="@drawable/top_pop_button_bg"
android:text="拍照"
android:textColor="#ff0000"
android:id="@+id/mPhotograph"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<View
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="#d4d4d4"
android:layout_width="match_parent"
android:layout_height="1dp"/>
<Button
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="@drawable/bottom_pop_button_bg"
android:text="相册"
android:textColor="#ff0000"
android:id="@+id/mAlbum"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:background="@drawable/cancel_button_bg"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="20dp"
android:text="取消"
android:textColor="#0090ff"
android:id="@+id/mCancel"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
//第六步 在res下新建anim,在anim下建了两个动画xml文件:
bottom_in.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:fromYDelta="100%p"
android:toYDelta="0"
android:duration="300" />
<alpha
android:fromAlpha="0"
android:toAlpha="1.0"
android:duration="300"/>
</set>
bottom_out.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:fromYDelta="0"
android:toYDelta="100%p"
android:duration="300"/>
<alpha
android:fromAlpha="1.0"
android:toAlpha="0"
android:duration="300"/>
</set>
//第七步 在res下,values下,style里 添加popwindow动画style:
<style name="popwin_anim_style">
<item name="android:windowEnterAnimation">@anim/bottom_in</item>
<item name="android:windowExitAnimation">@anim/bottom_out</item>
</style>
//第八步 在drawable下新建了三个选择圆角背景xml布局文件:
bottom_pop_button_bg.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false"> <!-- 按钮未点击-->
<shape >
<solid android:color="#d7d5d5"/>
<corners android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp"/>
</shape>
</item>
<item android:state_pressed="true"> <!-- 按钮选中状态-->
<shape >
<solid android:color="#b4b4b4"/>
<corners android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp"/>
</shape>
</item>
</selector>
cancel_button_bg.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false"> <!-- 按钮未点击-->
<shape >
<corners android:radius="10dp" />
<solid android:color="#d7d5d5"/>
</shape>
</item>
<item android:state_pressed="true"> <!-- 按钮选中状态-->
<shape >
<corners android:radius="10dp" />
<solid android:color="#b4b4b4"/>
</shape>
</item>
</selector>
top_pop_button_bg.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false"> <!-- 按钮未点击-->
<shape >
<solid android:color="#d7d5d5"/>
<corners android:topLeftRadius="10dp" android:topRightRadius="10dp"/>
</shape>
</item>
<item android:state_pressed="true"> <!-- 按钮选中状态-->
<shape >
<solid android:color="#b4b4b4"/>
<corners android:topLeftRadius="10dp" android:topRightRadius="10dp"/>
</shape>
</item>
</selector>
//第九步 Android7.0及以上的需要设置FileProvider,在res下新建xml文件夹,在xml下新建 file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
path="com.example.picturedemo" name="images" />
<root-path
name="root_path"
path="." />
</paths>
//第十步 在AndroidManifest.xml里注册清单文件,在application下注册,再替换你的包名:
<!--FileProvider共享文件、缓存-->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="你的包名.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
//简洁重要方法:
/**
* 相册请求码
*/
private static final int ALBUM_REQUEST_CODE = 1;
/**
* 相机请求码
*/
private static final int CAMERA_REQUEST_CODE = 2;
/**
* 剪裁请求码
*/
private static final int CROP_SMALL_PICTURE = 3;
/**
* 调用照相机返回图片文件
*/
private File tempFile;
/**
* 裁剪后的地址,保存到本地
*/
private String filePath = "";
public File getTempFile() {
if (null == tempFile) {
tempFile = new File(Environment.getExternalStorageDirectory().getPath(), "/temp.png");
}
return tempFile;
}
//拍照和选择相册的回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
//调用相机后返回
case CAMERA_REQUEST_CODE:
if (resultCode == RESULT_OK) {
//用相机返回的照片去调用剪裁也需要对Uri进行处理
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri contentUri = FileProvider.getUriForFile(this, getPackageName() + ".provider", getTempFile());
//开始对图片进行裁剪处理
startPhotoZoom(contentUri);
} else {
//开始对图片进行裁剪处理
startPhotoZoom(Uri.fromFile(getTempFile()));
}
}
break;
//调用相册后返回
case ALBUM_REQUEST_CODE:
if (resultCode == RESULT_OK) {
Uri uri = data.getData();
//开始对图片进行裁剪处理
startPhotoZoom(uri);
}
break;
//调用剪裁后返回
case CROP_SMALL_PICTURE:
Bitmap bitmap = BitmapFactory.decodeFile(getPath());
//让刚才选择裁剪得到的图片显示在界面上,清晰
mMyInfoImg.setImageBitmap(bitmap);
adapter.addData(getPath());
addPicData();
filePath = "";
if (null!=getTempFile()){
tempFile.delete();
}
break;
default:
break;
}
}
/**
* 裁剪图片方法实现
*
* @param uri
*/
private void startPhotoZoom(Uri uri) {
if (uri == null) {
Log.i("tag", "The uri is not exist.");
}
Intent intent = new Intent("com.android.camera.action.CROP");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setDataAndType(uri, "image/*");
// 设置裁剪
intent.putExtra("crop", "true");
intent.putExtra("scale", true);
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 720);
intent.putExtra("outputY", 720);
//设置了true的话直接返回bitmap,可能会很占内存
intent.putExtra("return-data", false);
//不启用人脸识别
intent.putExtra("noFaceDetection", true);
File out = new File(getPath());
if (!out.getParentFile().exists()) {
out.getParentFile().mkdirs();
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(intent, CROP_SMALL_PICTURE);
}
/**
* 裁剪后的地址,保存到本地
*
* @return
*/
public String getPath() {
if (TextUtils.isEmpty(filePath)) {
filePath = Environment.getExternalStorageDirectory() + "/recorderPhone/picture/" + DateTimeUtil.getInstance().getNowLongTime() + ".png";
}
return filePath;
}
/**
* 从相机获取图片
*/
private void getPicFromCamera() {
//跳转到调用系统相机
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//判断版本 如果在Android7.0以上,使用FileProvider获取Uri,否则使用Uri.fromFile(file)方法获取Uri
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(this, getPackageName() + ".provider", getTempFile());
intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
} else {
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile()));
}
startActivityForResult(intent, CAMERA_REQUEST_CODE);
}
/**
* 从相册获取图片
*/
private void getPicFromAlbm() {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, ALBUM_REQUEST_CODE);
}
//-------------------------------------------------------------------------------完-----------------------------------------------------------------------------