调用系统相机拍照与手机图库

最近公司项目,其中有一个用户头像上传的模块,包括调用手机相机拍照上传,以及调用手机图库上传两种方式。在网上收集整理了许多资料,最后才达到了自己的预期,先看效果图。

调用系统相机拍照与手机图库

首先点击详细界面里面头像栏,然后弹出一个activity,这里设置了一下android:theme=”@android:style/Theme.Dialog” : Activity显示为对话框模式,加上一个动画效果,就达到了图示的效果。之所以没用popwindow,因为业务稍微复杂,以后还要上传图片到服务器,用activity实现效果一样,方便管理,相对独立。点击拍照上传,跳转到拍照界面,拍照完成以后,跳转到截取照片的界面,如图所示,点击应用,选择的头像会显示在之前的界面上面;
调用系统相机拍照与手机图库
点击图库上传,会跳转到手机图库,这个手机不一样,界面也会有所差别。然后选择一张自己喜欢的图片,
直接跳转到截取界面,如图所示,点击应用,选择的头像会显示在之前的界面上。
最后就是把截取以后的图片全部保存在了自己定义的文件夹之下,都是320*320px大小的图片,以后再把图片上传到服务器即可。
下面就是具体的实现:

1.页面布局:

<RelativeLayout
                android:id="@+id/doctor_headpicture_rl"
                android:layout_width="match_parent"
                android:layout_height="@dimen/patient_item_hei"
                android:background="@color/white" >

                <com.jxj.followuphelper.view.RoundImageView
                    android:id="@+id/doctor_head_img"
                    style="@style/w_wrap_h_wrap"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:layout_marginBottom="@dimen/margin_bottom"
                    android:layout_marginRight="@dimen/activity_bar"
                    android:layout_marginTop="@dimen/margin_bottom"
                    android:src="@drawable/head_picture_man"
                    imagecontrol:border_outside_color="@color/gray"
                    imagecontrol:border_thickness="@dimen/line_width" />

                <TextView
                    style="@style/w_wrap_h_wrap"
                    android:layout_alignParentLeft="true"
                    android:layout_centerVertical="true"
                    android:layout_marginLeft="@dimen/margin"
                    android:text="@string/set_doctor_picture"
                    android:textColor="@color/black"
                    android:textSize="@dimen/title_name_text" />

                <ImageView
                    style="@style/w_wrap_h_wrap"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:layout_marginRight="18dp"
                    android:adjustViewBounds="true"
                    android:background="@drawable/right_arrow" />
            </RelativeLayout>

布局比较简单,多余代码就不贴了,重点是那个圆形头像的实现,用的是一个继承自imageview的自定义view,外面的边框可以自己设置,使用起来十分方便。

2.功能实现:

private void initviews() {
        headPictureCameraRl.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                // 指定照相机拍照后图片的存储路径,这里存储在自己定义的文件夹下
                if (Environment.MEDIA_MOUNTED.equals(Environment
                        .getExternalStorageState())) {
                    // 创建一个文件夹对象,赋值为外部存储器的目录
                    File sdcardDir = Environment.getExternalStorageDirectory();
                    // 得到一个路径,内容是sdcard的文件夹路径和名字
                    String path = sdcardDir.getPath()
                            + "/FollowUpHelper/cardImages";
                    File photofile = new File(path);
                    if (!photofile.exists()) {
                        // 若不存在,创建目录,可以在应用启动的时候创建
                        photofile.mkdirs();
                    } else {
                        imageUri = Uri.fromFile(new File(photofile,
                                getHeadPictureName()));
                        // 拍照我们用Action为MediaStore.ACTION_IMAGE_CAPTURE,
                        // 有些人使用其他的Action但我发现在有些机子中会出问题,所以优先选择这个
                        Intent intent = new Intent(
                                MediaStore.ACTION_IMAGE_CAPTURE);
                        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
                        // 保存照片在自定义的文件夹下面
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                        startActivityForResult(intent, 1);
                    }
                } else {
                    UiUtil.showToast(context, "SD卡不可用");
                    return;

                }

            }

        });
        headPicturePhotoRl.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                try {
                    // 选择照片的时候也一样,我们用Action为Intent.ACTION_GET_CONTENT,
                    // 有些人使用其他的Action但我发现在有些机子中会出问题,所以优先选择这个
                    Intent intent = new Intent();
                    intent.setType("image/*");
                    intent.setAction(Intent.ACTION_GET_CONTENT);
                    startActivityForResult(intent, 2);
                } catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
            }
        });

首先判断手机的SD卡是否可用,然后获取SD卡的绝对路径,在下面创建自己定义的文件夹用来存储截取的图片。接下里就是给每张截取的图片创建一个uri,用于区分每张图片,后面方法用的是getHeadPictureName(),根据时间的不同来区分。

public String getHeadPictureName() {
        Date date = new Date(System.currentTimeMillis());
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
        return dateFormat.format(date) + ".jpg";

    }

接下来就是调用手机相机与手机图库来选择头像了,注意在选择相机上传的时候加上这句话,intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);这样拍照的照片会暂时保存在自己定义的文件夹下面。手机拍照与图库选择都是使用startActivityForResult()来处理返回的结果。

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        Uri uri = null;
        //如果返回的是拍照上传
        if (data == null) {
            uri = imageUri;
        } //返回的是图库上传
        else {
            uri = data.getData();
        }
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
            case 1:
                intent.setDataAndType(uri, "image/*");
                //下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪
                intent.putExtra("crop", true);
                // 设置裁剪尺寸
                intent.putExtra("aspectX", 1);
                intent.putExtra("aspectY", 1);
                intent.putExtra("outputX", 320);
                intent.putExtra("outputY", 320);
                intent.putExtra("return-data", true);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
                startActivityForResult(intent, 3);
                break;
            case 2:
                intent.setDataAndType(uri, "image/*");
                intent.putExtra("crop", true);
                // 设置裁剪尺寸
                intent.putExtra("aspectX", 1);
                intent.putExtra("aspectY", 1);
                intent.putExtra("outputX", 320);
                intent.putExtra("outputY", 320);
                intent.putExtra("return-data", true);
                // 创建一个文件夹对象,赋值为外部存储器的目录
                File sdcardDir = Environment.getExternalStorageDirectory();
                // 得到一个路径,内容是sdcard的文件夹路径和名字
                String path = sdcardDir.getPath()
                        + "/FollowUpHelper/cardImages";

                File photofile = new File(path);
                uri = Uri.fromFile(new File(photofile, getHeadPictureName()));
                intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
                startActivityForResult(intent, 3);

                break;
            case 3:
                if (data != null) {

                    Intent resultIntent = getIntent();
                    Bundle bundle = data.getExtras();
                    Bitmap myBitmap = bundle.getParcelable("data");
                    resultIntent.putExtra("myBitmap", myBitmap);
                    setResult(1, resultIntent);
                    finish();
                }
                break;
            default:
                break;
            }
        }

通过onActivityResult来处理返回的结果,intent代表跳转到裁剪的界面,然后进行判断,如果是拍照上传的话,图片已经存在自己定义的文件下下面,所以取回的data为空,将imageuri的值传给uri;如果是图库选择上传的话,可以直接从data里面拿到图片的uri;依次设置裁剪类型,可裁剪,裁剪宽高比例与尺寸。然后就是保存裁剪完的图像,在调用手机拍照时,已经创建好了文件夹与文件名,直接覆盖即可;在调用图库上传时候,需要自己重新创建文件夹将裁剪以后的照片保存进来,不加这个的话,会提示“无法保存裁剪完的图片”。保存好裁剪图片以后,接下来就是进行图片的处理了。
这个界面是上一个界面跳转过来的,所以我这里要将图片的bitmap作为返回结果传递给上一个界面,进行显示。

@Override
    protected void onActivityResult(int requestCode, int resultCode,
            Intent intent) {
        if (resultCode == 1) {
            switch (requestCode) {
            case 1:
                Bundle data = intent.getExtras();
                doctorHeadImg.setImageBitmap((Bitmap) data.get("myBitmap"));
                break;

            default:
                break;
            }
        }
    }

很简单的处理一下,然后将照片显示在自定义的view里面即可。最后可以在自己定义的文件夹下面找到裁剪以后的图片,以后用来进行头像的上传。
欧了~~~

上一篇:从源码角度分析NestedScrolling


下一篇:Mac上Charles抓包iOS的https请求