【移动应用开发技术】怎么使用Android实现微信的图片选择器_第1页
【移动应用开发技术】怎么使用Android实现微信的图片选择器_第2页
【移动应用开发技术】怎么使用Android实现微信的图片选择器_第3页
【移动应用开发技术】怎么使用Android实现微信的图片选择器_第4页
【移动应用开发技术】怎么使用Android实现微信的图片选择器_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】怎么使用Android实现微信的图片选择器

在下给大家分享一下怎么使用Android实现微信的图片选择器,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!现在大部分的App都上传图片的功能,比如设置用户头像、聊天发送图片、发表动态、论坛帖子等。上传图片需要先从选择手机中选择要上传的图片,所以图片选择器在App中是很常见的组件,一般的手机都会自带一个图片选择器。不过很多App并不喜欢用手机自带的选择器,而是自己实现一个图片选择器。比如微信的图片选择器就做的很好。所以我也仿照微信的样式和交互效果,自己做了一个图片选择器:ImageSelector。ImageSelector支持图片的单选、限数量的多选和不限数量的多选。支持图片预览和图片文件夹的切换。项目已经上传到了我的GitHub,欢迎大家下载和使用。本篇文章我将为大家介绍ImageSelector是如何现实的。由于ImageSelector的项目代码比较多,所以这篇文章只讲解ImageSelector的实现思路和分析主要的项目代码。想要看完整代码的同学请到GitHub下载项目。至于ImageSelector的使用,在我的另一篇文章中有详细的介绍:《Android仿微信的图片选择器ImageSelector的使用》。先上效果图:要实现一个图片选择器,需要做的主要就是以下几个事情:1、从手机存储卡中扫描加载图片。2、用一个列表将图片显示出来。3、选择图片。4、把选中的图片返回给调用者。准备工作首先需要导入两个第三方库。//图片加载库,用于加载图片

compile

'com.github.bumptech.glide:glide:3.7.0'

//图片缩放库,用于图片的预览

compile

'com.github.chrisbanes:PhotoView:2.0.0'第一步:从手机存储卡中扫描加载图片读取手机存储卡需要先申请权限:<uses-permission

android:name="android.permission.WRITE_EXTERNAL_STORAGE"

/>对Android6.0以上的系统做动态权限处理。

/**

*

检查权限并加载SD卡里的图片。

*/

private

void

checkPermissionAndLoadImages()

{

int

hasWriteContactsPermission

=

ContextCompat.checkSelfPermission(getApplication(),

Manifest.permission.WRITE_EXTERNAL_STORAGE);

if

(hasWriteContactsPermission

==

PackageManager.PERMISSION_GRANTED)

{

//有权限,加载图片。

loadImageForSDCard();

}

else

{

//没有权限,申请权限。

ActivityCompat.requestPermissions(ImageSelectorActivity.this,

new

String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},

PERMISSION_REQUEST_CODE);

}

}

/**

*

处理权限申请的回调。

*/

@Override

public

void

onRequestPermissionsResult(int

requestCode,

String[]

permissions,

int[]

grantResults)

{

if

(requestCode

==

PERMISSION_REQUEST_CODE)

{

if

(grantResults.length

>

0

&&

grantResults[0]

==

PackageManager.PERMISSION_GRANTED)

{

//允许权限,加载图片。

loadImageForSDCard();

}

else

{

//拒绝权限,弹出提示框。

showExceptionDialog();

}

}

}接着就是从手机存储卡中扫描加载图片。

/**

*

从SDCard加载图片。

*/

private

void

loadImageForSDCard()

{

ImageModel.loadImageForSDCard(this,

new

ImageModel.DataCallback()

{

@Override

public

void

onSuccess(ArrayList<Folder>

folders)

{

//folders是图片文件夹的列表,每个文件夹中都有若干张图片。

}

});

}我将扫描手机存储卡的操作封装在ImageModel类,并通过DataCallback把扫描的结果返回给调用者。返回的结果是一个文件夹的列表,这是因为我们的图片选择器需要实现文件夹切换的功能,所以我把扫描出来的图片按文件夹进行了拆分。下面看文件夹实体类Folder和图片实体类Image:/**

*

图片文件夹实体类

*/

public

class

Folder

{

private

String

name;

private

ArrayList<Image>

images;

public

Folder(String

name)

{

=

name;

}

public

Folder(String

name,

ArrayList<Image>

images)

{

=

name;

this.images

=

images;

}

public

String

getName()

{

return

name;

}

public

void

setName(String

name)

{

=

name;

}

public

ArrayList<Image>

getImages()

{

return

images;

}

public

void

setImages(ArrayList<Image>

images)

{

this.images

=

images;

}

public

void

addImage(Image

image)

{

if

(image

!=

null

&&

StringUtils.isNotEmptyString(image.getPath()))

{

if

(images

==

null)

{

images

=

new

ArrayList<>();

}

images.add(image);

}

}

}

/**

*图片实体类

*/

public

class

Image

{

private

String

path;

private

long

time;

private

String

name;

public

Image(String

path,

long

time,

String

name)

{

this.path

=

path;

this.time

=

time;

=

name;

}

public

String

getPath()

{

return

path;

}

public

void

setPath(String

path)

{

this.path

=

path;

}

public

long

getTime()

{

return

time;

}

public

void

setTime(long

time)

{

this.time

=

time;

}

public

String

getName()

{

return

name;

}

public

void

setName(String

name)

{

=

name;

}

}注意,最核心的代码来了:使用ContentProvider扫描手机中的所有图片。public

class

ImageModel

{

/**

*

从SDCard加载图片

*/

public

static

void

loadImageForSDCard(final

Context

context,

final

DataCallback

callback)

{

//由于扫描图片是耗时的操作,所以要在子线程处理。

new

Thread(new

Runnable()

{

@Override

public

void

run()

{

//扫描图片

Uri

mImageUri

=

MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

ContentResolver

mContentResolver

=

context.getContentResolver();

Cursor

mCursor

=

mContentResolver.query(mImageUri,

new

String[]{

MediaStore.Images.Media.DATA,

MediaStore.Images.Media.DISPLAY_NAME,

MediaStore.Images.Media.DATE_ADDED,

MediaStore.Images.Media._ID},

null,

null,

MediaStore.Images.Media.DATE_ADDED);

ArrayList<Image>

images

=

new

ArrayList<>();

//读取扫描到的图片

while

(mCursor.moveToNext())

{

//

获取图片的路径

String

path

=

mCursor.getString(

mCursor.getColumnIndex(MediaStore.Images.Media.DATA));

//获取图片名称

String

name

=

mCursor.getString(

mCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));

//获取图片时间

long

time

=

mCursor.getLong(

mCursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED));

images.add(new

Image(path,

time,

name));

}

mCursor.close();

Collections.reverse(images);

callback.onSuccess(splitFolder(images));

}

}).start();

}

/**

*

把图片按文件夹拆分,第一个文件夹保存所有的图片

*/

private

static

ArrayList<Folder>

splitFolder(ArrayList<Image>

images)

{

ArrayList<Folder>

folders

=

new

ArrayList<>();

folders.add(new

Folder("全部图片",

images));

if

(images

!=

null

&&

!images.isEmpty())

{

int

size

=

images.size();

for

(int

i

=

0;

i

<

size;

i++)

{

String

path

=

images.get(i).getPath();

String

name

=

getFolderName(path);

if

(StringUtils.isNotEmptyString(name))

{

Folder

folder

=

getFolder(name,

folders);

folder.addImage(images.get(i));

}

}

}

return

folders;

}

/**

*

根据图片路径,获取图片文件夹名称

*/

private

static

String

getFolderName(String

path)

{

if

(StringUtils.isNotEmptyString(path))

{

String[]

strings

=

path.split(File.separator);

if

(strings.length

>=

2)

{

return

strings[strings.length

-

2];

}

}

return

"";

}

private

static

Folder

getFolder(String

name,

List<Folder>

folders)

{

if

(folders

!=

null

&&

!folders.isEmpty())

{

int

size

=

folders.size();

for

(int

i

=

0;

i

<

size;

i++)

{

Folder

folder

=

folders.get(i);

if

(name.equals(folder.getName()))

{

return

folder;

}

}

}

Folder

newFolder

=

new

Folder(name);

folders.add(newFolder);

return

newFolder;

}

public

interface

DataCallback

{

void

onSuccess(ArrayList<Folder>

folders);

}

}到这里,我们就已经拿到了手机里的所有图片了,接下来就是展示图片列表。第二步:展示图片这个非常的简单,其实就是写一个图片列表。

//图片列表

private

RecyclerView

rvImage;

//

初始化图片列表

private

void

initImageList()

{

mLayoutManager

=

new

GridLayoutManager(this,

3);

rvImage.setLayoutManager(mLayoutManager);

mAdapter

=

new

ImageAdapter(this,

mMaxCount,

isSingle);

rvImage.setAdapter(mAdapter);

}这里的ImageAdapter,就是图片列表的Adapter。public

class

ImageAdapter

extends

RecyclerView.Adapter<ImageAdapter.ViewHolder>

{

private

Context

mContext;

private

ArrayList<Image>

mImages;

private

LayoutInflater

mInflater;

private

int

mMaxCount;

private

boolean

isSingle;

/**

*

@param

maxCount

图片的最大选择数量,小于等于0时,不限数量,isSingle为false时才有用。

*

@param

isSingle

是否单选

*/

public

ImageAdapter(Context

context,

int

maxCount,

boolean

isSingle)

{

mContext

=

context;

this.mInflater

=

LayoutInflater.from(mContext);

mMaxCount

=

maxCount;

this.isSingle

=

isSingle;

}

@Override

public

ViewHolder

onCreateViewHolder(ViewGroup

parent,

int

viewType)

{

View

view

=

mInflater.inflate(R.layout.adapter_images_item,

parent,

false);

return

new

ViewHolder(view);

}

@Override

public

void

onBindViewHolder(final

ViewHolder

holder,

final

int

position)

{

final

Image

image

=

mImages.get(position);

Glide.with(mContext).load(new

File(image.getPath()))

.diskCacheStrategy(DiskCacheStrategy.NONE).into(holder.ivImage);

}

@Override

public

int

getItemCount()

{

return

mImages

==

null

?

0

:

mImages.size();

}

static

class

ViewHolder

extends

RecyclerView.ViewHolder

{

ImageView

ivImage;

ImageView

ivSelectIcon;

ImageView

ivMasking;

public

ViewHolder(View

itemView)

{

super(itemView);

ivImage

=

(ImageView)

itemView.findViewById(R.id.iv_image);

ivSelectIcon

=

(ImageView)

itemView.findViewById(R.id.iv_select);

ivMasking

=

(ImageView)

itemView.findViewById(R.id.iv_masking);

}

}

}第三步:选择图片点击选择图片,主要是对图片列表的ImageAdapter中的item进行操作,所以我就直接写在了ImageAdapter类里。选中的图片用一个数组保存。

//保存选中的图片

private

ArrayList<Image>

mSelectImages

=

new

ArrayList<>();

//点击选中/取消选中图片

holder.ivSelectIcon.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

v)

{

if

(mSelectImages.contains(image))

{

//如果图片已经选中,就取消选中

unSelectImage(image);

setItemSelect(holder,

false);

}

else

if

(isSingle)

{

//如果是单选,就先清空已经选中的图片,再选中当前图片

clearImageSelect();

selectImage(image);

setItemSelect(holder,true);

}

else

if

(mMaxCount

<=

0

||

mSelectImages.size()

<

mMaxCount)

{

//如果不限制图片的选中数量,或者图片的选中数量还没有达到最大限制,就直接选中当前图片。

selectImage(image);

setItemSelect(holder,

true);

}

}

});

/**

*

选中图片

*/

private

void

selectImage(Image

image){

mSelectImages.add(image);

}

/**

*

取消选中图片

*/

private

void

unSelectImage(Image

image

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论