一直以来都说要写博客,前面好几篇都是写了标题,就没写内容,看了鸿洋大神和吴小龙同学的博客,决定自己也开始写属于自己的博客,并且坚持下来.
先要把自己以前留下的坑给弥补上,今天先完成更换头像的操作,根据项目中实际的需求,步骤一步步完成.
在我实际的项目开发中,点击更换头像按钮,会进入到一个选择图片的界面,这个界面会预先给24张头像供用户选择.当用户点击随意一张时,返回原来的界面,并更换头像,同时会在24张头像上方显示一个最近使用图片这么一项,最近使用图片最多可以有8张,
这是实现的效果图,下面是使用gridView做的,上面是使用线性布局动态添加一个个View上去,实现的效果.在这里要说一下,GridView添加头布局使用的是GridViewWithHeaderAndFooter这么一个控件,github的地址,使用方法很合listview添加头布局一样,直接add就行,需要注意的是,也需要放在setAdapter前面进行.
点击右上角的按钮,会让选择是拍照还是从系统图库选择照片,这里先介绍调用系统的相机进行拍照,下面是实现的代码:
/**
* 开启相机
*/
private void startCarema() {
// 激活相机
Intent intentCarema = new Intent("android.media.action.IMAGE_CAPTURE");
// 判断存储卡是否可以用,(判断存储卡是否可用的方法没有提供),可用进行存储
if (hasSdcard()) {
tempFile = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + "");
// 从文件中创建uri
Uri uri = Uri.fromFile(tempFile);
intentCarema.putExtra(MediaStore.EXTRA_OUTPUT, uri);
}
// 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CAREMA
startActivityForResult(intentCarema, REQUESTCODE_CAREMA);
}
/**
* 判断sdcard是否被挂载
* @return 判断是否有sd卡
*/
public static boolean hasSdcard() {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
return true;
} else {
return false;
}
}
这样就会调用系统的相机进行拍照,然后返回一个uri,根据uri获取到图片保存在本地的文件地址,得到这个文件地址就可以去操作自己想要的逻辑
case REQUESTCODE_CAREMA: //这里判断是否是从相机界面返回
if (hasSdcard()) {
Uri uri = Uri.fromFile(tempFile);
//这里得到文件在本地的地址
String filePath = getRealFilePath(this, uri);
} else {
Toast.makeText(this, "未找到存储卡,无法存储照片!", Toast.LENGTH_SHORT).show();
}
break;
这是根据uri获取本地文件地址的方法:
/**
* 根据uri获取图片的真实路径(本地存储的路径)
* @param context
* @param uri
* @return
*/
public static String getRealFilePath(final Context context, final Uri uri) {
if (null == uri) return null;
final String scheme = uri.getScheme();
String data = null;
if (scheme == null)
data = uri.getPath();
else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
data = uri.getPath();
} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
if (null != cursor) {
if (cursor.moveToFirst()) {
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
if (index > -1) {
data = cursor.getString(index);
}
}
cursor.close();
}
}
return data;
}
上面是打开系统的相机,返回所拍的照片,返回的是uri,需要转换成本地的文件地址,然后再进行后续的操作,因为国产的手机rom不同,有的照片可能会进行过特殊处理,例如三星的会对照片进行旋转90度,所以在显示图片的时候,需要判断照片是否旋转了.
/**
* 读取照片exif信息中的旋转角度
*
* @param path 照片路径
* @return int 照片的旋转家督
*/
public static int readPictureDegree(String path) {
int degree = 0;
try {
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;
}
如果旋转了就需要旋转回正确的角度.
/**
* degree就是上面那个方法计算出来旋转的角度
*/
public static Bitmap toTurn(Bitmap img, int degree) {
Log.d("ClipPhotoActivity", "degree:" + degree);
Matrix matrix = new Matrix();
matrix.postRotate(+degree); /*翻转90度*/
int width = img.getWidth();
int height = img.getHeight();
img = Bitmap.createBitmap(img, 0, 0, width, height, matrix, true);
return img;
}
当前项目只是遇到这样的问题,如果后续遇到问题,再添加(加载图片的时候注意OOM异常).
下面是调用系统的图库选取图片,很简单就是几行代码:
/**
* 进入系统图库
*/
private void startSystemGallery() {
//进入系统图库
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, REQUESTCODE_LOCATIONPHOTO);
}
在得到的返回值里进行处理:
case REQUESTCODE_LOCATIONPHOTO: // 从相册返回的数据
if (data != null) {
// 得到图片的全路径
Uri uri = data.getData();
String filePath = getRealFilePath(this, uri);
}
break;
不管是从相机获取到图片还是从图库获取到图片,最后都获取到图片在本地存储的地址,如果各个界面之间需要将图片作为参数携带跳转的话,就使用图片的地址传递,如果之间传递图片的话,会超过intent所能携带的最大值.
当然很少有情况是需要显示图库或者相机的照片,一般都是需要拿来裁剪做头像才使用这样的功能,这样就牵扯到使用裁剪的功能,裁剪可以使用系统的裁剪或者使用第三方的裁剪.
使用系统的裁剪功能:
private void cropImageUri(Uri uri, int outputX, int outputY, int requestCode) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
//是否裁剪
intent.putExtra("crop", "true");
//设置xy的裁剪比例
intent.putExtra("aspectX", 2);
intent.putExtra("aspectY", 1);
//设置输出的宽高
intent.putExtra("outputX", outputX);
intent.putExtra("outputY", outputY);
//是否缩放
intent.putExtra("scale", false);
//输入图片的Uri,指定以后,可以在这个uri获得图片
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
//是否返回图片数据,可以不用,直接用uri就可以了
intent.putExtra("return-data", false);
//设置输入图片格式
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
//是否关闭面部识别
intent.putExtra("noFaceDetection", true); // no face detection
//启动
startActivityForResult(intent, requestCode);
}
我这个项目使用的是鸿洋的控件博客地址,也可以使用更为强大的裁剪控件uCrop的github地址,都是可以的,根据自己项目中的需求来完成.
第一篇大致博客完成了,感觉写的不是很好,我相信会慢慢的好起来的