Android调用系统相机、本地相册上传图片(头像上传(裁剪)、
2017-12-28 本文已影响2138人
可以再长高10cm
开发中基本上都会有头像上传的功能,有的app还需要多张图片同时上传,下面简单将头像上传以及多张图片上传功能整理一下。图片选择仿照微信选择图片的界面。【参考】 多图片选择器
!!!推荐一个动态权限请求的框架: 动态权限申请
下面先看一下想要实现的效果图:多张图片
选择图片:
33333.png
头像上传:
11111.png
一、头像上传(单张图片上传,可设置图片裁剪的比例)
1、选择图片前请求读写权限。
//先请求权限,再进行操作
AndPermission.with(MainActivity.this)
.requestCode(300)
.permission(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE)
.callback(this)
.start();
权限申请注解
// 成功回调的方法,用注解即可,这里的300就是请求时的requestCode。
@PermissionYes(300)
private void getPermissionYes(List<String> grantedPermissions) {
// TODO 申请权限成功。
if(AndPermission.hasPermission(this,grantedPermissions)) {
// TODO 执行拥有权限时的下一步。
chooseImage();
} else {
// 使用AndPermission提供的默认设置dialog,用户点击确定后会打开App的设置页面让用户授权。
AndPermission.defaultSettingDialog(this, 300).show();
// 建议:自定义这个Dialog,提示具体需要开启什么权限,自定义Dialog具体实现上面有示例代码。
}
}
@PermissionNo(300)
private void getPermissionNo(List<String> deniedPermissions) {
// TODO 申请权限失败。
if(AndPermission.hasPermission(this,deniedPermissions)) {
// TODO 执行拥有权限时的下一步。
} else {
// 使用AndPermission提供的默认设置dialog,用户点击确定后会打开App的设置页面让用户授权。
AndPermission.defaultSettingDialog(this, 300).show();
// 建议:自定义这个Dialog,提示具体需要开启什么权限,自定义Dialog具体实现上面有示例代码。
}
}
2、初始化图片选择器,设置裁剪形状为正方形。
private ImagePicker getImagePickerSquare() {//正方形
ImagePicker imagePicker = ImagePicker.getInstance();
imagePicker.setImageLoader(new GlideImageLoader()); //设置图片加载器
imagePicker.setShowCamera(true); //显示拍照按钮
imagePicker.setCrop(true); //允许裁剪(单选才有效)
imagePicker.setSaveRectangle(true); //是否按矩形区域保存
imagePicker.setMultiMode(false); //多选
imagePicker.setStyle(CropImageView.Style.RECTANGLE); //裁剪框的形状
imagePicker.setFocusWidth(800); //裁剪框的宽度。单位像素(圆形自动取宽高最小值)
imagePicker.setFocusHeight(800); //裁剪框的高度。单位像素(圆形自动取宽高最小值)
imagePicker.setOutPutX(1000); //保存文件的宽度。单位像素
imagePicker.setOutPutY(1000); //保存文件的高度。单位像素
return imagePicker;
}
3、选择图片。chooseImage()
private void chooseImage() {
List<String> names = new ArrayList<>();
names.add("拍照");
names.add("从相册选择");
showDialog(new PictureChooseDialog.SelectDialogListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
switch (position) {
case 0: // 直接调起相机
//打开选择,本次允许选择的数量
getImagePickerSquare().setSelectLimit(maxImgCount - selImageList.size());
Intent intent = new Intent(MainActivity.this, ImageGridActivity.class);
intent.putExtra(ImageGridActivity.EXTRAS_TAKE_PICKERS,true); // 是否是直接打开相机
startActivityForResult(intent, REQUEST_CODE_SELECT);
break;
case 1:
//打开选择,本次允许选择的数量
getImagePickerSquare().setSelectLimit(maxImgCount - selImageList.size());
Intent intent1 = new Intent(MainActivity.this, ImageGridActivity.class);
startActivityForResult(intent1, REQUEST_CODE_SELECT);
break;
default:
break;
}
}
}, names);
}
4、选择图片后的处理,onActivityResult()
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == ImagePicker.RESULT_CODE_ITEMS) {
//添加图片返回
if (data != null && requestCode == REQUEST_CODE_SELECT) {
ArrayList<ImageItem> images = (ArrayList<ImageItem>) data.getSerializableExtra(ImagePicker.EXTRA_RESULT_ITEMS);
if (images != null){
ImageItem imageItem = images.get(0);
String newPathHead = imageItem.path;
updateMineMessage(newPathHead);
}
}
} else if (resultCode == ImagePicker.RESULT_CODE_BACK) {
//预览图片返回
if (data != null && requestCode == REQUEST_CODE_PREVIEW) {
ArrayList<ImageItem> images = (ArrayList<ImageItem>) data.getSerializableExtra(ImagePicker.EXTRA_IMAGE_ITEMS);
if (images != null){
ImageItem imageItem = images.get(0);
// String newPathHead = BitmapUtils.compressImageUpload(imageItem.path);
String newPathHead = imageItem.path;
updateMineMessage(newPathHead);
}
}
}
}
二、多张图片上传,选择后可删除,这里以最多九张图片为例。步骤与选择一张图片时基本一致,图片选择器稍微不同。
1、布局中图片用RecyclerView
<android.support.v7.widget.RecyclerView
android:padding="5dp"
android:id="@+id/recyclerView"
android:layout_marginTop="12dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice"
android:divider="@null"
android:fadingEdge="none"
android:listSelector="@android:color/transparent"
android:scrollbarStyle="outsideOverlay"
app:layoutManager="android.support.v7.widget.GridLayoutManager"
app:spanCount="4"
tools:listitem="@layout/item_upload_image">
</android.support.v7.widget.RecyclerView>
2、初始化图片选择器。
private void initImagePickerMulti() {
ImagePicker imagePicker = ImagePicker.getInstance();
imagePicker.setImageLoader(new GlideImageLoader()); //设置图片加载器
imagePicker.setShowCamera(true); //显示拍照按钮
imagePicker.setCrop(false); //允许裁剪(单选才有效)
imagePicker.setSaveRectangle(true); //是否按矩形区域保存
imagePicker.setSelectLimit(maxImgCount); //选中数量限制
imagePicker.setMultiMode(true); //多选
// imagePicker.setStyle(CropImageView.Style.RECTANGLE); //裁剪框的形状
// imagePicker.setFocusWidth(800); //裁剪框的宽度。单位像素(圆形自动取宽高最小值)
// imagePicker.setFocusHeight(800); //裁剪框的高度。单位像素(圆形自动取宽高最小值)
// imagePicker.setOutPutX(1000); //保存文件的宽度。单位像素
// imagePicker.setOutPutY(1000); //保存文件的高度。单位像素
}
3、图片适配器。
public class ImagePickerAdapter extends RecyclerView.Adapter<ImagePickerAdapter.SelectedPicViewHolder> {
private int maxImgCount;
private Context mContext;
private List<ImageItem> mData;
private LayoutInflater mInflater;
private OnRecyclerViewItemClickListener listener;
private boolean isAdded; //是否额外添加了最后一个图片
private OnItemRemoveClick onItemRemoveClick;
public boolean isAdded() {
return isAdded;
}
public void setAdded(boolean added) {
isAdded = added;
}
public void setOnItemRemoveClick(OnItemRemoveClick onItemRemoveClick) {
this.onItemRemoveClick = onItemRemoveClick;
}
public interface OnRecyclerViewItemClickListener {
void onItemClick(View view, int position);
}
public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
this.listener = listener;
}
public void setImages(List<ImageItem> data) {
mData = new ArrayList<>(data);
if (getItemCount() < maxImgCount) {
mData.add(new ImageItem());
isAdded = true;
} else {
isAdded = false;
}
notifyDataSetChanged();
}
public void addImg() {
if (getItemCount() < maxImgCount) {
mData.add(new ImageItem());
isAdded = true;
} else {
isAdded = false;
}
}
public List<ImageItem> getImages() {
//由于图片未选满时,最后一张显示添加图片,因此这个方法返回真正的已选图片
if (isAdded) return new ArrayList<>(mData.subList(0, mData.size() - 1));
else return mData;
}
public ImagePickerAdapter(Context mContext, List<ImageItem> data, int maxImgCount) {
this.mContext = mContext;
this.maxImgCount = maxImgCount;
this.mInflater = LayoutInflater.from(mContext);
setImages(data);
}
@Override
public SelectedPicViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new SelectedPicViewHolder(mInflater.inflate(R.layout.item_upload_image, parent, false));
}
@Override
public void onBindViewHolder(SelectedPicViewHolder holder, int position) {
holder.bind(position);
}
@Override
public int getItemCount() {
return mData.size();
}
public class SelectedPicViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private RelativeLayout cancelImg;
private int clickPosition;
private ImageView iv_img;
public SelectedPicViewHolder(View itemView) {
super(itemView);
iv_img = (ImageView) itemView.findViewById(R.id.iv_img);
cancelImg = ((RelativeLayout) itemView.findViewById(R.id.item_upload_image_cancelImg));
}
public void bind(final int position) {
//设置条目的点击事件
itemView.setOnClickListener(this);
//根据条目位置设置图片
ImageItem item = mData.get(position);
if (isAdded && position == getItemCount() - 1) {
iv_img.setScaleType(ImageView.ScaleType.FIT_XY);
cancelImg.setVisibility(View.INVISIBLE);
iv_img.setImageResource(R.mipmap.img_add);
clickPosition = UploadMoreImagesActivity.IMAGE_ITEM_ADD;
} else {
iv_img.setScaleType(ImageView.ScaleType.CENTER_CROP);
cancelImg.setVisibility(View.VISIBLE);
ImagePicker.getInstance().getImageLoader().displayImage((Activity) mContext, item.path, iv_img, 0, 0);
clickPosition = position;
}
cancelImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
removeItem(position);
onItemRemoveClick.onItemRemoveClick();
}
});
}
@Override
public void onClick(View v) {
if (listener != null) listener.onItemClick(v, clickPosition);
}
}
/**
* 删除某条item
* @param position
*/
public void removeItem(int position){
mData.remove(position);
// notifyItemRemoved(position);
}
public interface OnItemRemoveClick {
public void onItemRemoveClick();
}
}
4、适配器中选择图片的点击事件。adapter.setOnItemClickListener(this);
@Override
public void onItemClick(View view, int position) {
switch (position){
case IMAGE_ITEM_ADD:
//先请求权限,再进行操作
AndPermission.with(this)
.requestCode(300)
.permission(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE)
.callback(this)
.start();
break;
default:
//打开预览
Intent intentPreview = new Intent(this, ImagePreviewDelActivity.class);
intentPreview.putExtra(ImagePicker.EXTRA_IMAGE_ITEMS, (ArrayList<ImageItem>) adapter.getImages());
intentPreview.putExtra(ImagePicker.EXTRA_SELECTED_IMAGE_POSITION, position);
intentPreview.putExtra(ImagePicker.EXTRA_FROM_ITEMS,true);
startActivityForResult(intentPreview, REQUEST_CODE_PREVIEW);
break;
}
}
5、适配器中图片删除。
adapter.setOnItemRemoveClick(new ImagePickerAdapter.OnItemRemoveClick() {
@Override
public void onItemRemoveClick() {
adapter.setImages(adapter.getImages());
adapter.notifyDataSetChanged();
selImageList.clear();
selImageList.addAll(adapter.getImages());
}
});
6、发布时需要将图片上传至服务器,这里以 严振杰的NoHttp为例。(没有实际测试)
/**
* 上传图片到服务器
*/
private void upLoadImages() {
StringRequest request = new StringRequest("rul", RequestMethod.POST);
request.addHeader("", "");
request.add("content",contentEt.getText().toString());
for (int i = 0; i < selImageList.size(); i++) {
ImageItem imageItem = selImageList.get(i);
String newPath = imageItem.path;
File oldFile = new File(newPath);
File newFile = CompressHelper.getDefault(getApplicationContext()).compressToFile(oldFile);
request.add("imgs"+(i+1),newFile);
}
requestData(request, new SimpleResponseListener<String>() {
@Override
public void onStart(int what) {
super.onStart(what);
}
@Override
public void onSucceed(int what, Response<String> response) {
super.onSucceed(what, response);
//上传成功
}
});
}