开门见山,直奔主题。项目中,我们一直会用到选择相册或者拍照进行图片上传的控件,通常我们自己去用GridView或者RecyclerView去实现,还要写布局,写adapter之类的进行处理,这里砖家把这个控件进行了自定义封装,以后直接加入使用就行,分分钟集成图片上传。
一、控件使用方式:
<com.moral.imageuploadview.lib.ImageUploadView
android:id="@+id/iv_load"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.moral.imageuploadview.lib.ImageUploadView>
iv_load = (ImageUploadView) findViewById(R.id.iv_load);
iv_load.setImageClickListener(new ImageClickListener() {
@Override
public void addImageClickListener() {
//选择相册,加入图片
}
@Override
public void showImageClickListener(ArrayList<ImageModel> list, int position) {
//查看大图
}
@Override
public void delImageClickListener(int position) {
//删除图片
}
}).setImageLoaderInterface(new ImageLoaderUtil())//图片加载类
.setShowDel(true)//是否显示删除按钮
.setOneLineShowNum(3)//每行几张图
.setmPicSize(ImageUploadView.dp2px(this, 110));//每张图大小
}
//加入图片
iv_load.addImage(list);
配合https://github.com/jeasonlzy/ImagePicker使用,真是一分钟搞定。
ImagePicker的使用:
1、加载ImagePicker库
compile 'com.lzy.widget:imagepicker:0.5.5'
2、初始化工具
ImagePicker imagePicker = ImagePicker.getInstance();
imagePicker.setImageLoader(new GlideImageLoader()); //设置图片加载器
imagePicker.setShowCamera(true); //显示拍照按钮
imagePicker.setMultiMode(true);
imagePicker.setSelectLimit(9); //选中数量限制
imagePicker.setFocusWidth(800); //裁剪框的宽度。单位像素(圆形自动取宽高最小值)
imagePicker.setFocusHeight(800); //裁剪框的高度。单位像素(圆形自动取宽高最小值)
imagePicker.setOutPutX(400);//保存文件的宽度。单位像素
imagePicker.setOutPutY(400);//保存文件的高度。单位像素
3、在刚才控件的addImageClickListener() 回掉方法中使用
imagePicker.setSelectLimit(9-iv_load.getImageList().size()); //选中数量限制
Intent intent = new Intent(ImagePickActivity.this, ImageGridActivity.class);
startActivityForResult(intent, REQUEST_CODE);
在onActivityResult回调中取得所选择的图片进行展示:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == ImagePicker.RESULT_CODE_ITEMS) {
if (requestCode == REQUEST_CODE&&data!=null) {
//获取选择的图片
ArrayList<ImageItem> images = (ArrayList<ImageItem>) data.getSerializableExtra(ImagePicker.EXTRA_RESULT_ITEMS);
if (images != null && images.size() > 0) {
list.clear();
for (ImageItem item : images){
list.add(new ImageModel(item.path));
}
//加入控件中
iv_load.addImage(list);
}
}
}
}
效果图如下:
此外,还可与哔哩哔哩出品的Boxing库结合,一样愉快搬砖。
二、实现思路
控件主体还是使用GirdView实现的。
1、首先自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ImageUploadView">
<!-- 单张图片大小(宽高一样) -->
<attr name="pic_size" format="dimension" />
<!-- 最大数量 -->
<attr name="max_num" format="integer" />
<!-- 添加图片 -->
<attr name="add_res" format="reference" />
<!-- 删除图片 -->
<attr name="del_res" format="reference" />
<!-- 是否显示删除按钮-->
<attr name="is_show_del" format="boolean" />
<!-- 单行显示数量-->
<attr name="one_line_show_num" format="integer" />
</declare-styleable>
</resources>
2、接着直接开始码代码
注释很清晰,继承LinearLayout ,addView一个GridView就行了,这里主要是定定义好图片加载的接口ImageLoaderInterface ,点击回调事件ImageClickListener ,图片数据父类ImageModel,封装好adapter,还有各种配置属性,详见代码:
public class ImageUploadView extends LinearLayout {
private Context context;
private GridView gridView;
/**
* 图片加载接口
*/
private ImageLoaderInterface imageLoaderInterface;
/**
* 点击事件接口
*/
private ImageClickListener imageClickListener;
private ImageAdapter adapter;
private ArrayList<ImageModel> imageList;
/**
* 默认单个大小
*/
private static final int PIC_SIZE = 80;
/**
* 默认单行显示数量
*/
private static final int ONE_LINE_SHOW_NUM = 4;
/**
* 默认单个大小
*/
private static final int MAX_NUM = 9;
/**
* 单个item大小
*/
private int mPicSize;
/**
* 添加图片
*/
private int mAddLabel;
/**
* 删除图片
*/
private int mDelLabel;
/**
* 是否显示删除
*/
private boolean isShowDel;
/**
* 单行显示数量,默认4
*/
private int oneLineShowNum;
/**
* 最大数量
*/
private int maxNum;
初始化化代码
private void init(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ImageUploadView);
mPicSize = typedArray.getDimensionPixelSize(R.styleable.ImageUploadView_pic_size, dp2px(context, PIC_SIZE));
isShowDel = typedArray.getBoolean(R.styleable.ImageUploadView_is_show_del, true);
mAddLabel = typedArray.getResourceId(R.styleable.ImageUploadView_add_res, R.mipmap.image_add);
mDelLabel = typedArray.getResourceId(R.styleable.ImageUploadView_del_res, R.mipmap.image_del);
oneLineShowNum = typedArray.getInt(R.styleable.ImageUploadView_one_line_show_num, ONE_LINE_SHOW_NUM);
maxNum = typedArray.getInt(R.styleable.ImageUploadView_max_num, MAX_NUM);
typedArray.recycle();
imageList = new ArrayList<>();
gridView = new GridView(context);
gridView.setNumColumns(oneLineShowNum);
adapter = new ImageAdapter(context,imageList);
adapter.setIconHeight(mPicSize);
adapter.setAddPicRes(mAddLabel);
adapter.setDelPicRes(mDelLabel);
gridView.setAdapter(adapter);
addView(gridView);
}
各种操作方法的编写
/**
* 加载数据
*/
public void addImage(ImageModel model) {
if (model == null) {
return;
}
imageList.add(model);
if (adapter != null) {
adapter.notifyDataSetChanged();
}
}
/**
* 加载数据
*/
public void addImage(ArrayList<ImageModel> modelList) {
if (modelList == null) {
return;
}
imageList.addAll(modelList);
if (adapter != null) {
adapter.notifyDataSetChanged();
}
}
/**
* 清除数据
*/
public void clearImage(){
imageList.clear();
if (adapter != null) {
adapter.notifyDataSetChanged();
}
}
/**
* 获取图片数量
* @return
*/
public ArrayList<ImageModel> getImageList() {
return imageList;
}
public void setImageList(ArrayList<ImageModel> imageList) {
this.imageList = imageList;
}
/**
* 刷新控件
*/
public void notifyImage(){
if (adapter != null) {
adapter.notifyDataSetChanged();
}
}
public void delImage(int position){
imageList.remove(position);
if (adapter != null) {
adapter.notifyDataSetChanged();
}
}
关键点adapter的封装
public class ImageAdapter extends BaseAdapter {
private int mMaxNum = 9;
private Context context;
private ArrayList<ImageModel> imageList;
private ImageLoaderInterface imageLoader;
private ImageClickListener imageClickListener;
private int iconHeight;
private int delPicRes;
private int addPicRes;
private boolean isShowDel;
public int getmMaxNum() {
return mMaxNum;
}
public void setmMaxNum(int mMaxNum) {
this.mMaxNum = mMaxNum;
}
public ImageLoaderInterface getImageLoader() {
return imageLoader;
}
public void setImageLoader(ImageLoaderInterface imageLoader) {
this.imageLoader = imageLoader;
}
public ImageClickListener getImageClickListener() {
return imageClickListener;
}
public void setImageClickListener(ImageClickListener imageClickListener) {
this.imageClickListener = imageClickListener;
}
public int getIconHeight() {
return this.iconHeight;
}
public void setIconHeight(int iconHeight) {
this.iconHeight = iconHeight;
}
public int getDelPicRes() {
return delPicRes;
}
public void setDelPicRes(int delPicRes) {
this.delPicRes = delPicRes;
}
public int getAddPicRes() {
return addPicRes;
}
public void setAddPicRes(int addPicRes) {
this.addPicRes = addPicRes;
}
public boolean isShowDel() {
return isShowDel;
}
public void setShowDel(boolean showDel) {
this.isShowDel = showDel;
}
public ImageAdapter(Context context, ArrayList<ImageModel> imageList) {
this.context = context;
this.imageList = imageList;
}
@Override
public int getCount() {
return imageList.size()>=mMaxNum?mMaxNum:imageList.size()+1;
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(final int i, View view, ViewGroup viewGroup) {
FrameLayout frameLayout = null;
ViewHoler holer = null;
if(frameLayout == null){
frameLayout = new FrameLayout(context);
frameLayout.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT));
holer = new ViewHoler();
holer.iv_pic = new ImageView(context);
holer.iv_del = new ImageView(context);
frameLayout.addView( holer.iv_pic);
frameLayout.addView( holer.iv_del);
frameLayout.setTag(holer);
}else{
holer = (ViewHoler) frameLayout.getTag();
}
FrameLayout.LayoutParams pic_params = new FrameLayout.LayoutParams(iconHeight,
iconHeight);
pic_params.setMargins(10, 10, 10, 10);
holer.iv_pic.setLayoutParams(pic_params);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.TOP | Gravity.END;
holer.iv_del.setPadding(5, 5, 5, 5);
holer.iv_del.setLayoutParams(layoutParams);
holer.iv_del.setImageResource(delPicRes);
if(i==imageList.size()){
if(imageLoader!=null){
imageLoader.displayImage(context,addPicRes,holer.iv_pic);
}
}else{
if(imageLoader!=null){
Log.d("haijiang",imageList.get(i).getImg());
imageLoader.displayImage(context,imageList.get(i).getImg(),holer.iv_pic);
}
}
if(isShowDel){
if(i==imageList.size()){
holer.iv_del.setVisibility(View.GONE);
}else{
holer.iv_del.setVisibility(View.VISIBLE);
}
}else{
holer.iv_del.setVisibility(View.GONE);
}
holer.iv_pic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(imageClickListener!=null){
if(imageList.size()<mMaxNum&&i==imageList.size()){
imageClickListener.addImageClickListener();
}else{
imageClickListener.showImageClickListener(imageList,i);
}
}
}
});
holer.iv_del.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(imageClickListener!=null){
imageClickListener.delImageClickListener(i);
}
}
});
return frameLayout;
}
public static class ViewHoler{
private ImageView iv_pic;
private ImageView iv_del;
}
}
好了,代码比较简单,有兴趣的旁友可以自行下载源码进行修改和学习,以后项目中遇到这个功能,就可以直接搞起了。有木有爽炸天的感觉。