【Android源码解析】选择多张图片上传多图预览

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/47731439

   最近做了选择多图并且上传服务器,在网上找了一些demo,适当的做了一下调整,用过了不能忘记,记下来以后还能多看看,本人觉得自己的博客有些渣渣,还希望大家不要介意啊,哪里有错误希望大家及时指正。

  好了下面具体的分析一下:(想要做出功能,需求分析是必不可少的,需求、逻辑弄懂了再上手写代码,思路会很清晰的)

1.多图上传首先得选择图片(这里项目需求是既可以拍照上传也可以从相册中选择)

2.拍照上传很简单了网上也有很多例子,调用照相机,返回uri,获取图片

3.从相册中选择图片

 3.1 获取手机中的所有图片

 3.2 将图片存到自定义图片数组中显示

 3.3 自定义ViewPager浏览图片

.

.

主要的逻辑大体是这样,下面具体看一下实现:

一、首先看一下界面:

<com.view.NoScrollGridView
                    android:id="@+id/noScrollgridview"
                    android:layout_marginLeft="@dimen/smaller_space"
                    android:layout_marginRight="@dimen/smaller_space"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:horizontalSpacing="3dp"
                    android:listSelector="@color/transparent"
                    android:numColumns="3"
                    android:scrollbars="none"
                    android:layout_gravity="center"
                    android:layout_marginTop="@dimen/smaller_space"
                    android:verticalSpacing="5dp" />

是一个 NoScrollGridView,项目需要,所以用了不滚动的GridView,大家用GridView也是一样的。

noScrollgridview = (GridView) findViewById(R.id.noScrollgridview);
        noScrollgridview.setSelector(new ColorDrawable(Color.TRANSPARENT));
        /*新建传值给adapter*/
        if (file == null) {
            picAdapter = new PictureAdapter(this, 0, null);
        } else {
            //添加失败的图片到数组中
            for (int i=0;i<file.getMulFailFilePaths().length;i++){
                ImageItem imageItem = new ImageItem();
                imageItem.setImagePath(file.getMulFailFilePaths()[i].trim());
                Bimp.tempSelectBitmap.add(imageItem);
            }
            /*上传失败传值给adapter*/
            picAdapter = new PictureAdapter(this, 2, file);
        }

这个是初始化图片数组,适配器(新建、上传失败、上传成功的图片我用的都是一个adapter)

ImageItem是图片的模型,下面有它的属性

//从图库选择的图片model
public class ImageItem extends File implements Serializable {
	@Id
	public String imageId; //图片id
	public String thumbnailPath; 
	public String imagePath; //图片路径
	private Bitmap bitmap; 
	public boolean isSelected = false;
	
	public String getImageId() {
		return imageId;
	}
	public void setImageId(String imageId) {
		this.imageId = imageId;
	}
	public String getThumbnailPath() {
		return thumbnailPath;
	}
	public void setThumbnailPath(String thumbnailPath) {
		this.thumbnailPath = thumbnailPath;
	}
	public String getImagePath() {
		return imagePath;
	}
	public void setImagePath(String imagePath) {
		this.imagePath = imagePath;
	}
	public boolean isSelected() {
		return isSelected;
	}
	public void setSelected(boolean isSelected) {
		this.isSelected = isSelected;
	}
	/*根据图片路径获取图片的bitmap*/
	public Bitmap getBitmap() {			
		if(bitmap == null){
			try {
				bitmap = Bimp.revitionImageSize(imagePath);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return bitmap;
	}
	public void setBitmap(Bitmap bitmap) {
		this.bitmap = bitmap;
	}
	
	
	
}

接下来是适配器:

由于涉及到添加图片,adapter中添加一个flag用来显示新建的图片,将选择的图片添加到公有的图片数组中,初始化的时候加载图片数组显示。(大家在看的时候可以忽略掉我的flag)

@SuppressLint("HandlerLeak")
public class PictureAdapter extends BaseAdapter {
    private LayoutInflater inflater;
    private int selectedPosition = -1;
    private boolean shape;
    private int flag = 0;//0 默认新建 1上传成功 2上传失败
    private AppItem_file file;
    public boolean isShape() {
        return shape;
    }
    private Activity context;

    public void setShape(boolean shape) {
        this.shape = shape;
    }

    public PictureAdapter(Activity context,int flag,AppItem_file file) {
        this.context = context;
        inflater = LayoutInflater.from(context);
        this.flag = flag;
        this.file = file;
    }

//    public void update() {
//        loading();
//    }

    public int getCount() {
        if (flag==0){   //新建图片
            if (Bimp.tempSelectBitmap.size() == 6) {
                return 6;
            }
            return (Bimp.tempSelectBitmap.size() + 1);
        }
        else if (flag==1){  //上传成功
            return file.getFileList().size();
        }
        else {  //上传失败
            return file.getMulFailFilePaths().length;
        }

    }



    public Object getItem(int arg0) {
        if (flag==1){
            return file.getFileList().get(arg0);
        }else {
            return file.getMulFailFilePaths()[arg0];
        }
    }

    public long getItemId(int arg0) {
        return arg0;
    }

    public void setSelectedPosition(int position) {
        selectedPosition = position;
    }

    public int getSelectedPosition() {
        return selectedPosition;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            //根据图片的数量加载不同布局
            if (getCount()==1&&flag!=0){
                convertView = inflater.inflate(R.layout.item_published_singal_item,
                        parent, false);
            }
            else {
                convertView = inflater.inflate(R.layout.item_published_grida,
                        parent, false);
            }

            holder = new ViewHolder();
            holder.image = (ImageView) convertView
                    .findViewById(R.id.item_grida_image);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        /**
         * 根据初始化adapter传过来的flag值,去不同的地方找图片
         * flag=0,去Bimp的图片数组中找
         * flag=1,证明上传成功的,去下载好的getFileList中找
         * flag=2,为上传失败的,图片保存在FailFile中的List<ImageItem>中
         * by黄海杰 at:2015年7月16日 09:51:25
         * 优化图片显示
         * by黄海杰 at:2015年8月3日 17:09:01
         */
        if (flag==0){   //新建图片
            if (position == Bimp.tempSelectBitmap.size()) {
                holder.image.setImageBitmap(BitmapFactory.decodeResource(
                        convertView.getResources(), R.drawable.icon_add_pic_unfocused));
                if (position == 6) {
                    if (flag==0){
                        holder.image.setVisibility(View.GONE);
                    }
                }
            } else {
                holder.image.setImageBitmap(Bimp.tempSelectBitmap.get(position).getBitmap());
            }
        }
        else if (flag==1){  //上传成功
//            List<Integer> ids = new ArrayList<Integer>();
//            for (int i=0;i<file.getFileList().size();i++){
//                ids.add(file.getFileList().get(i).getS_id());
//            }
            int id=file.getFileList().get(position).getS_id();
            try {
//                File file= NeedApplication.db.findById(File.class,id);
                String fileBigImgUri =NeedApplication.db.findById(File.class,id).getFileUriBig();
                if (fileBigImgUri!=null&&!"null".equals(fileBigImgUri))
                ImageLoader.getInstance().displayImage((fileBigImgUri).trim(),holder.image);
            } catch (DbException e) {
                e.printStackTrace();
            }
        }
        else {  //上传失败
                String url = "file://"+file.getMulFailFilePaths()[position].trim();
                ImageLoader.getInstance().displayImage(url, holder.image);
        }


        return convertView;
    }

    public class ViewHolder {
        public ImageView image;
    }

}

下面是自定义相册界面,用来选择图片的

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:background="#E1E0DE"
    >

    <RelativeLayout
        android:id="@+id/headview"
        android:layout_width="fill_parent"
        android:layout_height="45dp"
        android:background="@drawable/plugin_camera_title_bar"
        android:gravity="center_vertical"
        android:layout_marginBottom="3dp"
        >
        <Button
            android:layout_width="60dp"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:textColor="#fff"
            android:id="@+id/back"
            android:text="相册"
            android:background="@drawable/plugin_camera_title_btn_back"
            android:layout_marginTop="5dp"
            android:layout_marginBottom="5dp"
            android:layout_centerVertical="true"
            />
        <Button
            android:layout_width="67dp" 
      	    android:layout_height="wrap_content"
        	android:textSize="14sp"
        	android:textColor="#fff"
        	android:id="@+id/cancel"
        	android:text="取消"
        	android:background="@drawable/plugin_camera_title_btn_cancel"
      	    android:layout_centerVertical="true"
      	    android:layout_marginRight="5dp"
            android:layout_alignParentRight="true" 
            />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/bottom_layout"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:background="@drawable/plugin_camera_bottom_bar"
        android:layout_marginTop="3dp"
        >
 		<Button
            android:id="@+id/preview"
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:text="预览"
            android:background="@drawable/plugin_camera_title_btn_preview"
            />
        <Button
            android:id="@+id/ok_button"
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="10dp"
            android:background="@drawable/plugin_camera_ok_btn_state"
            />
    </RelativeLayout>

    <GridView
        android:id="@+id/myGrid"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_above="@id/bottom_layout"
        android:layout_below="@id/headview"
        android:layout_centerInParent="true"
        android:layout_marginTop="2dp"
        android:horizontalSpacing="10dp"
        android:numColumns="4"
        android:verticalSpacing="10dp"
        android:background="#E1E0DE" />
    <TextView
        android:id="@+id/myText"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="相册没有图片"
        android:textColor="@color/black"
        />

</RelativeLayout>

同样也是用了GridView,获取手机中的图片,添加到数组中,显示

这里用到了一个AlbumHelper(相册帮助类),网上找的代码,感觉挺好的

public List<ImageBucket> getImagesBucketList(boolean refresh) {
		if (refresh || (!refresh && !hasBuildImagesBucketList)) {
			buildImagesBucketList();
		}
		List<ImageBucket> tmpList = new ArrayList<ImageBucket>();
		Iterator<Entry<String, ImageBucket>> itr = bucketList.entrySet()
				.iterator();
		while (itr.hasNext()) {
			Entry<String, ImageBucket> entry = (Entry<String, ImageBucket>) itr
					.next();
			tmpList.add(entry.getValue());
		}
		return tmpList;
	}

获取到数据源之后,该显示了,也就是利用的获取图片帮助类里面的方法

// 初始化,给一些对象赋值
	private void init() {
		helper = AlbumHelper.getHelper();
		helper.init(getApplicationContext());
		
		contentList = helper.getImagesBucketList(false);
		dataList = new ArrayList<ImageItem>();
		for(int i = 0; i<contentList.size(); i++){
			dataList.addAll( contentList.get(i).imageList );
		}
		
		back = (Button) findViewById(R.id.back);
		cancel = (Button) findViewById(R.id.cancel);
		cancel.setOnClickListener(new CancelListener());
		back.setOnClickListener(new BackListener());
		preview = (Button) findViewById(R.id.preview);
		preview.setOnClickListener(new PreviewListener());
		intent = getIntent();
		Bundle bundle = intent.getExtras();
		gridView = (GridView) findViewById(R.id.myGrid);
		gridImageAdapter = new AlbumGridViewAdapter(mContext,dataList,Bimp.tempSelectBitmap);
		gridView.setAdapter(gridImageAdapter);
		tv = (TextView) findViewById(R.id.myText);
		gridView.setEmptyView(tv);
		okButton = (Button) findViewById(R.id.ok_button);
		okButton.setText("完成"+"(" + Bimp.tempSelectBitmap.size()
				+ "/"+ NeedApplication.picNums+")");
	}
gridImageAdapter
				.setOnItemClickListener(new AlbumGridViewAdapter.OnItemClickListener() {

					@Override
					public void onItemClick(final ToggleButton toggleButton,
							int position, boolean isChecked,Button chooseBt) {
						if (Bimp.tempSelectBitmap.size() >= NeedApplication.picNums) {
							toggleButton.setChecked(false);
							chooseBt.setVisibility(View.GONE);
							if (!removeOneData(dataList.get(position))) {
								Toast.makeText(AlbumActivity.this, "超出可选图片张数", Toast.LENGTH_SHORT).show();
							}
							return;
						}
						if (isChecked) {
							chooseBt.setVisibility(View.VISIBLE);
							Bimp.tempSelectBitmap.add(dataList.get(position));
							okButton.setText("完成"+"(" + Bimp.tempSelectBitmap.size()
									+ "/"+ NeedApplication.picNums+")");
						} else {
							Bimp.tempSelectBitmap.remove(dataList.get(position));
							chooseBt.setVisibility(View.GONE);
							okButton.setText("完成"+"(" + Bimp.tempSelectBitmap.size() + "/"+ NeedApplication.picNums+")");
						}
						isShowOkBt();
					}
				});

点击图片选择加到公有图片数组中显示已选择

最后是预览图片,利用自定义viewpager,实现图片滑动.....代码就不占了,好多demo

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏图像识别与深度学习

《Android》Lesson04-Menu

21370
来自专栏Phoenix的Android之旅

ListView的相关总结

回顾一下, ListView的使用其实非常简单, 只需要提供一个 UI,提供一个装载数据的 Adapter, 在 Adapter的 getView 方法里实现每...

11020
来自专栏腾讯Bugly的专栏

RecyclerView 必知必会

导语 RecyclerView是Android 5.0提出的新UI控件,可以用来代替传统的ListView。 Bugly之前也发过一篇相关文章,讲解了 Recy...

48970
来自专栏androidBlog

RecycleView下拉刷新控件的封装(包括下拉刷新和加载更多 )

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

49710
来自专栏项勇

[Android学习]之解析练习RadioButton+Fragment+viewpager布局架构

25040
来自专栏向治洪

Android View架构总结

View和Activity的区别 android的四大组件,Activity是四大组件中唯一一个用来和用户进行交互的组件。可以说Activity就是androi...

25860
来自专栏向治洪

可拖拽gridview

在Android开发中,我们常常用到ListView和GridView,而有的时候系统的ListView,GridView并不能满足我们的需求,所以我们需要自己...

32350
来自专栏Vamei实验室

安卓第五夜 维纳斯的诞生

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

20830
来自专栏飞雪无情的博客

Android EditText使用详解-包含很多教程上看不到的功能演示

标题有点大,说是详解,其实就是对EditText的一些常用功能的介绍,包括密码框,电话框,空白提示文字等等的讲解,尽量的介绍详细一点,也就是所谓的详解了。。呵呵

76420
来自专栏Android知识点总结

1--安卓多媒体之图片综合篇

8420

扫码关注云+社区

领取腾讯云代金券