最近项目要求做一个仿微信朋友圈拍照获取照片显示上传,要对图片进行压缩处理,防止OOM,废话不多说,下面进行拍照功能实现:
实现效果如图:
1.选择界面:
预览界面(可以根据手势放大缩小):
已经封装成一个lib包,直接添加项目依赖就能使用:
下载依赖包地址源码:
https://download.csdn.net/download/zqr772791008/10300742
项目大概长这样:
对类的说明:
开始之前记得添加权限:
android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> android:name="android.permission.WAKE_LOCK" /> android:name="android.permission.CAMERA"/> android:name="com.zoesoft.mobile.imagezoom.activity.ImagePagerActivity" >
使用方法例子:
package com.example.administrator.myapplication.photo; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import com.example.administrator.myapplication.R; import java.util.ArrayList; public class photoActivity extends AppCompatActivity implements IMakePic { RecyclerView mRecyclerView; MakePhotoAdapter mMakePicAdapter; ArrayListphotoInfos = new ArrayList<>(); TakePhotoUtil takePhotoUtil; // 相机取图 private static final int CAMERA_WITH_DATA = 1000; private String imageUrl; private Uri imageUri; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_photo); mRecyclerView = (RecyclerView) findViewById(R.id.rv_addphoto); takePhotoUtil = new TakePhotoUtil(CAMERA_WITH_DATA,this,this); //图片列表 GridLayoutManager mLayoutManager = new GridLayoutManager(this, 3); mRecyclerView.setLayoutManager(mLayoutManager); mMakePicAdapter = new MakePhotoAdapter(this, photoInfos, this, Constatnt.EDIT); mMakePicAdapter.setMaxCount(9); mRecyclerView.setAdapter(mMakePicAdapter); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == CAMERA_WITH_DATA && resultCode == RESULT_OK ) { // luban(); takePhotoUtil.luBanCompress();//压缩图片 } } @Override public void takePic() { // doTakePhoto(); takePhotoUtil.doTakePhoto();//开启相机 } @Override public void onImageUpload(String url) { photoInfos.add(url); Log.e("photoInfos的大小",""+photoInfos.size()); mMakePicAdapter.setDataList(photoInfos); } }
关键代码:
1.Constatnt类:
package com.example.administrator.myapplication.photo; public class Constatnt { /** * 图片显示的最大数量 */ public static final int MAX_COUNT = 9; /** * 是否显示增加按钮 */ public static final int ITEM_ADD = 0; public static final int ITEM_CONTENT = 1; /** * 显示图片 */ public static final int SHOW = 10000; /** * 编辑图片 */ public static final int EDIT = 20000; }
2.IMakePic:
package com.example.administrator.myapplication.photo; public interface IMakePic { /** * 拍照片 */ void takePic(); /** * 图片压缩获取成功以后的回调接口 */ void onImageUpload(String url); }
3.MakePhotoAdapter:
package com.example.administrator.myapplication.photo; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import com.bumptech.glide.Glide; import com.example.administrator.myapplication.R; import com.example.administrator.myapplication.photo.imagezoom.util.ImageZoom; import com.nostra13.universalimageloader.core.download.ImageDownloader; import java.util.ArrayList; import java.util.List; public class MakePhotoAdapter extends RecyclerView.Adapter{ private Context mContext = null; private LayoutInflater mInflater = null; List mPhotoInfoList = new ArrayList<>(); private IMakePic mMakePic = null; /** * 显示还是编辑 */ private int type = Constatnt.SHOW; /** * 图片选取的最大数量,当达到最大数量是,不显示增加按钮 */ private int maxCount = Constatnt.MAX_COUNT; public int getType() { return type; } public void setType(int type) { this.type = type; } public int getMaxCount() { return maxCount; } public void setMaxCount(int maxCount) { this.maxCount = maxCount; } public MakePhotoAdapter(Context context, List photoInfoList, IMakePic makePic) { this(context, photoInfoList, makePic, Constatnt.EDIT); } public MakePhotoAdapter(Context context, List photoInfoList, IMakePic makePic, int type) { mContext = context; mPhotoInfoList = photoInfoList; mMakePic = makePic; this.type = type; mInflater = LayoutInflater.from(mContext); } /** * 判断是否需要显示一个增加按钮,当达到最大数量是不显示增加按钮 * @return */ @Override public int getItemCount() { if (getType() == Constatnt.SHOW) { return mPhotoInfoList.size(); } else { int num = mPhotoInfoList.size(); return num == getMaxCount() ? getMaxCount() : ++num; } } /** * 判断选择哪种布局,一种是显示布局,一种是增加布局(有删除按钮) * @param position * @return */ @Override public int getItemViewType(int position) { if (getType() == Constatnt.SHOW) { return Constatnt.ITEM_CONTENT; } else { if (position == mPhotoInfoList.size()) { return Constatnt.ITEM_ADD; } return Constatnt.ITEM_CONTENT; } } /** * 返回列表数据 * * @return */ public List getDataList() { return this.mPhotoInfoList; } /** * 更新数据集 * @param dataList */ public void setDataList(ArrayList dataList) { mPhotoInfoList = dataList; notifyDataSetChanged(); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (getType() == Constatnt.SHOW) { return new ContentViewHolder(mInflater.inflate(R.layout.item_adapter_photo_list, parent, false)); } else { if (viewType == Constatnt.ITEM_ADD) { return new AddViewHolder(mInflater.inflate(R.layout.item_photo_add, parent, false)); } else { return new ContentViewHolder(mInflater.inflate(R.layout.item_adapter_photo_list, parent, false)); } } } @Override public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) { //显示图片数据 if (holder instanceof ContentViewHolder) { String path =mPhotoInfoList.get(position) ; if (path.contains("storage")) { path =ImageDownloader.Scheme.FILE.wrap(path); } //加载图片 Glide.with(mContext).load(path).into(((ContentViewHolder) holder).mIvPhoto); //图片右上角显示删除按钮 ((ContentViewHolder) holder).mIvDelete.setVisibility(View.VISIBLE); final String finalPath = path; //删除按钮操作 ((ContentViewHolder) holder).mIvDelete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getDataList().remove(holder.getLayoutPosition()); notifyDataSetChanged(); } }); //查看预览图 ((ContentViewHolder) holder).mIvPhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // ImageZoom.show(mContext, finalPath, ImageZoom.LOCAL); ImageZoom.show(mContext, position,mPhotoInfoList ); } }); } else if (holder instanceof AddViewHolder) { //显示添加按钮 ((AddViewHolder) holder).mImageAdd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mMakePic != null) mMakePic.takePic(); } }); } } public static class AddViewHolder extends RecyclerView.ViewHolder { ImageView mImageAdd; public AddViewHolder(View footView) { super(footView); mImageAdd = (ImageView) itemView.findViewById(R.id.imageviewadd); } } public static class ContentViewHolder extends RecyclerView.ViewHolder { ImageView mIvPhoto; ImageView mIvDelete; public ContentViewHolder(View itemView) { super(itemView); mIvPhoto = (ImageView) itemView.findViewById(R.id.iv_photo); mIvDelete = (ImageView) itemView.findViewById(R.id.iv_delete); } } }
4.PhotoFileUtils:
package com.example.administrator.myapplication.photo; import android.os.Environment; import android.text.TextUtils; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class PhotoFileUtils { private static String rootPath = "TakePhoto"; private static String playPath = ""; private final static String PHOTO_JPG_BASEPATH = "/" + rootPath + "/img/"; private final static String PHOTO_COMPRESS_JPG_BASEPATH = "/" + rootPath + "/CompressImg/"; public static void setRootPath(String rootPath) { PhotoFileUtils.rootPath = rootPath; } //获取保存原始文件的位置 public static String getJpgFileAbsolutePath(String fileName) { if (TextUtils.isEmpty(fileName)) { throw new NullPointerException("fileName isEmpty"); } String photoPath = ""; if (!fileName.endsWith(".jpg")) { fileName = fileName + ".jpg"; } String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + PHOTO_JPG_BASEPATH; File file = new File(fileBasePath); if (!file.exists()) { file.mkdirs(); } photoPath = fileBasePath + fileName; return photoPath; } // //获取保存压缩图片文件的位置 public static String getCompressJpgFileAbsolutePath(){ String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + PHOTO_COMPRESS_JPG_BASEPATH; File file = new File(fileBasePath); if (!file.exists()) { file.mkdirs(); } return fileBasePath; } /** * 获取全部压缩jpg文件列表 * * @return */ public static ListgetJpgFiles() { List list = new ArrayList<>(); String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + PHOTO_COMPRESS_JPG_BASEPATH; File rootFile = new File(fileBasePath); if (!rootFile.exists()) { } else { File[] files = rootFile.listFiles(); for (File file : files) { list.add(file); } } Collections.reverse(list); //倒序排列 return list; } /** * 获取全部压缩jpg文件列表 * * @return */ public static List getPcmFilesPath() { List list = new ArrayList<>(); String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + PHOTO_COMPRESS_JPG_BASEPATH; File rootFile = new File(fileBasePath); if (!rootFile.exists()) { } else { File[] files = rootFile.listFiles(); for (File file : files) { list.add(file.getPath()); } } Collections.reverse(list); //倒序排列 return list; } }
5.TakePhotoUtil:
package com.example.administrator.myapplication.photo; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; import android.util.Log; import android.widget.ActionMenuView; import android.widget.Toast; import java.io.File; import top.zibin.luban.Luban; import top.zibin.luban.OnCompressListener; /** * Created by Administrator on 2017/12/28. */ public class TakePhotoUtil { private Activity mContext; private String imageUrl;//照片的url private Uri imageUri;//照片的uri private IMakePic iMakePic; private int mRequestCode; /** * 图片压缩获取成功以后的回调接口 */ public TakePhotoUtil(int requestCode,Context context, IMakePic imakePic) { this.mContext = (Activity) context; this.iMakePic = imakePic; this.mRequestCode = requestCode; } // 开启相机 public void doTakePhoto() { String SDState = Environment.getExternalStorageState(); if(SDState.equals(Environment.MEDIA_MOUNTED)) { imageUrl = PhotoFileUtils.getJpgFileAbsolutePath( System.currentTimeMillis() + ".jpg"); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); imageUri = Uri.fromFile(new File(imageUrl)); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); mContext.startActivityForResult(intent, mRequestCode); }else { Toast.makeText(mContext, "内存卡不存在!",Toast.LENGTH_LONG).show(); } } //压缩图片 public void luBanCompress(){ Luban.with(mContext) .load(new File(imageUrl)) .putGear(3)//设置压缩级别 默认是3 .setTargetDir(PhotoFileUtils.getCompressJpgFileAbsolutePath()) .setCompressListener(new OnCompressListener() { @Override public void onStart() { } @Override public void onSuccess(File file) { Log.e("path", file.getAbsolutePath()); Log.e("压缩以后file大小", file.length()+""); File oldfile = new File(imageUrl);//删掉旧文件 if (oldfile.exists()) { oldfile.delete(); } if (iMakePic != null){ iMakePic.onImageUpload(file.getAbsolutePath()); } // photoInfos.add(file.getAbsolutePath()); // Log.e("photoInfos的大小",""+photoInfos.size()); // mMakePicAdapter.setDataList(photoInfos); } @Override public void onError(Throwable e) { } }) .launch(); } }