安卓开发 第八篇 我的安卓应用架构设计-----图片选择以及剪裁
2016-05-17 21:30
846 查看
Android开发中遇到要从相册选择图片时,大多数人都会选择调用Android自带的相册,毕竟这样可以节约时间,又不用自己去处理图片的问题,不过这样也会产生一些问题,有些系统自带的相册真的是丑到没朋友,有时调用系统相册时不时的还可能发生崩溃问题。而我的安卓架构中选择了自定义相册的功能,其效果是仿照QQ的图片选择样式,通过dialog展现出来的,还自定义了图片的剪裁,使用了CropImageView 实现了多种剪裁效果。
图片选择的直接辅助类:
图片选择dialog:
图片的封装对象:
图片显示适配器:
图片显示的Viewholder:
图片文件夹页面适配器:
图片文件夹页面ViewHolder:
选中的图片预览适配器:
剪裁图片dialog:
下面来看看效果图:
1.图片显示页面
2.图片文件夹显示页面
3.选中的图片的预览页面
4.图片剪裁页面
好了,就到这里吧!
如果有更深的理解,本文将会修改;
如果有错误的地方,欢迎指正;
如果你有更好的理解,欢迎交流。
本文为原创文章,版权归博主所有,转载请注明出处。
更多资料:
我的github地址以及使用demo: https://github.com/naivor/naivorapp
图片选择的直接辅助类:
/** * 图片选择辅助类 * Created by tianlai on 16-4-12. */ public class PickImageHelper { private static final String TAG = "PickImageHelper"; private PickType pickType; private Type type; private Activity activtiy; private PicKImageDialog picKImageDialog; private CropImageDialog cropImageDialog; private String cachePath; private OnImageOutputListener onImageOutputListener; @Inject public PickImageHelper(PicKImageDialog picKImageDialog) { this.picKImageDialog = picKImageDialog; } /** * 初始化 * * @param activtiy */ public void initPickImageHelper(final Activity activtiy) { this.activtiy = activtiy; picKImageDialog.setCancelable(false); cachePath = SDCardUtil.getRootPath() + activtiy.getString(R.string.cache_path); picKImageDialog.setPickImageListener(new PicKImageDialog.PickImageListener() { @Override public void onPickFinish(List<String> paths) { LogUtil.i(TAG, "已选的图片---" + paths.toString()); picKImageDialog.dismiss(); if (onImageOutputListener != null) { if (pickType == PickType.HEADICON) { onImageOutputListener.outputHeadImage(paths.get(0)); } else if (pickType == PickType.MULTIIMAGE) { onImageOutputListener.outputPickedImages(paths); } } } @Override public void toCropImage(String path) { LogUtil.i(TAG, "要剪裁的图片---" + path.toString()); picKImageDialog.dismiss(); initCropImageDialog(Uri.parse("file://" + path)); } }); } /** * 初始化剪裁的对话框 * * @param path * @param activtiy */ public void onCaptureResult(final String path, Activity activtiy) { this.activtiy = activtiy; new AlertDialog.Builder(activtiy) .setTitle("提示") .setMessage("是否剪裁图片?") .setNegativeButton("否", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dealCropResult(path); } }).setPositiveButton("是", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { initCropImageDialog(Uri.parse("file://" + path)); } }).create().show(); } /** * 初始化剪裁的对话框 * * @param uri */ private void initCropImageDialog(Uri uri) { cropImageDialog = new CropImageDialog(activtiy); cropImageDialog.setCancelable(false); cropImageDialog.setCachePath(cachePath); cropImageDialog.setCropImageListener(new CropImageDialog.CropImageListener() { @Override public void onPickImage() { LogUtil.i(TAG, "---重新选择图片---"); cropImageDialog.dismiss(); picKImageDialog.setMaxNum(1); picKImageDialog.show(); } @Override public void onCropSucceed(String path) { LogUtil.i(TAG, "剪裁后的图片路径---" + path); cropImageDialog.dismiss(); dealCropResult(path); } }); cropImageDialog.show(uri, true); } /** * 剪裁结果的处理 * * @param path */ private void dealCropResult(String path) { if (onImageOutputListener != null) { if (pickType == PickType.HEADICON) { onImageOutputListener.outputHeadImage(path); } else if (pickType == PickType.MULTIIMAGE) { List<String> paths = new ArrayList<String>(); paths.add(path); onImageOutputListener.outputPickedImages(paths); } } } /** * 选择头像 */ public void pickHeadImage() { this.pickType = PickType.HEADICON; picKImageDialog.setMaxNum(1); showPickOrCapture(); } /** * 选择图片 */ public void pickImages(int maxNum) { this.pickType = PickType.MULTIIMAGE; picKImageDialog.setMaxNum(maxNum); showPickOrCapture(); } /** * 从相册选择或者拍照 */ private void showPickOrCapture() { new AlertDialog.Builder(activtiy) .setItems(R.array.pick_image, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case 0: //拍照 type = Type.CAPTURE; if (onImageOutputListener != null) { onImageOutputListener.takePhoto(); } break; case 1: //图库 type = Type.PICKIMAGE; picKImageDialog.show(); break; case 2: //取消 break; } } }).create().show(); } public OnImageOutputListener getOnImageOutputListener() { return onImageOutputListener; } public void setOnImageOutputListener(OnImageOutputListener onImageOutputListener) { this.onImageOutputListener = onImageOutputListener; } public PickType getPickType() { return pickType; } public void setPickType(PickType pickType) { this.pickType = pickType; } //选择类型,单张头像还是多张 public enum PickType { HEADICON, MULTIIMAGE } //选择类型,拍照还是图库 public enum Type { CAPTURE, PICKIMAGE } public static interface OnImageOutputListener { public void takePhoto(); /** * 输出头像 * * @param path */ public void outputHeadImage(String path); /** * 输出选择的图片 * * @param paths */ public void outputPickedImages(List<String> paths); } }
图片选择dialog:
/** * 图片选择弹出对话框 * <p/> * Created by tianlai on 16-4-12. */ public class PicKImageDialog extends Dialog { private Context context; private LayoutInflater inflater; private ImageView topHome; private TextView topTitle; private TextView topCenter; private TextView topAction; private GridView gvPictures; private ViewPager vpPictures; private ViewSwitcher vsPictures; private TextView bottomPreview; private TextView bottomCrop; private TextView bottomSure; private ListView lvPaths; private ViewSwitcher vsLayout; private List<ImageCollection> imagePaths; private Set<String> parentPaths; private ParentPathsAdapter parentPathsAdapter; private PicturesAdapter picturesAdapter; private PicturesPagerAdapter picturesPagerAdapter; private int maxNum; private PickImageListener pickImageListener; public PicKImageDialog(Context context) { super(context, R.style.AppTheme_Dialog); init(context); } public PicKImageDialog(Context context, int theme) { super(context, theme); init(context); } private void init(Context context) { this.context = context; inflater = LayoutInflater.from(context); imagePaths = new ArrayList<>(); parentPaths = new HashSet<>(); picturesAdapter = new PicturesAdapter(context, inflater); parentPathsAdapter = new ParentPathsAdapter(context, inflater); scanPictures(context); } /** * 扫描手机中的图片 * * @param context */ private void scanPictures(final Context context) { new Thread(new Runnable() { @Override public void run() { Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; ContentResolver mContentResolver = context.getContentResolver(); String[] projections = { MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA, MediaStore.Images.Media.SIZE }; String selection = MediaStore.Images.Media.MIME_TYPE + "=?"; String[] selectionArgs = {"image/jpeg"}; String sortOrder = MediaStore.Images.Media.DATE_MODIFIED + " desc"; // 只查询jpeg和png的图片 Cursor mCursor = mContentResolver.query(mImageUri, projections, selection, selectionArgs, sortOrder); if (mCursor != null) { ImageCollection imageCollection; while (mCursor.moveToNext()) { imageCollection = new ImageCollection(); // 获取图片的uri路径 String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA)); if (path != null) { File file = new File(path); if (file != null && file.exists()) { // 获取该图片的父路径名 File parentFile = file.getParentFile(); String parentPath = parentFile.getAbsolutePath(); if (parentPaths.contains(parentPath)) { continue; } else { parentPaths.add(parentPath); imageCollection.setRootPath(parentPath); imageCollection.setRootName(parentFile.getName()); File[] files = parentFile.listFiles(); for (File f : files) { String fName = f.getName(); if (fName.endsWith(".jpg") || fName.endsWith(".png")) { imageCollection.addPicture(f.getAbsolutePath()); } } imagePaths.add(imageCollection); } } } } mCursor.close(); } } }).start(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.dialog_pickimage); initView(); } /** * 初始化view */ private void initView() { topHome = (ImageView) find(R.id.top_home); topTitle = (TextView) find(R.id.top_title); topCenter = (TextView) find(R.id.top_center); topAction = (TextView) find(R.id.top_action); gvPictures = (GridView) find(R.id.gv_pictures); vpPictures = (ViewPager) find(R.id.vp_pictures); vsPictures = (ViewSwitcher) find(R.id.vs_pictures); bottomPreview = (TextView) find(R.id.bottom_title); bottomCrop = (TextView) find(R.id.bottom_center); bottomSure = (TextView) find(R.id.bottom_action); lvPaths = (ListView) find(R.id.lv_paths); vsLayout = (ViewSwitcher) find(R.id.vs_layout); setListeners(); gvPictures.setAdapter(picturesAdapter); lvPaths.setAdapter(parentPathsAdapter); parentPathsAdapter.setItems(imagePaths); List<String> items = transToFullPath(imagePaths); parentPathsAdapter.addItem(0, new ImageCollection(new HashSet<String>(items), "所有图片")); picturesAdapter.setItems(items); } /** * 设置监听器 */ private void setListeners() { //返回 topHome.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); //取消 topAction.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismiss(); } }); //预览 bottomPreview.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showPreviews(new ArrayList<String>(picturesAdapter.getSelectedPictures())); } }); //剪裁 bottomCrop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (pickImageListener != null) { pickImageListener.toCropImage(picturesAdapter.getCorpPicturePath()); picturesAdapter.clearSelectedPictures(); } } }); //确定 bottomSure.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (pickImageListener != null) { pickImageListener.onPickFinish(new ArrayList<String>(picturesAdapter.getSelectedPictures())); picturesAdapter.clearSelectedPictures(); } } }); picturesAdapter.setOnPictrueSelectListener(new PicturesAdapter.OnPictrueSelectListener() { @Override public void selectedSingleItem(boolean selectedSingleItem) { if (selectedSingleItem) { bottomCrop.setEnabled(true); } else { bottomCrop.setEnabled(false); } } @Override public void hasItemSelected(boolean hasItemSelected, int selectNum) { if (hasItemSelected) { bottomPreview.setEnabled(true); bottomSure.setEnabled(true); bottomSure.setText("确定(" + selectNum + "/" + maxNum + ")"); } else { bottomPreview.setEnabled(false); bottomSure.setEnabled(false); bottomSure.setText("确定"); } } }); //点击预览单张图片 gvPictures.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { List<String> paths = new ArrayList<String>(); String item = picturesAdapter.getItem(position); paths.add(item); showPreviews(paths); //判断是否可以剪裁 if (bottomCrop.isEnabled() && !picturesAdapter.isSamePicture(item)) { bottomCrop.setEnabled(false); } } }); //点击查看某个目录下面的图片 lvPaths.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ImageCollection imageCollection = parentPathsAdapter.getItem(position); picturesAdapter.setItems(new ArrayList<String>(imageCollection.getPictures())); topCenter.setText(imageCollection.getRootName()); vsLayout.showNext(); } }); } private void showPreviews(List<String> paths) { PicturesPagerAdapter adapter = new PicturesPagerAdapter(paths, inflater); vpPictures.setAdapter(adapter); vsPictures.showNext(); //隐藏预览按钮 bottomPreview.setVisibility(View.GONE); } /** * @param imagePaths * @return */ private List<String> transToFullPath(List<ImageCollection> imagePaths) { Observable<String> observable = null; if (imagePaths != null) { int size = imagePaths.size(); if (size > 0) { Observable<String> observableMerge; for (int i = 0; i < size; i++) { Set<String> pictures = imagePaths.get(i).getPictures(); if (pictures == null) { continue; } else { observableMerge = Observable.from(pictures); if (observable == null) { observable = observableMerge; } else { observable = Observable.merge(observable, observableMerge); } } } return observable.distinct().toList().toBlocking().single(); } } return Collections.emptyList(); } /** * 初始化dialog * * @param maxNum * @param pickImageListener */ public void initPickDialog(int maxNum, PickImageListener pickImageListener) { this.maxNum = maxNum; this.pickImageListener = pickImageListener; } @Override public void show() { picturesAdapter.setMaxNum(maxNum); super.show(); setDialogWindowAttr(); } /** * 调整dialog的大小 */ public void setDialogWindowAttr() { WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.gravity = Gravity.CENTER; lp.width = WindowManager.LayoutParams.MATCH_PARENT;//宽高可设置具体大小 lp.height = WindowManager.LayoutParams.MATCH_PARENT; getWindow().setAttributes(lp); } @Override public void onBackPressed() { super.onBackPressed(); if (lvPaths.isShown()) { dismiss(); } else if (vpPictures.isShown()) { vsPictures.showNext(); //显示预览按钮 bottomPreview.setVisibility(View.VISIBLE); //判断是否可以剪裁 if (!bottomCrop.isEnabled() && picturesAdapter.isSelectedSingleItem()) { bottomCrop.setEnabled(true); } } else { vsLayout.showNext(); } } public int getMaxNum() { return maxNum; } public void setMaxNum(int maxNum) { this.maxNum = maxNum; } public PickImageListener getPickImageListener() { return pickImageListener; } public void setPickImageListener(PickImageListener pickImageListener) { this.pickImageListener = pickImageListener; } /** * 获取view * * @param viewId * @return */ public View find(int viewId) { return findViewById(viewId); } /** * 获取view * * @param viewId * @return */ public View find(View parent, int viewId) { return parent.findViewById(viewId); } public static interface PickImageListener { /** * 选择图片完成 */ public void onPickFinish(List<String> paths); /** * 剪裁图片 */ public void toCropImage(String path); } }
图片的封装对象:
/** * 封装一个目录及其目录下的图片文件的路径 * Created by tianlai on 16-4-12. */ public class ImageCollection { private String rootPath; private String rootName; private Set<String> pictures; public ImageCollection() { } public ImageCollection(Set<String> pictures, String rootName) { this.pictures = pictures; this.rootName = rootName; } public String getRootPath() { return rootPath; } public void setRootPath(String rootPath) { this.rootPath = rootPath; } public Set<String> getPictures() { return pictures; } public void setPictures(Set<String> pictures) { this.pictures = pictures; } public void addPicture(String picture){ if (pictures==null){ pictures=new HashSet<>(); } pictures.add(picture); } public void rmPicture(String picture){ if (pictures==null){ return; } pictures.remove(picture); } public String getRootName() { return rootName; } public void setRootName(String rootName) { this.rootName = rootName; } @Override public String toString() { return "ImageCollection{" + "rootPath='" + rootPath + '\'' + ", pictures=" + pictures + '}'; } }
图片显示适配器:
/** * 图片显示页面的适配器 * Created by tianlai on 16-4-12. */ public class PicturesAdapter extends BaseAbsListAdapter<String,PicturesViewHolder> { private Set<String> selectedPictures; private OnPictrueSelectListener onPictrueSelectListener; private int maxNum; public PicturesAdapter(Context context, LayoutInflater inflater) { super(context, inflater); selectedPictures=new HashSet<>(); } @Override public PicturesViewHolder onCreateViewHolder(ViewGroup parent, int viewType, LayoutInflater inflater) { return new PicturesViewHolder(inflater.inflate(R.layout.grid_item_select_image,null),this); } public Set<String> getSelectedPictures() { return selectedPictures; } public void setSelectedPictures(Set<String> selectedPictures) { this.selectedPictures = selectedPictures; } public void addSelectedPicture(String path){ selectedPictures.add(path); notifySelectedItem(); } public void removeSelectedPicture(String path){ selectedPictures.remove(path); notifySelectedItem(); } /** * 有item选中或者取消选中时的事件 */ private void notifySelectedItem() { if (onPictrueSelectListener!=null){ int size = selectedPictures.size(); onPictrueSelectListener.selectedSingleItem(size==1); onPictrueSelectListener.hasItemSelected(size >0,size); } } public boolean isSlected(String path){ Log.i("picture",selectedPictures.toString()); return selectedPictures.contains(path); } public OnPictrueSelectListener getOnPictrueSelectListener() { return onPictrueSelectListener; } public void setOnPictrueSelectListener(OnPictrueSelectListener onPictrueSelectListener) { this.onPictrueSelectListener = onPictrueSelectListener; } public int getMaxNum() { return maxNum; } public void setMaxNum(int maxNum) { this.maxNum = maxNum; } public boolean isCanSelectMore(){ return selectedPictures.size()<maxNum; } public boolean isSelectedSingleItem(){ return selectedPictures.size()==1; } public boolean isSamePicture(String path){ if (isSelectedSingleItem()){ if (new ArrayList<String>(selectedPictures).get(0).equals(path)){ return true; } } return false; } /** * 获取要剪裁的图片路径 * * @return */ public String getCorpPicturePath(){ if (selectedPictures.size()==1){ return new ArrayList<>(selectedPictures).get(0); } return null; } /** * 清空选中的图片 */ public void clearSelectedPictures(){ selectedPictures.clear(); } public static interface OnPictrueSelectListener{ public void selectedSingleItem(boolean selectedSingleItem); public void hasItemSelected(boolean hasItemSelected, int selectNum); } }
图片显示的Viewholder:
/** * 图片显示页面的适配器的ViewHolder * Created by tianlai on 16-4-12. */ public class PicturesViewHolder extends BaseViewHolder<String> implements CompoundButton .OnCheckedChangeListener { SimpleDraweeView sdvPicture; CheckBox cbSelect; private ImageRequest imageRequest; private DraweeController draweeController; public PicturesViewHolder(View convertView, BaseAbsListAdapter absListAdapter) { super(convertView, absListAdapter); sdvPicture = (SimpleDraweeView) find(R.id.sdv_picture); cbSelect = (CheckBox) find(R.id.cb_select); cbSelect.setOnCheckedChangeListener(this); } @Override public void loadDataToView(int position, String data) { super.loadDataToView(position,data); imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse("file://" + data)) .setResizeOptions(new ResizeOptions(128,128)) .setLocalThumbnailPreviewsEnabled(true) .build(); draweeController = Fresco.newDraweeControllerBuilder() .setImageRequest(imageRequest) .setOldController(sdvPicture.getController()) .build(); sdvPicture.setController(draweeController); if (((PicturesAdapter) absListAdapter).isSlected(data)) { cbSelect.setChecked(true); Log.i("picture","位置"+position+"--已选中"); }else { cbSelect.setChecked(false); Log.i("picture","位置"+position+"--未选中"); } } @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { if (((PicturesAdapter) absListAdapter).isCanSelectMore()||((PicturesAdapter) absListAdapter).isSlected(data)){ ((PicturesAdapter) absListAdapter).addSelectedPicture(data); Log.i("picture","位置"+position+"--正在点击选中"); }else { Toast.makeText(context,"最多只能选择"+((PicturesAdapter) absListAdapter).getMaxNum()+"张图片",Toast .LENGTH_SHORT).show(); buttonView.setChecked(false); } } else { ((PicturesAdapter) absListAdapter).removeSelectedPicture(data); Log.i("picture","位置"+position+"--正在取消选中"); } } }
图片文件夹页面适配器:
/** * 选择图片文件夹页面的适配器 * Created by tianlai on 16-4-12. */ public class ParentPathsAdapter extends BaseAbsListAdapter<ImageCollection,ParentPathsViewHolder> { public ParentPathsAdapter(Context context, LayoutInflater inflater) { super(context, inflater); } @Override public ParentPathsViewHolder onCreateViewHolder(ViewGroup parent, int viewType, LayoutInflater inflater) { return new ParentPathsViewHolder(inflater.inflate(R.layout.list_item_parent_paths,null),this); } }
图片文件夹页面ViewHolder:
/** * 选择图片文件夹页面的适配器的ViewHolder * Created by tianlai on 16-4-12. */ public class ParentPathsViewHolder extends BaseViewHolder<ImageCollection> { SimpleDraweeView sdvImage; TextView tvPath; public ParentPathsViewHolder(View convertView, BaseAbsListAdapter absListAdapter) { super(convertView, absListAdapter); sdvImage= (SimpleDraweeView) find(R.id.sdv_image); tvPath= (TextView) find(R.id.tv_path); } @Override public void loadDataToView(int position, ImageCollection data) { List<String> pictures = new ArrayList<>(data.getPictures()); if (pictures != null) { int size = pictures.size(); if (size > 0) { sdvImage.setImageURI(Uri.parse("file://" + pictures.get(0))); tvPath.setText(data.getRootName() + "(" + size + ")"); } } } }
选中的图片预览适配器:
/** * 浏览选中的图片的适配器(浏览页面是一个ViewPager) * Created by tianlai on 16-4-12. */ public class PicturesPagerAdapter extends PagerAdapter { private List<View> images; private List<String> picturePaths; private LayoutInflater inflater; public PicturesPagerAdapter(List<String> picturePaths, LayoutInflater inflater) { this.inflater = inflater; this.picturePaths=picturePaths; images = new ArrayList<View>(); ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup .LayoutParams.MATCH_PARENT); View view; for (String path : picturePaths) { view=inflater.inflate(R.layout.vp_item_picture,null); ((SimpleDraweeView)view.findViewById(R.id.vp_picture)).setImageURI(Uri.parse("file://"+path)); images.add(view); } } @Override public int getCount() { return images.size(); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, int position) { View view = images.get(position); container.addView(view); return view; } public List<String> getPicturePaths() { return picturePaths; } public void setPicturePaths(List<String> picturePaths) { this.picturePaths = picturePaths; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(images.get(position)); } }
剪裁图片dialog:
/** * 剪裁图片的对话框 * Created by tianlai on 16-4-13. */ public class CropImageDialog extends Dialog { private Context context; private LayoutInflater inflater; // Views /////////////////////////////////////////////////////////////////////////////////////// private CropImageView mCropView; private LinearLayout mRootLayout; private ProgressBar progressBar; private String cachePath; private String cropPath; private boolean isFromPick; private CropImageListener cropImageListener; public CropImageDialog(Context context) { super(context, R.style.AppTheme_Dialog); init(context); } public CropImageDialog(Context context, int theme) { super(context, theme); init(context); } private void init(Context context) { this.context = context; inflater = LayoutInflater.from(context); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); View contentView = inflater.inflate(R.layout.dialog_cropimage, null); setContentView(contentView); // bind Views bindViews(contentView); mCropView.setDebug(BuildConfig.DEBUG); } private void bindViews(View view) { progressBar = (ProgressBar) view.findViewById(R.id.progress); progressBar.getIndeterminateDrawable().setColorFilter(getContext().getResources().getColor(R.color.colorAccent), PorterDuff.Mode.SRC_IN); mRootLayout = (LinearLayout) view.findViewById(R.id.layout_root); mCropView = (CropImageView) view.findViewById(R.id.cropImageView); mCropView.setOutputMaxSize(300, 300); view.findViewById(R.id.top_home).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); view.findViewById(R.id.top_action).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismiss(); } }); view.findViewById(R.id.buttonDone).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showProgress(); mCropView.startCrop(createSaveUri(), mCropCallback, mSaveCallback); } }); view.findViewById(R.id.buttonFitImage).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCropView.setCropMode(CropImageView.CropMode.FIT_IMAGE); } }); view.findViewById(R.id.button1_1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCropView.setCropMode(CropImageView.CropMode.SQUARE); } }); view.findViewById(R.id.button3_4).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCropView.setCropMode(CropImageView.CropMode.RATIO_3_4); } }); view.findViewById(R.id.button4_3).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCropView.setCropMode(CropImageView.CropMode.RATIO_4_3); } }); view.findViewById(R.id.button9_16).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCropView.setCropMode(CropImageView.CropMode.RATIO_9_16); } }); view.findViewById(R.id.button16_9).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCropView.setCropMode(CropImageView.CropMode.RATIO_16_9); } }); view.findViewById(R.id.buttonFree).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCropView.setCropMode(CropImageView.CropMode.FREE); } }); view.findViewById(R.id.buttonPickImage).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (cropImageListener != null) { cropImageListener.onPickImage(); } } }); view.findViewById(R.id.buttonRotateLeft).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCropView.rotateImage(CropImageView.RotateDegrees.ROTATE_M90D); } }); view.findViewById(R.id.buttonRotateRight).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCropView.rotateImage(CropImageView.RotateDegrees.ROTATE_90D); } }); view.findViewById(R.id.buttonCustom).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCropView.setCustomRatio(7, 5); } }); view.findViewById(R.id.buttonCircle).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCropView.setCropMode(CropImageView.CropMode.CIRCLE); } }); view.findViewById(R.id.buttonShowCircleButCropAsSquare).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCropView.setCropMode(CropImageView.CropMode.CIRCLE_SQUARE); } }); } /** * 创建保存剪裁图片的Uri * * @return */ public Uri createSaveUri() { try { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { //检查路径是否存在 File dir = new File(cachePath); if (!dir.exists()) { dir.mkdirs(); } //检查文件是否存在 File file = new File(cachePath, "cropped.jpg"); if (!file.exists()) { file.createNewFile(); } cropPath = file.getAbsolutePath(); return Uri.fromFile(file); } } catch (Exception e) { e.printStackTrace(); } return null; } @Override public void onBackPressed() { super.onBackPressed(); if (isFromPick) { if (cropImageListener != null) { cropImageListener.onPickImage(); return; } } dismiss(); } private void showProgress() { progressBar.setVisibility(View.VISIBLE); } private void dismissProgress() { progressBar.setVisibility(View.GONE); } /** * @param cachePath * @param pickImageListener */ public void initCropDialog(String cachePath, CropImageListener pickImageListener) { this.cropImageListener = pickImageListener; this.cachePath = cachePath; } /** * 开始剪裁 * * @param pictureUri 要剪裁的图片的Uri */ public void show(Uri pictureUri, boolean isFromPick) { Log.i("CropImageDialog", pictureUri.toString()); this.isFromPick = isFromPick; super.show(); setDialogWindowAttr(); showProgress(); mCropView.startLoad(pictureUri, mLoadCallback); } // /** // * 开始剪裁 // * // * @param pictureUri // * @param isFromPick // */ // public void show(Uri pictureUri, boolean isFromPick) { // super.show(); // // setDialogWindowAttr(); // // Log.i("CropImageDialog", pictureUri.toString()); // // this.isFromPick = isFromPick; // // showProgress(); // mCropView.setImageURI(pictureUri); // // } /** * 调整dialog的大小 */ public void setDialogWindowAttr() { WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.gravity = Gravity.CENTER; lp.width = WindowManager.LayoutParams.MATCH_PARENT;//宽高可设置具体大小 lp.height = WindowManager.LayoutParams.MATCH_PARENT; getWindow().setAttributes(lp); } public String getCachePath() { return cachePath; } public void setCachePath(String cachePath) { this.cachePath = cachePath; } public CropImageListener getCropImageListener() { return cropImageListener; } public void setCropImageListener(CropImageListener cropImageListener) { this.cropImageListener = cropImageListener; } // Callbacks /////////////////////////////////////////////////////////////////////////////////// private final LoadCallback mLoadCallback = new LoadCallback() { @Override public void onSuccess() { dismissProgress(); } @Override public void onError() { dismissProgress(); } }; private final CropCallback mCropCallback = new CropCallback() { @Override public void onSuccess(Bitmap cropped) { } @Override public void onError() { } }; private final SaveCallback mSaveCallback = new SaveCallback() { @Override public void onSuccess(Uri outputUri) { dismissProgress(); if (cropImageListener != null) { cropImageListener.onCropSucceed(cropPath); } } @Override public void onError() { dismissProgress(); } }; public static interface CropImageListener { /** * 选择图片 */ public void onPickImage(); /** * 剪裁成功 * * @param path */ public void onCropSucceed(String path); } }
下面来看看效果图:
1.图片显示页面
2.图片文件夹显示页面
3.选中的图片的预览页面
4.图片剪裁页面
好了,就到这里吧!
如果有更深的理解,本文将会修改;
如果有错误的地方,欢迎指正;
如果你有更好的理解,欢迎交流。
本文为原创文章,版权归博主所有,转载请注明出处。
更多资料:
我的github地址以及使用demo: https://github.com/naivor/naivorapp
相关文章推荐
- node+express+mongoose快速搭建电影网站
- 格局与架构
- 大型网站架构系列:负载均衡详解(4)
- 大型网站架构系列:负载均衡详解(3)
- 大型网站架构系列:负载均衡详解(2)
- 大型网站架构系列:负载均衡详解(上)
- 专访阿里陈康贤:我所理解的网站架构
- Power Gating的设计(架构)
- 从12306.cn谈大网站架构与性能优化
- 指尖资讯——基于MVP架构、遵循Material Design的Android应用
- IP反查网站/IP反查接口 域名汇总
- 阿里云服务器重启后网站无法访问解决办法
- 流氓网站5599.net修改ie主页分析
- 安全论坛网站大全
- 大型网站系统架构的演化
- 学习Qt的资源-网站、论坛、博客等(必看)
- 802.1X/EAP架构
- 架构
- JavaScript判断移动端及pc端访问不同的网站
- 理解RESTful架构