项目开发中碰到了类似微信的图片选择、图片压缩及上传,一开始利用一些第三方的进行修改,但是很容就出现内存溢出,而有些比较优秀的第三方的多半是采用远程依赖的方式集成开发的,很难对源码进行改动而达到自己的需求,后面在跟大牛的学习过程中,就写了一个简单的图片选择,已用于项目开发,并没有出现内存溢出。
简单的对实现做一个说明:
1、图片压缩采用的是第三方的鲁班图片压缩;

github:[https://github.com/Curzibn/Luban](https://github.com/Curzibn/Luban)

2、图片加载采用的是glide;

compile 'com.github.bumptech.glide:glide:3.7.0'

3、图片展示列表用的是recyclerview实现的;

compile 'com.android.support:recyclerview-v7:25.3.1'

4、实现了多选(可以随便控制图片选择的数量)、单选、隐藏拍照、删除、预览等功能;
5、已对android6.0读取和写入sd权限做了适配,android7.0访问相机权限做了适配;

效果如下:
图片压缩效果:

拍照的原图(大小是2.59M):

压缩的效果(75.33kb):

主要代码实现:

public class MainActivity extends AppCompatActivity {private static final int PHOTO_CAMERA = 1000;private static final int DELETE_CODE = 1002;private final int SELECT_IMAGE_REQUEST = 0x0011;private ArrayList<String> mImageList = new ArrayList<>();private ArrayList<String> mRuquestList = new ArrayList<>();@ViewById(R.id.image_list_rv)private RecyclerView imageListRv;private RequestAdapter adapter;private int maxChoice = 9;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ViewUtils.inject(this);adapter = new RequestAdapter(this, mImageList, maxChoice);imageListRv.setLayoutManager(new GridLayoutManager(MainActivity.this, 4));imageListRv.setAdapter(adapter);//设置分割线imageListRv.addItemDecoration(new DividerGridItemDecoration(MainActivity.this, R.drawable.item_dirver_02));adapter.setOnItemClickListener(new ItemClickListener() {@Overridepublic void onItemClick(Object obj, int position) {Log.e("position", "position---->" + position);if (mImageList.size() == position) {//动态申请权限PermissionHelper.with(MainActivity.this).requestPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}).requestCode(PHOTO_CAMERA).request();} else {//跳转至删除或者预览页面Intent intent = new Intent(MainActivity.this, PreViewActivity.class);Bundle bundle = new Bundle();bundle.putInt("choicePosition", position);bundle.putSerializable("choiceList", mImageList);intent.putExtras(bundle);startActivity(intent);}}});adapter.setOnDeleteClickListener(new DeleteListener() {@Overridepublic void onDeleteClick(Object obj, int position) {removeList(position);}});}/*** 删除图片** @param position*/private void removeList(int position) {mImageList.remove(position);adapter.nodfiyData(mImageList);}@PermissionSuccess(requestCode = PHOTO_CAMERA)private void toSelectImageActivity() {ImageSelector.create().multi().count(maxChoice).showCamera(true).origin(mImageList).start(this, SELECT_IMAGE_REQUEST);}/*** 图片压缩  这里放在网络请求之前做好些,放在onActivityResult里面每次图片改动都要调用* 这里没有网络请求环境就放在onActivityResult里面了*/private void compressImg() {if (mRuquestList.size() != 0) {mRuquestList.clear();}// 把选择好的图片做了一下压缩for (String path : mImageList) {// 做优化  第一个decodeFile有可能会内存移除// 一般后台会规定尺寸  800  小米 规定了宽度 720// 上传的时候可能会多张 for循环 最好用线程池 (2-3)Bitmap bitmap = ImageUtil.decodeFile(960, path);// 调用写好的native方法//压缩存储的路径String imageViewUrl = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +new File(path).getName();// 用Bitmap.compress压缩1/10ImageUtil.compressBitmap(bitmap, 75, imageViewUrl);mRuquestList.add(imageViewUrl);}adapter.nodfiyData(mImageList);Log.e("mRuquestList", "mRuquestList----->" + mRuquestList.size());}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode == RESULT_OK) {if (requestCode == SELECT_IMAGE_REQUEST && data != null) {mImageList = (ArrayList<String>) data.getSerializableExtra(SelectImageActivity.EXTRA_DEFAULT_SELECTED_LIST);adapter.nodfiyData(mImageList);}}}/*** 压缩点击事件** @param view*/public void tvCompress(View view) {compressImageView();}/*** 使用鲁班压缩图片* 在子线程中开启图片压缩*/private void compressImageView() {new Thread(new Runnable() {@Overridepublic void run() {if (mRuquestList.size() != 0) {mRuquestList.clear();}for (String s : mImageList) {if (s == null) {s = "";}File file = new File(s);Luban.with(MainActivity.this).load(file)//传入要压缩的图片   这里采用的是单张压缩  也可以采用多张压缩.ignoreBy(100)   // 忽略不压缩图片的大小  如果原图片小于100kb不会进行压缩
//                    .putGear(Luban.Builder.)//设定压缩档次,默认三挡.setCompressListener(new OnCompressListener() { //设置回调@Overridepublic void onStart() {// TODO 压缩开始前调用,可以在方法内启动 loading UI}@Overridepublic void onSuccess(File file) {// TODO 压缩成功后调用,返回压缩后的图片文件String absolutePath = file.getAbsolutePath();mRuquestList.add(absolutePath);}@Overridepublic void onError(Throwable e) {// TODO 当压缩过程出现问题时调用}}).launch();    //启动压缩}}}).start();}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);PermissionHelper.requestPermissionsResult(this, requestCode, permissions, grantResults);}
}

MainActivity类中主要是读取和写入sd卡权限的申请、选择图片的入口函数、选择图片后的展示、图片删除、图片预览入口、图片压缩等。

public class RequestAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {private ArrayList<String> mRequestList;private int mMaxNumber;private Context mContext;public  RequestAdapter(Context context,ArrayList<String> requestList,int maxNumber){this.mContext=context;this.mMaxNumber=maxNumber;this.mRequestList = new ArrayList<String>();if(mRequestList!=null){this.mRequestList.addAll(requestList);}}public void nodfiyData(List<String> list){if(list!=null){this.mRequestList.clear();this.mRequestList.addAll(list);}notifyDataSetChanged();}@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.request_chooser_item, parent, false);return new Holder(view);}@Overridepublic void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {Holder holder = (Holder) viewHolder;if(position==mRequestList.size()){holder.ivDelete.setVisibility(View.GONE);int resourceId = R.drawable.icon_addpic_unfocused;//显示图片 利用Glide centerCrop()Glide.with(mContext).load(resourceId).centerCrop().into(holder.image);if(position==mMaxNumber){holder.image.setVisibility(View.GONE);}}else{holder.ivDelete.setVisibility(View.VISIBLE);//显示图片 利用Glide centerCrop()Glide.with(mContext).load(mRequestList.get(position)).centerCrop().into(holder.image);}//条目点击事件if(mItemClickListener!=null){holder.itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if(position==mMaxNumber){return;}if(mRequestList.size()==position){mItemClickListener.onItemClick("",position);}else {mItemClickListener.onItemClick(mRequestList.get(position), position);}}});}if(mItemDeleteListener!=null){holder.ivDelete.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {mItemDeleteListener.onDeleteClick(mRequestList.get(position), position);}});}}@Overridepublic int getItemCount() {return mRequestList.size()+1;}class Holder extends RecyclerView.ViewHolder{SquareImageView image;ImageView ivDelete;public Holder(View itemView) {super(itemView);image = (SquareImageView) itemView.findViewById(R.id.image_show);ivDelete= (ImageView) itemView.findViewById(R.id.iv_delete);}}//使用接口回调点击事件private ItemClickListener mItemClickListener;public void setOnItemClickListener(ItemClickListener itemClickListener){this.mItemClickListener=itemClickListener;}//使用接口回调点击事件private DeleteListener mItemDeleteListener;public void setOnDeleteClickListener(DeleteListener itemDeleteListener){this.mItemDeleteListener=itemDeleteListener;}
}

RequestAdapter是MainActivity类中RecyclerView的列表适配器,主要是根据position和选择图片的数量来显示图片和“+”选择更多、删除图片、图片点击的一些回调。

public class SelectImageActivity extends AppCompatActivity implements View.OnClickListener{//相机public static final String EXTRA_SHOW_CAMERA = "EXTRA_SHOW_CAMERA";//选择张数public static final String EXTRA_SELECT_COUNT = "EXTRA_SELECT_COUNT";//原始的图片路径public static final String EXTRA_DEFAULT_SELECTED_LIST = "EXTRA_DEFAULT_SELECTED_LIST";//选择的模式public static final String EXTRA_SELECT_MODE = "EXTRA_SELECT_MODE";//返回选择图片的列表public static final String EXTRA_RESULT = "EXTRA_RESULT";//多选public static final int MODE_MULTI = 0x0011;//单选public static final int MODE_SINGLE = 0x0012;private static final int LOADER_TYPE = 0x0021;private static final int REQUEST_CAMERA = 0x0022;private static final int PHOTO_CAMERA = 1002;private static final int PREVIEW_CODE = 1003;//单选或多选private int mMode = MODE_MULTI;//选择图片的张数private int mMaxCount = 9;//是否显示拍照按钮private boolean mShowCamera = true;//选择图片的listprivate ArrayList<String> mResultList;@ViewById(R.id.btn_back)private ImageView btnBack;@ViewById(R.id.image_list_rv)private RecyclerView imageListRv;//预览@ViewById(R.id.select_preview)private TextView selectPreview;@ViewById(R.id.select_num)private TextView selectNum;@ViewById(R.id.select_finshi)private TextView selectFinshi;private File mTempFile;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_select_image);ViewUtils.inject(this);initData();}/*** 初始化本地数据*/private void initImageList() {//获取本地图片  耗时操作getLoaderManager().initLoader(LOADER_TYPE, null, mLoaderCallBack);}private LoaderManager.LoaderCallbacks<Cursor> mLoaderCallBack = new LoaderManager.LoaderCallbacks<Cursor>() {private final String[] IMAGE_PROJECTION = {MediaStore.Images.Media.DATA,MediaStore.Images.Media.DISPLAY_NAME,MediaStore.Images.Media.DATE_ADDED,MediaStore.Images.Media.MIME_TYPE,MediaStore.Images.Media.SIZE,MediaStore.Images.Media._ID,};@Overridepublic Loader<Cursor> onCreateLoader(int id, Bundle args) {CursorLoader cursorLoader = new CursorLoader(SelectImageActivity.this,MediaStore.Images.Media.EXTERNAL_CONTENT_URI,IMAGE_PROJECTION, IMAGE_PROJECTION[4] + ">0 AND " + IMAGE_PROJECTION[3] + "=? OR "+ IMAGE_PROJECTION[3] + "=? ",new String[]{"image/jpeg", "image/png"},IMAGE_PROJECTION[2] + " DESC");return cursorLoader;}@Overridepublic void onLoadFinished(Loader<Cursor> loader, Cursor data) {//如果有数据变化if (data != null && data.getCount() > 0) {ArrayList<String> images = new ArrayList<>();//如果需要显示拍照就添加一条空数据if (mShowCamera) {//封装数据对象
//                    ImageEntity photoImage = new ImageEntity("", "", 0);images.add("");}//不断遍历循环while (data.moveToNext()) {String path = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));
//                    String name = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));
//                    long dateTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));
//                    Log.e("TAG", path + " " + name + " " + dateTime);
//                    //判断文件是否存在
//                    if (!pathExist(path)) {//                        continue;
//                    }
//                    Log.e("TAG", path + " " + name + " " + dateTime);//封装数据对象
//                    ImageEntity image = new ImageEntity(path, name, dateTime);images.add(path);}//显示列表数据showListData(images);}}/*** 判断文件是否存在** @param path* @return*/private boolean pathExist(String path) {if (!TextUtils.isEmpty(path)) {return new File(path).exists();}return false;}@Overridepublic void onLoaderReset(Loader<Cursor> loader) {}};/*** 显示列表数据** @param images*/private void showListData(ArrayList<String> images) {SelectImageAdapter adapter = new SelectImageAdapter(SelectImageActivity.this, images, mResultList,mMaxCount, R.layout.media_chooser_item);imageListRv.setLayoutManager(new GridLayoutManager(SelectImageActivity.this, 4));imageListRv.setAdapter(adapter);//设置分割线imageListRv.addItemDecoration(new DividerGridItemDecoration(SelectImageActivity.this,R.drawable.item_dirver_01));adapter.setOnSelectImageListener(new SelectImageListener() {@Overridepublic void select(int number) {exchangViewShow(number);}});//拍照回调adapter.setTakePhotoListener(new TakePhotoListener() {@Overridepublic void takePhoto() {//动态申请权限PermissionHelper.with(SelectImageActivity.this).requestPermission(new String[]{Manifest.permission.CAMERA}).requestCode(PHOTO_CAMERA).request();}});}/*** 拍照这里要做Android6.0以下 Android6.0和Android7.0以上的适配*/@PermissionSuccess(requestCode = PHOTO_CAMERA)private void takePhoto(){mTempFile=new File(getInnerSDCardPath(), "imagephoto" + SystemClock.currentThreadTimeMillis() + ".jpg");if (!mTempFile.getParentFile().exists()){mTempFile.getParentFile().mkdirs();}if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){//Android7.0 com.picchoice替换成自己的包名Uri imageUri = FileProvider.getUriForFile(SelectImageActivity.this, "com.picchoice.fileprovider", mTempFile);//通过FileProvider创建一个content类型的UriIntent intent = new Intent();intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加这一句表示对目标应用临时授权该Uri所代表的文件intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//将拍取的照片保存到指定URIstartActivityForResult(intent,REQUEST_CAMERA);}else {Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempFile));startActivityForResult(intent, REQUEST_CAMERA);}
//        File file=new File(Environment.getExternalStorageDirectory(), "/temp/"+System.currentTimeMillis() + ".jpg");}/*** 获取内置SD卡路径* @return*/public String getInnerSDCardPath() {return Environment.getExternalStorageDirectory().getPath();}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);PermissionHelper.requestPermissionsResult(this,requestCode,permissions,grantResults);}@Click({R.id.btn_back,R.id.select_finshi})private void Click(View view) {switch (view.getId()) {case R.id.btn_back:finish();break;case R.id.select_finshi://确定Intent intent=new Intent();Bundle bundle=new Bundle();bundle.putSerializable(SelectImageActivity.EXTRA_DEFAULT_SELECTED_LIST,mResultList);intent.putExtras(bundle);setResult(RESULT_OK,intent);finish();break;}}/*** 获取传递过来的参数*/private void initData() {Intent intent = getIntent();mMode = intent.getIntExtra(EXTRA_SELECT_MODE, mMode);mMaxCount = intent.getIntExtra(EXTRA_SELECT_COUNT, mMaxCount);mShowCamera = intent.getBooleanExtra(EXTRA_SHOW_CAMERA, mShowCamera);mResultList = (ArrayList<String>) intent.getSerializableExtra(EXTRA_DEFAULT_SELECTED_LIST);if (mResultList == null) {mResultList = new ArrayList<>();}//初始化本地数据initImageList();//改变显示exchangViewShow(mResultList.size());}/*** 改变显示*/private void exchangViewShow(int numder) {if (numder> 0) {selectPreview.setTextColor(Color.parseColor("#FF4081"));selectFinshi.setTextColor(Color.parseColor("#FF4081"));selectPreview.setEnabled(true);selectPreview.setOnClickListener(this);} else {selectPreview.setTextColor(Color.parseColor("#ffffff"));selectFinshi.setTextColor(Color.parseColor("#ffffff"));selectPreview.setEnabled(false);selectPreview.setOnClickListener(null);}selectNum.setText(numder + "/" + mMaxCount);}@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.select_preview://预览//跳转至删除或者预览页面Intent intent=new Intent(SelectImageActivity.this,PreViewActivity.class);Bundle bundle=new Bundle();bundle.putInt("choicePosition",0);bundle.putSerializable("choiceList",mResultList);intent.putExtras(bundle);startActivity(intent);break;}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);//第一个要把图片添加到集合//调用Click方法//通知系统本地有图片改变了  下次进来可以找到这张图片if(resultCode==RESULT_OK){if(requestCode==REQUEST_CAMERA){sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(mTempFile)));mResultList.add(mTempFile.getAbsolutePath());setResult();}}}/*** 设置返回结果*/private void setResult(){Intent intent=new Intent();Bundle bundle=new Bundle();
//        bundle.putSerializable(EXTRA_RESULT,mResultList);//EXTRA_DEFAULT_SELECTED_LISTbundle.putSerializable(EXTRA_DEFAULT_SELECTED_LIST,mResultList);intent.putExtras(bundle);setResult(RESULT_OK,intent);//关闭当前页面finish();}
}

SelectImageActivity类主要是获取系统sd里面的图片并展示、android7.0访问相机适配、相机拍照后图片的刷新和保存等。

public class SelectImageAdapter extends RecyclerCommonAdapter<String> {private Context mContext;private List<String> imageList;private int mMaxCount;public SelectImageAdapter(Context context, List<String> data, List<String> choice, int maxCount, int layoutId) {super(context, data, layoutId);this.mContext = context;this.imageList = choice;this.mMaxCount = maxCount;}@Overrideprotected void bindData(ViewHolder holder, final String mPath, final int position) {if (TextUtils.isEmpty(mPath)) {//显示拍照holder.setViewVisibility(R.id.camear_ll, View.VISIBLE);holder.setViewVisibility(R.id.media_selected_indicator, View.INVISIBLE);holder.setViewVisibility(R.id.image_show, View.INVISIBLE);//拍照holder.getView(R.id.camear_ll).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//调用拍照if(takePhotoListener!=null){takePhotoListener.takePhoto();}}});} else {//显示图片holder.setViewVisibility(R.id.camear_ll, View.INVISIBLE);holder.setViewVisibility(R.id.media_selected_indicator, View.VISIBLE);holder.setViewVisibility(R.id.image_show, View.VISIBLE);SquareImageView image = holder.getView(R.id.image_show);//显示图片 利用Glide centerCrop()Glide.with(mContext).load(mPath).centerCrop().into(image);ImageView selectImageView = holder.getView(R.id.media_selected_indicator);if (imageList.contains(mPath)) {//设置勾选图片selectImageView.setSelected(true);} else {selectImageView.setSelected(false);}//给条目添加点击事件image.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//没有就加入集合if (!imageList.contains(mPath)) {if (imageList.size() >= mMaxCount) {Toast.makeText(mContext, "最多只能选择" + mMaxCount + "张图片", Toast.LENGTH_LONG).show();return;}imageList.add(mPath);} else {//有就移除imageList.remove(mPath);}//刷新数据notifyDataSetChanged();//通知显示布局if (selectImageListener != null) {selectImageListener.select(imageList.size());}}});}}private SelectImageListener selectImageListener;public void setOnSelectImageListener(SelectImageListener listener) {this.selectImageListener = listener;}private TakePhotoListener takePhotoListener;public void setTakePhotoListener(TakePhotoListener listener) {this.takePhotoListener = listener;}
}

SelectImageAdapter类是SelectImageActivity类中RecyclerView的适配器,展示系统sd获取的图片、控制图片选择的数量等。

public class PreViewActivity extends AppCompatActivity implements View.OnClickListener {@ViewById(R.id.btn_back)private ImageView btnBack;@ViewById(R.id.viewpager)private ViewPager viewpager;private List<String> choiceList;private DeleteAdapter adapter;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_delete);ViewUtils.inject(this);choiceList = (List<String>) getIntent().getSerializableExtra("choiceList");if(choiceList==null){choiceList=new ArrayList<>();}adapter=new DeleteAdapter(getSupportFragmentManager());viewpager.setAdapter(adapter);btnBack.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.btn_back:finish();break;}}class DeleteAdapter extends FragmentPagerAdapter{public DeleteAdapter(FragmentManager fm) {super(fm);}@Overridepublic Fragment getItem(int position) {return ImageViewFragment.newInstance(choiceList.get(position));}@Overridepublic int getCount() {return choiceList.size();}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {super.destroyItem(container, position, object);}}
}
public class ImageViewFragment extends Fragment{public static ImageViewFragment newInstance(String item){ImageViewFragment fragment=new ImageViewFragment();Bundle bundle=new Bundle();bundle.putString("url",item);fragment.setArguments(bundle);return fragment;}@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_imageview, container, false);ImageView image = (ImageView) view.findViewById(R.id.image);Bundle bundle = getArguments();String url = bundle.getString("url");if(url==null){url="";}int screenWidth = getW(getActivity());Bitmap diskBitmap = getDiskBitmap(url);if(diskBitmap!=null){//获取Bitmap的宽高int width = diskBitmap.getWidth();int height = diskBitmap.getHeight();//根据Bitmap的宽高和屏幕的宽高重新设置imageview显示的大小RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) image.getLayoutParams();layoutParams.width=screenWidth;layoutParams.height=screenWidth*height/width;image.setLayoutParams(layoutParams);}//显示图片 利用Glide centerCrop()Glide.with(this).load(url).centerCrop().into(image);return view;}/*** 根据url获取一个bitmap对象* @param pathString  图片路径* @return  返回对应的Bitmap对象*/private Bitmap getDiskBitmap(String pathString) {Bitmap bitmap = null;try{File file = new File(pathString);if(file.exists()) {bitmap = BitmapFactory.decodeFile(pathString);}} catch (Exception e) {e.printStackTrace();}return bitmap;}/** 获取屏幕的宽度*/private int getW(Context context){DisplayMetrics dm = new DisplayMetrics();WindowManager windowMgr = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);windowMgr.getDefaultDisplay().getMetrics(dm);return dm.widthPixels;}
}

PreViewActivity类和ImageViewFragment类是图片预览,这里的图片预览效果做的不是很好,可以根据自己的需要进行修改。

public class ImageSelector {//选择图片张数private int mMaxCount = 9;//选择图片的模式private int mMode = SelectImageActivity.MODE_MULTI;//是否显示拍照的相机private boolean mShowCamera = true;//原始的图片private ArrayList<String> mOriginData;private ImageSelector() {}public static ImageSelector create() {return new ImageSelector();}/*** 单选模式** @return*/public ImageSelector single() {mMode = SelectImageActivity.MODE_SINGLE;return this;}/*** 多选模式** @return*/public ImageSelector multi() {mMode = SelectImageActivity.MODE_MULTI;return this;}/*** 设置可以选择的图片张数** @param count* @return*/public ImageSelector count(int count) {mMaxCount = count;return this;}/*** 是否显示相机** @param showCamera* @return*/public ImageSelector showCamera(boolean showCamera) {mShowCamera = showCamera;return this;}/*** 选择好的图片** @param originList* @return*/public ImageSelector origin(ArrayList<String> originList) {this.mOriginData = originList;return this;}/*** 启动requestCode** @param activity* @param requestCode*/public void start(Activity activity, int requestCode) {Intent intent = new Intent(activity, SelectImageActivity.class);addParmasByIntent(intent);activity.startActivityForResult(intent, requestCode);}/*** 启动requestCode** @param fragment* @param requestCode*/public void start(Fragment fragment, int requestCode) {Intent intent = new Intent(fragment.getContext(), SelectImageActivity.class);addParmasByIntent(intent);fragment.startActivityForResult(intent, requestCode);}/*** 设置参数** @param intent*/private void addParmasByIntent(Intent intent) {Bundle bundle = new Bundle();bundle.putInt(SelectImageActivity.EXTRA_SELECT_COUNT, mMaxCount);bundle.putInt(SelectImageActivity.EXTRA_SELECT_MODE, mMode);bundle.putBoolean(SelectImageActivity.EXTRA_SHOW_CAMERA, mShowCamera);if (mOriginData != null && mMode == SelectImageActivity.MODE_MULTI) {bundle.putSerializable(SelectImageActivity.EXTRA_DEFAULT_SELECTED_LIST, mOriginData);}intent.putExtras(bundle);}
}

ImageSelector类是一个工具类,里面提供了设置图片多选还是单选,选择图片的数量,是否显示相机等。

上面这些就是实现的主要代码,下面会提供源码,可以根据自己的需要对源码进行修改。

源码地址:
http://pan.baidu.com/s/1bp50kLT

鲁班图片压缩实现仿微信九宫格选择图片效果相关推荐

  1. Android显示九宫图(自定义圆角,仿微信九宫格图)

    详细解析Android显示九宫图(自定义圆角,仿微信九宫格图) 这是一个自定义九宫格图片框架,里面有设置圆角大小,还有当图片一张的时候控件自定义的大小,图片的间隔,四张图片的时候图片自定义为两行两列等 ...

  2. php 合成微信头像,PHP 图片合成、仿微信群头像的方法示例

    搜索热词 本文实例讲述了PHP 图片合成.仿微信群头像的方法.分享给大家供大家参考,具体如下: 参考文章: 作者:凯歌~,PHP图片合成方法(多张图片合成一张)https://www.jb51.net ...

  3. 如何把jpg图片压缩变小?jpg格式图片压缩方法

    Jpg图片压缩变小怎么操作?图片在上传到网站平台时,会遇到图片过大无法上传的情况,例如需要将jpg压缩到30K.100K.200K.1M以下等要求时该如何处理呢?这时候就需要使用jpg压缩功能,缩小j ...

  4. android 底部tab效果,Android 仿微信底部渐变Tab效果

    先来看一下效果图 除了第三个的发现Tab有所差别外,其他的基本还原了微信的底部Tab渐变效果 每个Tab都是一个自定义View,根据ImageView的tint属性来实现颜色渐变效果,tint属性的使 ...

  5. android bmob 朋友圈,仿微信朋友圈视频效果 – MVideo

    MVideo 仿微信朋友圈视频效果,可以拖拽及缩放,视频查看,基于ijkplayer. Demo 入门 Step 1:在buil文件中添加JitPack仓库: allprojects { reposi ...

  6. pictureselector 压缩_GitHub - HobertHe/PictureSelector-1: 仿微信、QQ图片选择器(自带图片压缩,裁剪)...

    声明 本项目Fork自PictureSelector,在原项目加入自己的UI和压缩裁剪,本项目仅供自己使用,不保证维护.大家有需求可以移步原项目,以下内容为原项目说明. PictureSelector ...

  7. 仿微信查看系统图片缩略图选择多张图片

    最近做的项目有用到查看系统图片并选择多张图片的功能,网上搜索了一些源码运行起来,拖动一下缩略图列表就卡住了,都是没有考虑到OOM的原因.结合网上的一些LRUCACHE和ASYNCTASK资料,自己写了 ...

  8. 使用南尘的ImagePicker实现仿微信的相册图片选择以及拍照上传

    在记录之前先放上原作的GitHub项目地址:ImagePicker 南尘的框架写得相当不错,我们可以在我们的项目中添加依赖直接使用,但是我在使用的时候发现了一个小bug,就在图片预览的界面选择了图片后 ...

  9. iOS 仿微信相册选择照片imagePicker(Swift) 序号 预览缩略图

    序:微信最新版,选择照片控件细节有所改变,一般有轮子我是不会从新造的 .产品要求一模一样,无奈重新写.调查了一下,GitHub大部分仿微信imagePicker还是基于TZImagePicker,sw ...

最新文章

  1. java的知识点33——死锁及解决方案
  2. ELK日志分析平台搭建全过程(自己做了测试,测试不完整因为原文章都是图片)
  3. MySQL事务处理与事务隔离(锁机制)
  4. 如何学习streamdecoder类_2019年终巨献:一份拿下了阿里、网易、滴滴等大厂offer的学习笔记...
  5. 波拉契尔数列 C++
  6. Jetson AGX Xavier配置PyTorch与TorchVision流程
  7. 【文末福利】聊天机器人的几种主要架构实现
  8. asp.net本质论学习笔记第一章
  9. iMindMap2020 中文旗舰免费版
  10. 北京房租大涨?Python帮你揭穿真相
  11. python multiprocessing dummy Pool 使用
  12. ROS 多机器人导航salm中的问题
  13. java wed高德地图开发_java接入高德地图常用WEB API
  14. arcmap提取dem高程_利用ArcGIS高效率提取DEM高程点至CAD
  15. ROS wiki系列|Documentation-ROS部分讲解
  16. 使用普中科技STM32发ZEB6的准备工作:
  17. SringBoot集成阿里云OSS上传文件
  18. Anubis可视化绘图详细教程(从安装到出图)
  19. Opencv2.4.9源码分析——Stitching(一)
  20. 加密保护软件 WinLicense常见问题整理大全(二):如何为应用程序创建试用期...

热门文章

  1. SystemUI原生信号塔替换为五格信号塔
  2. 云端系统服务器是什么,云端服务器是什么-云端服务器介绍
  3. 微信、Uber、阴谋论和口袋罪
  4. SQL字符串首字母大写
  5. 【Windows Server 2019】路由服务的配置和管理
  6. Theorem、Proposition、Lemma的区别
  7. python爬app西瓜视频_Python爬虫工程师面试题,采集头条西瓜视频
  8. 2021.02.02刷题总结
  9. 管理员同志,回收站博文希望得到恢复,万分感谢
  10. 【GD32F310开发板试用】Contiki-NG在GD32F310的移植