作为一个android小白,自己想尝试写一个小项目,因此写个小博客记录一下自己的开发历程。这一篇记录自己学习调取手机相册以及打开相机选择图片并显示

示例是采用PopupWindow弹出底部菜单,选择相应按钮,来显示图片。
第一步:加载好PopupWindow控件,具体代码如下(不详情描述):
PopupWindow控件的xml文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"android:orientation="vertical" ><LinearLayoutandroid:id="@+id/pop_layout"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:gravity="center_horizontal"android:orientation="vertical" ><Buttonandroid:id="@+id/takePhotoBtn"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="10dip"android:layout_marginRight="10dip"android:layout_marginTop="10dp"android:background="#373447"android:padding="10dp"android:text="拍照"android:textColor="#CEC9E7"android:textSize="18sp"android:textStyle="bold" /><Buttonandroid:id="@+id/pickPhotoBtn"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="10dip"android:layout_marginRight="10dip"android:layout_marginTop="5dp"android:background="#373447"android:padding="10dp"android:text="从相册选择"android:textColor="#CEC9E7"android:textSize="18sp"android:textStyle="bold" /><Buttonandroid:id="@+id/cancelBtn"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="15dip"android:layout_marginLeft="10dip"android:layout_marginRight="10dip"android:layout_marginTop="20dp"android:background="@android:color/white"android:padding="10dp"android:text="取消"android:textColor="#373447"android:textSize="18sp"android:textStyle="bold" /></LinearLayout></RelativeLayout>

对应的继承PopupWindow的java代码:

public class ChoosePicPopWindow extends PopupWindow {private Button takePhotoBtn, pickPhotoBtn, cancelBtn;private View mMenuView;@SuppressLint("InflateParams")public ChoosePicPopWindow(Context context, View.OnClickListener itemsOnClick) {super(context);LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);mMenuView = inflater.inflate(R.layout.item_choosepicture, null);takePhotoBtn = (Button) mMenuView.findViewById(R.id.takePhotoBtn);pickPhotoBtn = (Button) mMenuView.findViewById(R.id.pickPhotoBtn);cancelBtn = (Button) mMenuView.findViewById(R.id.cancelBtn);cancelBtn.setOnClickListener(itemsOnClick);pickPhotoBtn.setOnClickListener(itemsOnClick);takePhotoBtn.setOnClickListener(itemsOnClick);//为choosePicPopWindow设置底部菜单视图this.setContentView(mMenuView);//设置宽度this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);//设置高度this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);//是否可点击this.setFocusable(true);//设置弹出窗体动画效果this.setAnimationStyle(R.style.PopupAnimation);//实例化一个颜色为半透明ColorDrawable dw = new ColorDrawable(0x80000000);//设置弹出窗口为半透明this.setBackgroundDrawable(dw);//mMenuView添加OnTouchListener监听判断获取触屏位置如果在选择框外面则销毁弹出框mMenuView.setOnTouchListener(new View.OnTouchListener() {@Override@SuppressLint("ClickableViewAccessibility")public boolean onTouch(View v, MotionEvent event) {int height = mMenuView.findViewById(R.id.pop_layout).getTop();int y = (int) event.getY();if (event.getAction() == MotionEvent.ACTION_UP) {if (y < height) {dismiss();}}return true;}});}
}

其中涉及的style样式:

<style name="PopupAnimation" parent="android:Animation"><item name="android:windowEnterAnimation">@anim/push_bottom_in</item><item name="android:windowExitAnimation">@anim/push_bottom_out</item>
</style>

弹出窗口的动画效果文件
(1)push_button_in.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" ><translateandroid:duration="200"android:fromYDelta="100%p"android:toYDelta="0"        />   <alphaandroid:fromAlpha="0.0"android:toAlpha="1.0"android:duration="200"/>
</set>

(2)push_button_out.xml

<?xml version="1.0" encoding="utf-8"?><!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translateandroid:duration="200"android:fromYDelta="0"android:toYDelta="50%p" />
<alphaandroid:fromAlpha="1.0"android:toAlpha="0.0"android:duration="200"/>
</set>

第二步:填入申请的权限

<!--相机的权限--><uses-permission android:name="android.permission.CAMERA"/>
<!--获取sd卡写的权限,用于文件上传和下载--><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

第三步:点击“相册”按钮,进入相册选取图片然后显示
1.点击按钮判断权限,并发出读取相册意图

if(v.getId() == R.id.pickPhotoBtn){Toast.makeText(MainActivity.this,"选择本地照片",Toast.LENGTH_SHORT).show();//进行权限的判断,看是否申请权限if (ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {// 权限还没有授予,进行申请ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 200); // 申请的 requestCode 为 200} else {// 如果权限已经申请过,直接进行图片选择mpopWindow.dismiss();//关闭底部窗口//传递读取本地相册意图Intent intent = new Intent(Intent.ACTION_PICK);intent.setType("image/*");// 判断系统中是否有处理该 Intent 的 Activityif (intent.resolveActivity(getPackageManager()) != null) {startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);} else {Toast.makeText(MainActivity.this, "未找到图片查看器", Toast.LENGTH_SHORT).show();}}}

注:上面代码的常量以及变量

    private static final int REQUEST_CODE_PICK_IMAGE = 0;           //选择图片private static final int REQUEST_CODE_CAPTURE_CAMEIA = 1;       //拍照private static final String IMAGE_FILE_NAME = "user_head_icon.jpg";     //拍照之后的图片名称private Uri userImageUri;//保存用户头像的ur

2.接受回调的信息(即获取选择好图片返回的uri):

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {Uri imageUri;//resultCode参数为返回的信息,为 RESULT_CANCELED表示失败(简单理解)if (resultCode == RESULT_CANCELED) {Toast.makeText(MainActivity.this, "获取失败", Toast.LENGTH_SHORT).show();img.setImageDrawable(getResources().getDrawable(R.drawable.img_1));//预设的图片} else if(resultCode == RESULT_OK){    //成功switch (requestCode) {//相册照片选择case REQUEST_CODE_PICK_IMAGE:{        //对应上面的常量//返回选择图片的uri,参数data.getData()方法获得imageUri = data.getData();//通过uri的方式返回,部分手机uri可能为空Bitmap bm = null;if(imageUri != null){try {//将获得的图片uri进行压缩,不然图片像素过大,可能会出现错误bm = getBitmapFormUri(imageUri); //此方法在下面} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}else {//部分手机可能直接存放在bundle中Bundle bundleExtras = data.getExtras();if(bundleExtras != null){bm = bundleExtras.getParcelable("data");}}img.setImageBitmap(bm);      //显示图片break;}

注:在相册选择的图片,会下面拍照之后的照片都可能需要压缩像素,不然像素过大,可能会出现问题。下面这段代码可以不需要理解,太麻烦直接粘贴复制就好

//压缩图片像素public Bitmap getBitmapFormUri(Uri uri) throws FileNotFoundException, IOException {InputStream input = getContentResolver().openInputStream(uri);//这一段代码是不加载文件到内存中也得到bitmap的真是宽高,主要是设置inJustDecodeBounds为trueBitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();onlyBoundsOptions.inJustDecodeBounds = true;//不加载到内存onlyBoundsOptions.inDither = true;//optionalonlyBoundsOptions.inPreferredConfig = Bitmap.Config.RGB_565;//optionalBitmapFactory.decodeStream(input, null, onlyBoundsOptions);input.close();int originalWidth = onlyBoundsOptions.outWidth;int originalHeight = onlyBoundsOptions.outHeight;if ((originalWidth == -1) || (originalHeight == -1))return null;//图片分辨率以480x800为标准float hh = 800f;//这里设置高度为800ffloat ww = 480f;//这里设置宽度为480f//缩放比,由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可int be = 1;//be=1表示不缩放if (originalWidth > originalHeight && originalWidth > ww) {//如果宽度大的话根据宽度固定大小缩放be = (int) (originalWidth / ww);} else if (originalWidth < originalHeight && originalHeight > hh) {//如果高度高的话根据宽度固定大小缩放be = (int) (originalHeight / hh);}if (be <= 0)be = 1;//比例压缩BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inSampleSize = be;//设置缩放比例bitmapOptions.inDither = true;bitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;input = getContentResolver().openInputStream(uri);Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);input.close();return compressImage(bitmap);//再进行质量压缩}public Bitmap compressImage(Bitmap image) {ByteArrayOutputStream baos = new ByteArrayOutputStream();image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中int options = 100;while (baos.toByteArray().length / 1024 > 100) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩baos.reset();//重置baos即清空baos//第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差  ,第三个参数:保存压缩后的数据的流image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options,把压缩后的数据存放到baos中options -= 10;//每次都减少10if (options<=0)break;}ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片return bitmap;}

第三步:调取相机拍照,并显示图片
1.点击按钮,判断权限,并打开相机拍照

else if(v.getId() == R.id.takePhotoBtn){Toast.makeText(MainActivity.this,"照相",Toast.LENGTH_SHORT).show();if (ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED|| ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {// 权限还没有授予,进行申请ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 300); // 申请的 requestCode 为 300} else {// 权限已经申请,直接拍照mpopWindow.dismiss();imageCapture();}}

2.拍完照,发送意图

//跳转到拍照,拍完并intent发送请求private void imageCapture() {Intent intent;//也就是我存放头像的文件夹(目录)File pictureFile = new File(Environment.getExternalStorageDirectory()+File.separator+"MyText", IMAGE_FILE_NAME);     //第二个参数为图片的名字,在上面常量里if(!pictureFile.getParentFile().exists()){pictureFile.getParentFile().mkdirs();}// 判断当前系统,android7.0以上版本if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);/*FileProvider是ContentProvider的一个子类,用于应用程序之间私有文件的传递,需要在清单里配置,代码在下方。实际的getUriForFile就是FileProvider.getUriForFile("上下文","清单文件中authorities的值","共享的文件");*/userImageUri = FileProvider.getUriForFile(MainActivity.this,"com.example.dell.test", pictureFile);} else {intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);userImageUri = Uri.fromFile(pictureFile);}// 去拍照,拍照的结果存到oictureUri对应的路径中intent.putExtra(MediaStore.EXTRA_OUTPUT, userImageUri);Log.e(TAG,"before take photo"+userImageUri.toString());startActivityForResult(intent, REQUEST_CODE_CAPTURE_CAMEIA);}

注:(1)清单的配置

<application***<provider<!--name为FileProvider所在的v4报的路径,不需要改就这么填-->android:name="android.support.v4.content.FileProvider"<!--这个为自己定义,在上面getUriForFile的第二个参数就是这个,建议为自己demo的包名-->android:authorities="com.example.dell.test"<!--代表是否可以输出被外部程序使用,填false就行-->android:exported="false"<!-- 是否允许为文件授予临时权限,必须为true-->android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"<!--对应的xml文件路径-->android:resource="@xml/provider_paths" /></provider>

(2)指定可共享的文件路径
(这一部分不好理解,可以去参考这个大神,https://www.jianshu.com/p/6c51202c845d)

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android"><external-path path="MyText/" name="MyTextRoot" /><external-path name="sdcard_root" path="."/>
</paths>

3.得到uri,然后显示即可全部完成

case REQUEST_CODE_CAPTURE_CAMEIA: {      //拍照常量Bitmap bm1 = null;try {bm1 = getBitmapFormUri(userImageUri);        //压缩照片} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}img.setImageBitmap(bm1);         //显示照片break;}

以上即可完成。最终效果是在真机上显示,所以无法放在这上面

android调取手机相册或打开相机选择图片并显示相关推荐

  1. vue H5app plus调取手机相册,限制图片大小,图片转base64

    vue H5app plus调取手机相册,限制图片大小,图片转base64 直接上代码 filmImg(){ //移动端发送图片let _this = this plus.gallery.pick(f ...

  2. Swift使用UIImagePickerController 从相册选择图片、从相机选择图片

    配置: 如果是相机使用,需要在info.plist文件增加使用前应用程序说明:相机使用也是如此.(第二个是CALENDARS权限,打错了:图片是Photo Library Usage Descript ...

  3. 点击button按钮打开file选择图片并使用ajax图片上传并预览

    最近有个需求让人很无奈,每条记录都需要让用户上传图片.由于使用插件无法准确的定位到那条记录,只好使用ajax上传图片准确获取id 先将file文件隐藏掉,通过点击button打开file选择图片,一些 ...

  4. 手机php网站不显示图片,javascript,_手机页面用innerHTML拼接的图片不显示,javascript - phpStudy...

    手机页面用innerHTML拼接的图片不显示 测试代码 input,button{ height:35px; } add function addEmotion(t){ alert(t); } var ...

  5. php file取不到手机相册,webuploader移动端选择文件无法打开手机相册的解决办法...

    webuploader移动端选择文件无法打开手机相册的解决办法 本文为转载: 原文链接:http://www.juguw.net/article-2325.html webUploader是一款不错的 ...

  6. android点击按钮打开相册,打开相机的代码

    打开相册 首先在onclick方法中: Intent intent = new Intent(); intent.setType("image/*");// 开启Pictures画 ...

  7. android 7.0之后的打开相机拍摄头像上传

    今天一天都在搞这个头像相关的android开发,不断的在网上查找资料,什么都不懂,然后就照抄. 就是一个什么问题呢,现在android打开一个相机不再简单的请求打开就行了,按照我今天查到的资料,就是说 ...

  8. Xamarin 打开相机 选择系统照片并上传服务器

    1. 首先在AndroidManifest.xml中进行配置权限 <!-- 这两个权限用于进行拍照存储权限--><uses-permission android:name=" ...

  9. android调取系统相册和照相机选取图片

    在让用户自定义头像或皮肤的时候 可能会采取照相或选取相册等方法来实现用户自定义,这里我们就简单实现一下~ 在这里先贴出布局-----仅供参考 activity_main://一张图片而已  很简单 & ...

最新文章

  1. mysql 多少个数据库_mysql数据库的几个基本概念
  2. [C#]从URL中获取路径的最简单方法-new Uri(url).AbsolutePath
  3. Worktile 技术架构概要
  4. 更极速:EdgeRoutine边缘程序
  5. 国内机床发展水平和现状
  6. java的文本框如何回车键触发按钮_java回车触发按钮的代码
  7. DesiredCapabilities内容详解(摘)
  8. 【云周刊】第141期:阿里正式发布《Java开发手册》终极版!绝对珍藏!
  9. 智慧校园: 00 开发流程
  10. 美团外卖订单中心的演进
  11. 领导力有哪些方面?什么是领导力?
  12. 动态规划 机器人军团 POJ2533 中等
  13. 对话管理DST:Deep Neural Network Approach for the Dialog State Tracking Challenge
  14. 【学习记录2】数组里的字符串转换成数字或者把数字转换成字符串
  15. 关于Window10系统无法打开Microsoft Store(应用商店)解决方案
  16. C++-queue:queue基本用法【q.push(x)、q.front()、q.back()、q.pop()、q.size()、q.empty()】
  17. mysql联合索引和索引优化的理解
  18. http拨测是什么意思_网络性能拨测-网络传输速度体验检测系统有哪些指标?
  19. 关于如何清除百度全家桶的一些经验
  20. ARMV8体系结构简介:exclusive操作例子

热门文章

  1. 微信小程序以SpringBoot作为后端开发遇到的问题及解决思路总结
  2. Lintcode 428. Pow(x, n) (Medium) (Python)
  3. 22年春晚,一个让元宇宙照进现实的沉浸式演出舞台
  4. 仅用1天!腾讯协助警方破获伪造交警罚单诈骗案
  5. 为永嘉路故店合弛的宣扬口号毛病援用“法租界”做替店址的描述
  6. python刷页面浏览量
  7. android启动微信服务器,Android之高仿微信“启动画面”(一)
  8. 【webpack】前端工程化与webpack
  9. c语言sizeof char,sizeof(char),sizeof(char*),sizeof(char[4]),
  10. 电信重组又起,对移动软件供应商与SP的影响有哪些!思考:如何从3G网络中找寻我们程序员的价值..