android 从图库或者相机拍照获得照片并显示在界面上

    首先,不管是从图库还是从打开相机拍照,都是先拿到照片的路径,然后再对照片进行处理,比如要先压缩,因为现在的照片比较大,如果不进行压缩,会造成内存溢出,而且由于手机型号的不同,也会是拍出来的照片角度不同,所以我们也要对照片进行旋转角度,最后再展示到界面上。效果如下:

拍照 这里写图片描述

不管是打开图库,还是打开相机,这些代码网上都有,我给整合了一下,代码如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnLongClickListener {

    protected Button btn;
    protected com.nex3z.flowlayout.FlowLayout mFlowLayout;
    protected Button btnGallery;
    private String filename;
    private String name;
    protected ArrayList<String> addresses = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.activity_main);
        initView();
        filename = Environment.getExternalStorageDirectory().getAbsolutePath() + "/photos/";
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        //在这保存 name 的数据
        outState.putString("name", name);
    }

    //读取数据
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        name = savedInstanceState.getString("name");
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.btn) {
            takephoto();
        } else if (view.getId() == R.id.btn_gallery) {
           openGallery();
        }
    }

    //打开图库
    private void openGallery() {
        /**
         *以带结果的方式启动Intent,这样就可以拿到图片地址
         */
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        intent.putExtra("crop", true);
        intent.putExtra("return-data", true);
        startActivityForResult(intent, 1);

    }

    //拍照
    private void takephoto() {
        //判断是否有相机
        boolean b = PhotoUtils.hasCamera(MainActivity.this);
        if (b) {
            name = getPhotoFileName();
            File mFile = new File(filename);
            if (!mFile.exists()) {
                mFile.mkdirs();
            }
            File mPhotoFile = new File(filename, name);
            Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            Uri fileUri = Uri.fromFile(mPhotoFile);
            captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
            startActivityForResult(captureIntent, 0);
        } else {
            Toast.makeText(MainActivity.this, "系统无相机", Toast.LENGTH_SHORT).show();
        }

    }

    private String getPhotoFileName() {
        Date date = new Date(System.currentTimeMillis());
        SimpleDateFormat dateFormat = new SimpleDateFormat(
                "'IMG'_yyyyMMdd_HH-mm-ss");
        return dateFormat.format(date) + ".jpg";
    }

    //拿到照片
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            //获取到相机拍的照片
            if (requestCode == 0) {

                String filestr = filename + "/" + name;
                //向flowlayout中添加图片
                addPhotoToFlow(filestr);

            }
            //获取到图库的照片
            if (requestCode == 1) {
                Uri selectedImage = data.getData();
                String[] filePathColumn = {MediaStore.Images.Media.DATA};
                Cursor cursor = this.getContentResolver().query(selectedImage,
                        filePathColumn, null, null, null);
                cursor.moveToFirst();
                int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                //picturePath就是图片在储存卡所在的位置
                String picturePath = cursor.getString(columnIndex);
                Log.e("aaa","pocture===>"+picturePath);

                cursor.close();
                addPhotoToFlow(picturePath);
            }

        }
    }

    /**
     * 通过拿到图片的地址来向mFlowLayout中添加ImageView
     * @param filestr
     */
    private void addPhotoToFlow(String filestr) {
        //获取旋转角度
        int degree = PhotoUtils.getBitmapDegree(filestr);
        //压缩图片
        Bitmap bitmap1 = PhotoUtils.decodeSampledBitmapFromFd(filestr, 250, 250);
        //根据旋转角度旋转图片
        Bitmap bitmap2 = PhotoUtils.rotateBitmapByDegree(bitmap1, degree);

        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        ImageView imageView = new ImageView(this);
        params.setMargins(15, 15, 15, 15);
        imageView.setLayoutParams(params);
        imageView.setBackgroundResource(R.drawable.shape_img_bg);
        imageView.setPadding(18, 18, 18, 18);
        imageView.setTag(filestr);
        imageView.setOnLongClickListener(this);
        imageView.setImageBitmap(bitmap2);
        addresses.add(filestr);
        mFlowLayout.addView(imageView);
    }

    private void initView() {
        btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(MainActivity.this);
        mFlowLayout = (com.nex3z.flowlayout.FlowLayout) findViewById(R.id.mFlowLayout);
        btnGallery = (Button) findViewById(R.id.btn_gallery);
        btnGallery.setOnClickListener(MainActivity.this);
    }

    @Override
    public boolean onLongClick(final View view) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("删除");
        builder.setPositiveButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {

            }
        });
        builder.setNegativeButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                String tag = (String) view.getTag();
                mFlowLayout.removeView(view);
                addresses.remove(tag);

            }
        });
        builder.create().show();
        return true;
    }
}

PhotoUtils工具类的代码:

public class PhotoUtils {


    /**
     * 判断系统中是否存在可以启动的相机应用
     *
     * @return 存在返回true,不存在返回false
     */
    public static boolean hasCamera(Context context) {
        PackageManager packageManager = context.getPackageManager();
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        List list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        return list.size() > 0;
    }


    /**
     * 获取图片的旋转角度
     *
     * @param path 图片绝对路径
     * @return 图片的旋转角度
     */
    public static int getBitmapDegree(String path) {
        int degree = 0;
        try {
            // 从指定路径下读取图片,并获取其EXIF信息
            ExifInterface exifInterface = new ExifInterface(path);
            // 获取图片的旋转信息
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 将图片按照指定的角度进行旋转
     *
     * @param bitmap 需要旋转的图片
     * @param degree 指定的旋转角度
     * @return 旋转后的图片
     */
    public static Bitmap rotateBitmapByDegree(Bitmap bitmap, int degree) {
        // 根据旋转角度,生成旋转矩阵
        Matrix matrix = new Matrix();
        matrix.postRotate(degree);
        // 将原始图片按照旋转矩阵进行旋转,并得到新的图片
        Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        if (bitmap != null & !bitmap.isRecycled()) {
            bitmap.recycle();
        }
        return newBitmap;
    }

    // 从sd卡上加载图片
    public static Bitmap decodeSampledBitmapFromFd(String pathName,
                                                   int reqWidth, int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        //我们需要先拿到原有图片的宽和高,所以可以通过设置inJustDecodeBounds = true来忽略能够显示在屏幕上的色素点
        //而只采集边框。
        options.inJustDecodeBounds = true;
        //采集完图片信息之后把图片属性存储到options
        BitmapFactory.decodeFile(pathName, options);
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        //已经计算出来缩放的比例,我们可以按照缩放的比例对图片进行处理,生成新的图片,
        //这个事时候吧inJustDecodeBounds设置为false,意味着并不是只采集边框,还需要像素点。
        options.inJustDecodeBounds = false;
        Bitmap src = BitmapFactory.decodeFile(pathName, options);
        return createScaleBitmap(src, reqWidth, reqHeight);
    }

    //缩放的比例
    private static int calculateInSampleSize(BitmapFactory.Options options,
                                             int reqWidth, int reqHeight) {
        //图片的本身的大小
        final int height = options.outHeight;
        final int width = options.outWidth;
        //缩放比例
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
            //图片本身大小与期望图片的大小做比较,若本身宽高大于期望,需要缩小本身的大小
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }

    // 如果是放大图片,filter决定是否平滑,如果是缩小图片,filter无影响
    private static Bitmap createScaleBitmap(Bitmap src, int dstWidth,
                                            int dstHeight) {
        Bitmap dst = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false);
        if (src != dst) { // 如果没有缩放,那么不回收
            src.recycle(); // 释放Bitmap的native像素数组
        }
        return dst;
    }

}

activity_main.xml 的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.dt.photo.MainActivity">

        <Button
            android:id="@+id/btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="拍照" />

        <Button
            android:id="@+id/btn_gallery"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="从图库中获取" />

        <com.nex3z.flowlayout.FlowLayout
            android:id="@+id/mFlowLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        </com.nex3z.flowlayout.FlowLayout>

    </LinearLayout>
</ScrollView>

shape_img_bg.xml的代码:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <stroke
        android:width="2dp"
        android:color="#CCCCCC" />

</shape>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ljp345775

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值