最近在做一个拍照应用,查看图库时要有类似于 Google Photos 的效果:

  1. 长按图片时,图库进入多选模式,被选中的图片则需要缩放
  2. 在选中的图片点击或长按时,则取消选中,图片需要恢复原始大小
  3. 在多选模式时,点击返回键,被选中的图片需要统一恢复原始大小
  4. 全选和取消全选的操作,同样需要缩放、恢复原始大小

为了更好的操作单个/多个 Grid Item 控件,将控件改为了 RecyclerView。

在继承自 RecyclerView.Adapter 的 GalleryRecyclerAdapter 中,使用 SparseArray\ 存储选中的 Item。

下面直接讲一下在选中图片时如何进行缩放、取消选中时恢复原始大小。
在图片未进入多选模式时,长按任何一个图片,则进入多选模式,点击图片则执行如下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void performGalleryItemCheck(int position) {
// 改变对应位置图片的选中状态
mAdapter.toggleItemChoice(position);
GalleryRecyclerViewHolder viewHolder = (GalleryRecyclerViewHolder) mPhotoGrid.findViewHolderForAdapterPosition(position);
if (viewHolder != null) {
// 对 view 执行动画
playHolderAnimatorSet(viewHolder, mAdapter.getItemSelected(position));
}

int count = mAdapter.getSelectedItemsCount();
if (count == 0) {
mSelectActionMode.setTitle("");
} else {
mSelectActionMode.setTitle(String.valueOf(count));
}
mSelectActionMode.invalidate();

}

playHolderAnimatorSet 方法的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void playHolderAnimatorSet(final GalleryRecyclerViewHolder holder, final boolean selected) {
ObjectAnimator scaleX;
ObjectAnimator scaleY;
holder.mCheckableImageView.setImageResource(selected ? R.mipmap.ic_photo_corner_checked : R.mipmap.ic_photo_corner_normal);
holder.mCheckableImageView.setVisibility(View.VISIBLE);
if (selected) {
scaleX = ObjectAnimator.ofFloat(holder.mPhotoView, "scaleX", 1.0f, 0.8F);
scaleY = ObjectAnimator.ofFloat(holder.mPhotoView, "scaleY", 1.0f, 0.8F);
} else {
scaleX = ObjectAnimator.ofFloat(holder.mPhotoView, "scaleX", 0.8f, 1.0F);
scaleY = ObjectAnimator.ofFloat(holder.mPhotoView, "scaleY", 0.8f, 1.0F);
}

AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(scaleX).with(scaleY);
animatorSet.setDuration(150);
animatorSet.start();
}

通过 ViewHolder 获取到 ImageView,对 ImageView 执行选中/未选中的动画。

到这里应该已经清楚如何实现全选/取消全选的操作了。

全选:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void performSelectAllAction() {

int size = Data.URLS.length;
for (int i = 0; i < size; i++) {
GalleryRecyclerViewHolder viewHolder = (GalleryRecyclerViewHolder) mPhotoGrid.findViewHolderForAdapterPosition(i);
if (viewHolder != null) {
viewHolder.mCheckableImageView.setImageResource(R.mipmap.ic_photo_corner_checked);
viewHolder.mCheckableImageView.setVisibility(View.VISIBLE);
if (!mAdapter.getItemSelected(i)) {
mAdapter.toggleItemChoice(i);
playHolderAnimatorSet(viewHolder, true);
}
} else {
if (!mAdapter.getItemSelected(i)) {
mAdapter.toggleItemChoice(i);
}
}
}
}

取消全选:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void clearSelectionWithAnimator(boolean showCheckImage) {
SparseArray<Integer> mSelections = mAdapter.getMultiSelections();
int size = mSelections.size();
for(int i = 0; i < size; i++) {
int position = mSelections.valueAt(i);
GalleryRecyclerViewHolder viewHolder = (GalleryRecyclerViewHolder) mPhotoGrid.findViewHolderForAdapterPosition(position);
if (viewHolder != null) {
viewHolder.mCheckableImageView.setImageResource(R.mipmap.ic_photo_corner_normal);
viewHolder.mCheckableImageView.setVisibility(showCheckImage ? View.VISIBLE : View.GONE);
playHolderAnimatorSet(viewHolder, false);
}
}
mAdapter.clearMultiSelections();
}

显示效果:

Recycler_Photos_Preview_0

Recycler_Photos_Preview_1

Recycler_Photos_Preview_2

源码下载地址:RecyclerPhotos