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

最近做了选择多图并且上传服务器,在网上找了一些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

下面贴两张截图吧:

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-25 05:29:04

【Android源码解析】--选择多张图片上传多图预览的相关文章

微信JSSDK上传多图预览,点击查看大图

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no"> <meta name="ap

Android源码解析——LruCache

Android源码解析--LruCache LRU 在读LruCache源码之前,我们先来了解一下这里的Lru是什么.LRU全称为Least Recently Used,即最近最少使用,是一种缓存置换算法.我们的缓存容量是有限的,它会面临一个问题:当有新的内容需要加入我们的缓存,但我们的缓存空闲的空间不足以放进新的内容时,如何舍弃原有的部分内容从而腾出空间用来放新的内容.解决这个问题的算法有多种,比如LRU,LFU,FIFO等.需要注意区分的是LRU和LFU.前者是最近最少使用,即淘汰最长时间未

文件上传之图片预览

一.业界现状分析 有时候我们需要在上传图片之前为用户提供图片预览的功能,HTML5规范出来之前,由于缺少原生的File API支持,我们需要借助Flash或者浏览器插件来满足这种需求.有了HTML5,我们可使用URL或者FileReader对象实现预览功能. 二.应用场景 图片分享类的应用,如Flickr,Facebook.相册应用,如:QQ相册. 虽然139邮箱没有合适的应用场景,但是可将技术预研的成果作为技术储备,好东西总有用得着的时候. 三.编码实现 方式一:window.URL (1).

2016/4/19 ①单个文件上传 ②上传图片后 预览图片

1,f1.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <!-- 作业:在网上找上传图片预览的代码 上传服务器 再预览--> <form action="f1chuli.php&q

confluence上传文件附件预览乱码问题(linux服务器安装字体操作)

在confluence上传excel文件,预览时发现乱码问题主要是因为再上传文件的时候一般是Windows下的文件上传,而预览的时候,是linux下的环境,由于linux下没有微软字体,所以预览的时候无法识别文档字体,所以才会出现乱码.还比如某个业务有个功能生成图片,结果图片里的字全变空格了,这也是服务器上没相应的字库造成的.解决办法:在服务器上安装中文字体.操作方法如下: 1)先安装想要的字体, 如楷体等, 从本机"c盘->Windows-Fonts"文件夹里复制simkai字

关于confluence上传文件附件预览查看时出现乱码的问题解决办法

在confluence上传excel文件,预览时发现乱码问题主要是因为再上传文件的时候一般是Windows下的文件上传,而预览的时候,是linux下的环境,由于linux下没有微软字体,所以预览的时候无法识别文档字体,所以才会出现乱码.还比如某个业务有个功能生成图片,结果图片里的字全变空格了,这也是服务器上没相应的字库造成的. 1.解决办法:在服务器上安装中文字体.操作方法如下: 1)先安装想要的字体, 如楷体等, 从本机"c盘->Windows-Fonts"文件夹里复制simk

input 文件上传实现本地预览

上传图片 本地预览 获取图片大小 上传视频 本地预览 获取视频 duration 视频大小 图片上传 主要涉及内容 input accept filesList URL.createObjectURL() URL.revokeObjectURL() input file <label for='upload'></label> // ::before :: after 用于扩展可点击区域 <input type="file" id="upload

Android源码解析——Toast

简介 Toast是一种向用户快速提供少量信息的视图.当它显示时,它会浮在整个应用层的上面,并且不会获取到焦点.它的设计思想是能够向用户展示些信息,但又能尽量不显得唐突.本篇我们来研读一下Toast的源码,并探明它的显示及隐藏机制. 源码解析 Toast 我们从Toast的最简单调用开始,它的调用代码是: Toast.makeText(context,"Show toast",Toast.LENGTH_LONG).show(); 在上面的代码中,我们是先调用Toast的静态方法来创建一个

android源码解析--Handler

转载自:http://blog.csdn.net/lilu_leo/article/details/8143205 开始,先看下android官方对于Handler的解释: [java] view plaincopy /** * A Handler allows you to send and process {@link Message} and Runnable * objects associated with a thread's {@link MessageQueue}.  Each