前言
在网上找了很多第三方的相册拍照框架,都不尽人意,最后终于找到了一个比较好的框架,并且集成到了自己的demo中,花了两天的时间吧感觉挺值的。老规矩不说废话,直接上代码。
感谢某开源库的作者:Alum
以及本文的案例地址:Demo_ChooseImg
思路
先看目录,我尽可能的在自己力所能及的范围内,用最简单的方式和代码来实现。这里最重要的玩意儿是那个适配器。最下面的那个popupwindow是个自己写的控件,如果有兴趣我回头再把这个玩意儿放出来。
先看看功能吧:
简单来说就是点击加号可以新增或拍照,拍照后可直接返回到主页面直接更新图片。可以控制选择的图片数量,主题,以及预览等等。
先看布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/llMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<GridView
android:id="@+id/gvImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:horizontalSpacing="5dp"
android:numColumns="3"
android:verticalSpacing="5dp" />
</LinearLayout>
主页只有一个GridView+适配器
然后看一下每一个item的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--显示图片-->
<RelativeLayout
android:id="@+id/rlItemShow"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="?android:attr/selectableItemBackground"
android:visibility="gone">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/sdvItemShowImg"
android:layout_width="match_parent"
android:layout_height="match_parent"
fresco:actualImageScaleType="fitXY"
fresco:placeholderImage="@color/blue1"
fresco:placeholderImageScaleType="fitXY" />
<!--删除图片-->
<ImageView
android:id="@+id/ivDeleteImg"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_margin="5dp"
android:scaleType="fitXY"
android:src="@mipmap/ic_delete_img" />
</RelativeLayout>
<!--添加图片-->
<ImageView
android:id="@+id/ivItemAdd"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="@drawable/shape_iv_add_img"
android:padding="20dp"
android:scaleType="centerInside"
android:src="@mipmap/ic_plus_img"
android:visibility="gone" />
</LinearLayout>
手动控制一下宽高,这里对于每一个item来说,可以坐三件事情,显示图片,删除图片,新增图片。其中,点击显示的图片可以跳转到预览界面,点击删除图片可以删除被点的这张,点击新增图片跳转到相册。这个逻辑应该是简单而又清晰的。
那么我们主要来看一下适配器
public class ImgGridAdapter extends BaseAdapter {
private Context context;
private ArrayList<String> imgList;
private int maxImgCount;
private FreshImgCallBack freshImgCallBack;//针对三种操作逻辑所自定义的回调
public ImgGridAdapter(Context context, ArrayList<String> imgList, int maxImgCount) {
this.context = context;
this.imgList = imgList;
this.maxImgCount = maxImgCount;
}
/**
* 设置回调
*
* @param callBack freshImgCallBack
*/
public void setImgShowFresh(FreshImgCallBack callBack) {
freshImgCallBack = callBack;
}
@Override
public int getCount() {
if (imgList.size() < maxImgCount) {
return imgList.size() + 1;
} else {
return maxImgCount;
}
}
@Override
public Object getItem(int position) {
return imgList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (holder != null) {
holder = (ViewHolder) convertView.getTag();
} else {
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.itme_gridview, null);
holder.sdvItemShowImg = (SimpleDraweeView) convertView.findViewById(R.id.sdvItemShowImg);
holder.ivDeleteImg = (ImageView) convertView.findViewById(R.id.ivDeleteImg);
holder.ivItemAdd = (ImageView) convertView.findViewById(R.id.ivItemAdd);
holder.ivItemAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
freshImgCallBack.openGallery();//打开相册放在里面即可
}
});
holder.rlItemShow = (RelativeLayout) convertView.findViewById(R.id.rlItemShow);
}
//——————————————————————————————设置图片逻辑——————————————————————————————
holder.ivItemAdd.setVisibility(View.GONE);
holder.rlItemShow.setVisibility(View.GONE);
if (imgList.size() < 5) {
if (position == getCount() - 1) {
holder.ivItemAdd.setVisibility(View.VISIBLE);
} else {
if (getCount() > 1) {
showImg(position, holder);
}
}
} else {
showImg(position, holder);
}
//放在外面用于更新position
holder.sdvItemShowImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
freshImgCallBack.previewImg(position);//预览图片
}
});
holder.ivDeleteImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
freshImgCallBack.updateGvImgShow(position);//更新数据
}
});
return convertView;
}
//显示图片
private void showImg(int position, ViewHolder holder) {
holder.ivItemAdd.setVisibility(View.GONE);
holder.rlItemShow.setVisibility(View.VISIBLE);
//设置图片
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(Uri.parse("file://" + imgList.get(position)))
.setProgressiveRenderingEnabled(true)
.setResizeOptions(new ResizeOptions(100, 100))
.build();
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(request)
.setAutoPlayAnimations(true)
.setTapToRetryEnabled(true)
.setOldController(holder.sdvItemShowImg.getController())
.build();
holder.sdvItemShowImg.setController(controller);
}
class ViewHolder {
SimpleDraweeView sdvItemShowImg;
ImageView ivDeleteImg;
ImageView ivItemAdd;
RelativeLayout rlItemShow;
}
}
粗略看了一下一百多行,应该不算多吧- -!这里使用了Fresco是因为自己的项目里面用了这个框架,并且这里针对缩略图做了压缩处理。
针对如何显示新增图片,这里把逻辑理了一下:如果图片数量小于最大数量,那么就让gridview多显示一个,并且最后一个item只显示新增,否则就显示所有的图片。控制可见不可见对于内存资源的消耗相对较少。
适配器就是原生的适配器,我在里面写了一个接口的实现,用于在外部暴露一个入口来刷新图片。这里主要使用了观察者模式,不懂的同学自行学习接口回调。这里不再赘述。
看一下我定义的接口:
public interface FreshImgCallBack {
void previewImg(int position);//用于预览图片
void updateGvImgShow(int position);//用于刷新GridView
void openGallery();//用于打开相册
}
然后我们在Activity里面去实现它
public class MainActivity extends AppCompatActivity implements FreshImgCallBack {
private static final int REQUEST_CODE_GALLERY = 100;//打开相册
private static final int REQUEST_CODE_PREVIEW = 101;//预览图片
private GridView gvImage;
private ImgGridAdapter adapter;
private ArrayList<String> imgList = new ArrayList<>();
private final static int maxImgSize = 5;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
gvImage = (GridView) findViewById(R.id.gvImage);
adapter = new ImgGridAdapter(this, imgList, maxImgSize);
adapter.setImgShowFresh(this);//实现刷新接口
gvImage.setAdapter(adapter);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_GALLERY:
if (resultCode == RESULT_OK) {
imgList.clear();//不可直接指向
for (int i = Album.parseResult(data).size() - 1; i < 0; i++) {
imgList.add(Album.parseResult(data).get(i));//控制图片顺序
}
adapter.notifyDataSetChanged();
}
break;
}
}
//更新图片:当前用于删除
@Override
public void updateGvImgShow(int position) {
imgList.remove(position);
adapter.notifyDataSetChanged();
}
@Override
public void openGallery() {
Album.album(this)//打开相册
.requestCode(REQUEST_CODE_GALLERY)
.toolBarColor(ContextCompat.getColor(this, R.color.colorPrimary))
.statusBarColor(ContextCompat.getColor(this, R.color.colorPrimaryDark))
.selectCount(maxImgSize)
.columnCount(3)
.camera(true)
.checkedList(imgList)
.start();
}
@Override
public void previewImg(int position) {
Album.gallery(this)//预览图片
.requestCode(REQUEST_CODE_PREVIEW)
.toolBarColor(ContextCompat.getColor(this, R.color.colorPrimary))
.statusBarColor(ContextCompat.getColor(this, R.color.colorPrimaryDark))
.checkedList(imgList)
.currentPosition(position)
.checkFunction(false)
.start();
}
}
然后大功告成,这个逻辑应该是很简单的吧,实现方式应该也很简单。然后对于相册的功能,我引入的框架地址在文章头部已经标出来了。使用方法在github上面都写的很清楚。如果需要的话我后期会在本文下面列出使用教程。