Android选择图片
我的视频课程:《FFmpeg打造Android万能音频播放器》
距离上次更新博客都感觉是好久远的事了,不过不管过多久,有更新总是不错的。今天给大家带来一个自己写的获取Android手机相册图片或相机拍照图片的例子,可以相册可以单选或多选,在单选或相机模式下可以设置是否裁剪,裁剪是调用的系统的裁剪方法,对于6.0以上的系统,会先去申请相机和读写SDcard权限。先简单看几张效果图:
模拟器动态图如下:
手机静态图:
1、
2、
3、
4、
一、老规矩,先说说实现的思路:
(1)首先是相册选择:由于Android的多样性,通过系统来选择图片也是可行的,但是兼容性不好,对不同版本返回的uri解析也不同,而且还不能实现多张同时选择。因此为了达到好的用户体验,就抛弃了系统选择图片的这种方式。因为图片都是存储在手机Sdcard上的,因此我们可以通过扫描Sdcard来获取所以图片的路径,然后再根据路径来获取图片,这样就不会有什么问题了。为了扫描Sdcard,我们使用ContentResolver来查询媒体类型为:jpg或png的图片,然后分文件夹来存储相应的图片路径就可以了。
对于对图片按文件夹分类时,我们只需要存储文件夹的路径和里面第一张图片就行了,就可以把图片列表展示给用户选择,然后选择相应文件夹时,再查询相应文件夹下所有图片类型的文件,获取其实际路径就OK了。
(2)相机拍照:我们可以用默认的方式调用相机拍照,然后在返回的data里面获取图片,但是这个图片是缩略图,不是很清晰。所以我们改变策略,Android系统调用相机拍照时可以设置所拍的照片的存储路径,这样我们就可以自己定义文件路径,然后拍照成功后,到相应路径下面去获取图片就可以了,而且还是高清五码的哦 吼吼。不过我们自己定义图片路径并且保存成功后,还需要做一步就是通知系统刷新图库,这样我们才能及时在图片文件夹列表里面找到我们刚拍摄的图片。
综上:我们对图片的处理都是通过图片的实际路径来获取图片,这样就不会存在兼容性问题了。
二、代码比较多,并且大多都是处理交互UI的,这里就没必要贴出来了,只贴出重要代码即可:
(1)扫描系统图库,并存储所以图片路径和分文件夹存储图片和相应的图片数量:
public void scanImgs() { if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { Toast.makeText(context, "当前存储卡不可用", Toast.LENGTH_SHORT).show(); return; } new Thread() { @Override public void run() { Uri muri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; ContentResolver cr = activity.getContentResolver(); Cursor cursor = cr.query(muri, null, MediaStore.Images.Media.MIME_TYPE + " = ? or " + MediaStore.Images.Media.MIME_TYPE + " = ? ", new String[]{"image/jpeg", "image/png"}, MediaStore.Images.Media.DATE_MODIFIED); Set dirPaths = new HashSet(); int count = cursor.getCount(); for(int i = count - 1; i >= 0; i--) { cursor.moveToPosition(i); String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); if(i == count - 1) { ImgFloderBean imgflder = new ImgFloderBean(); imgflder.setFirstImgPath(path); imgflder.setDirName("所以图片"); imgflder.setType(0); imgflder.setSelected(true); imgFloderBeens.add(imgflder); } ImgBean imgBean = new ImgBean(); imgBean.setPath(path); imgBean.setSelected(false);// checkSelectedImgBeans(imgBean); imgs.add(imgBean); tempImgs.add(imgBean); File parentFile = new File(path).getParentFile(); if (parentFile == null) continue; String dirPath = parentFile.getAbsolutePath(); ImgFloderBean imgFloderBean = null; if (dirPaths.contains(dirPath)) { continue; } else { dirPaths.add(dirPath); imgFloderBean = new ImgFloderBean(); imgFloderBean.setDir(dirPath); imgFloderBean.setFirstImgPath(path); imgFloderBean.setDirName(parentFile.getName()); imgFloderBean.setType(1); imgFloderBean.setSelected(false); imgFloderBeens.add(imgFloderBean); } if (parentFile.list() == null) continue; int picSize = parentFile.list(new FilenameFilter() { @Override public boolean accept(File file, String s) { if (s.endsWith(".jpg") || s.endsWith(".jpeg") || s.endsWith(".png")) return true; return false; } }).length; if (imgFloderBean != null) { imgFloderBean.setSize(picSize); } } cursor.close(); Message message = Message.obtain(); message.what = 0x001; handler.sendMessage(message); } }.start(); }
(2)扫描文件夹下面的图片:
public void scanChildDirPaths(String dirPath) { this.dirPath = dirPath; File file = new File(dirPath); String[]childFilePaths = file.list(new FilenameFilter() { @Override public boolean accept(File file, String s) { if(s.endsWith(".jpg") || s.endsWith(".jpeg") || s.endsWith(".png")) return true; return false; } }); if(childFilePaths != null) { imgGridViewAdapter.setIsaddpath(true); imgGridViewAdapter.setPpath(dirPath); imgs.clear(); int length = childFilePaths.length; for(int i = 0; i < length; i++) { ImgBean imgBean = new ImgBean(); imgBean.setPath(childFilePaths[i]); imgs.add(imgBean); } Collections.reverse(imgs); imgGridViewAdapter.notifyDataSetInvalidated(); } }
(3)相机拍照后,更新系统相册 try { MediaStore.Images.Media.insertImage(context.getContentResolver(), imageUri.getPath(), imgname, null); } catch (FileNotFoundException e) { e.printStackTrace(); } // 最后通知图库更新 context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + file.getPath())));
(4)打开相机,设置自定义图片保存路径:
file = new File(getImgPath()); if (!file.exists()) { file.mkdirs(); } imgname = getHeadImgName(); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); imageUri = Uri.fromFile(new File(file, imgname)); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//设置图片保存路径 activity.startActivityForResult(intent, REQUEST_CAMERA_RESULT_CODE);
这里以申请相机权限为例:
(1)首先判断是否允许调用相机权限
if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)//相机权限 { ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_CODE);//去申请相机权限 }else{}
(2)在onRequestPermissionsResult中处理权限申请结果,如果用户拒绝,则给出相应的提示: if (requestCode == REQUEST_CAMERA_CODE) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(context, "camera--1", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context, "请允许打开摄像头权限", Toast.LENGTH_SHORT).show(); } return; }
四、调用方法(这里是在Activity中)
private PickPhotoDialog pickPhotoDialog; //点击事件里面添加 pickPhotoDialog = new PickPhotoDialog(MainActivity.this, MainActivity.this); Window window = pickPhotoDialog.getWindow(); window.setGravity(Gravity.BOTTOM); window.setWindowAnimations(R.style.DialogEnter); pickPhotoDialog.setCutImg(true, 5);//第一个参数为true:表示图片会被裁剪,此时第二个参数默认为1,只能选择一种图片;为false时,表示不裁剪,然后第二个参数表示选择图片的数量。 pickPhotoDialog.setOnPhotoResultListener(new PickPhotoDialog.OnPhotoResultListener() { @Override public void onCameraResult(String path) {//相机拍照图片路径 List imgBeens = new ArrayList(); ImgBean imgBean = new ImgBean(); imgBean.setPath(path); imgBeens.add(imgBean); adViewpagerUtil = new AdViewpagerUtil(MainActivity.this, viewpager, lydots, 8, 4, imgBeens); adViewpagerUtil.initVps(); } @Override public void onCutPhotoResult(Bitmap bitmap) { //图片(相机和相册)裁剪后返回的bitmap } @Override public void onPhotoResult(List selectedImgs) {//相册多图选择返回图片路径结果集 if(selectedImgs != null && selectedImgs.size() > 0) { adViewpagerUtil = new AdViewpagerUtil(MainActivity.this, viewpager, lydots, 8, 4, selectedImgs); adViewpagerUtil.initVps(); } else { if(adViewpagerUtil != null) { adViewpagerUtil.startLoopViewPager(); } } } }); //权限申请 @TargetApi(23) @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (pickPhotoDialog != null) { pickPhotoDialog.onRequestPermissionsResult(requestCode, permissions, grantResults); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); if(pickPhotoDialog != null) { pickPhotoDialog.onActivityResult(requestCode, resultCode, data); } }
GitHub下载
CSDN下载
更多相关文章
- android相机如何只显示处理后的图像以及这里onPreviewFrame不被
- Android中合多图片和文字合成PDF文件---路很长
- ANDROID XML图像资源文件详细讲解(一)
- Android中的缓存策略—拉取网络图片,缓存本地
- android 新闻图片加载,缓存处理
- Android(安卓)使用ColorMatrix改变图片颜色
- Android(安卓)图片获取及上传
- 使用Glide替换Picasso经验小结
- Android中新建的文件在R没有显示对应的文件解决办法总结