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