1.由于产品想要图片上传的时候到后台数据,增加排序,安卓端展示选择的时候,就需要增加选择的数字标识
类似于安卓版QQ选择图片上传功能(ios则类似于ios版微信)
2.选择图片框架,我是基于ImagePicker虽然没有维护,但是基本能用
3.添加图片上传数字标识,思路其实很简单,就是在对应的图片的bean里面增加一个字段就可以;
4.ImagePicker对应的bean
public String name; //图片的名字
public String path; //图片的路径
public long size; //图片的大小
public int width; //图片的宽度
public int height; //图片的高度
public String mimeType; //图片的类型
public long addTime;
private int uploadIndex; //上传图片数字顺序
private String custId;
private String attachId;
private String generateSmallURL;
private String generateURL;
public boolean isLocal = true;
private boolean isDelete = true;
private String withdrawalId;
5.之后就是各种adapter里面的数字显示,小图的adapter对应的代码
public class ImageRecyclerAdapter extends RecyclerView.Adapter<ViewHolder> {
private static final int ITEM_TYPE_CAMERA = 0; //第一个条目是相机
private static final int ITEM_TYPE_NORMAL = 1; //第一个条目不是相机
private ImagePicker imagePicker;
private Activity mActivity;
private ArrayList<ImageItem> images; //当前需要显示的所有的图片数据
private ArrayList<ImageItem> mSelectedImages; //全局保存的已经选中的图片数据
private boolean isShowCamera; //是否显示拍照按钮
private int mImageSize; //每个条目的大小
private LayoutInflater mInflater;
private OnImageItemClickListener listener; //图片被点击的监听
private int maxIndex = 0;
public void setOnImageItemClickListener(OnImageItemClickListener listener) {
this.listener = listener;
}
public interface OnImageItemClickListener {
void onImageItemClick(View view, ImageItem imageItem, int position);
}
public void refreshData(ArrayList<ImageItem> images) {
if (images == null || images.size() == 0) {
this.images = new ArrayList<>();
} else {
this.images = images;
}
notifyDataSetChanged();
}
/**
* 构造方法
*/
public ImageRecyclerAdapter(Activity activity, ArrayList<ImageItem> images) {
this.mActivity = activity;
if (images == null || images.size() == 0){
this.images = new ArrayList<>();
}else{
this.images = images;
}
mImageSize = Utils.getImageItemWidth(mActivity);
imagePicker = ImagePicker.getInstance();
isShowCamera = imagePicker.isShowCamera();
mSelectedImages = imagePicker.getSelectedImages();
mInflater = LayoutInflater.from(activity);
}
public void setmSelectedImages(ArrayList<ImageItem> mSelectedImages) {
this.mSelectedImages = mSelectedImages;
notifyDataSetChanged();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == ITEM_TYPE_CAMERA){
return new CameraViewHolder(mInflater.inflate(R.layout.adapter_camera_item,parent,false));
}
return new ImageViewHolder(mInflater.inflate(R.layout.adapter_image_list_item,parent,false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (holder instanceof CameraViewHolder){
((CameraViewHolder)holder).bindCamera();
}else if (holder instanceof ImageViewHolder){
((ImageViewHolder)holder).bind(position);
}
}
@Override
public int getItemViewType(int position) {
if (isShowCamera){
return position == 0 ? ITEM_TYPE_CAMERA : ITEM_TYPE_NORMAL;
}
return ITEM_TYPE_NORMAL;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemCount() {
return isShowCamera ? images.size() + 1 : images.size();
}
public ImageItem getItem(int position) {
if (isShowCamera) {
if (position == 0){
return null;
}
return images.get(position - 1);
} else {
return images.get(position);
}
}
private class ImageViewHolder extends ViewHolder{
View rootView;
ImageView ivThumb;
View mask;
TextView indexTV;
SuperCheckBox cbCheck;
ImageViewHolder(View itemView) {
super(itemView);
rootView = itemView;
ivThumb = (ImageView) itemView.findViewById(R.id.iv_thumb);
mask = itemView.findViewById(R.id.mask);
cbCheck = (SuperCheckBox) itemView.findViewById(R.id.cb_check);
indexTV = (TextView) itemView.findViewById(R.id.indexTV);
}
void bind(final int position){
final ImageItem imageItem = getItem(position);
ivThumb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) {
listener.onImageItemClick(rootView, imageItem, position);
}
}
});
cbCheck.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
maxIndex = mSelectedImages.size();
int selectLimit = imagePicker.getSelectLimit();
if (cbCheck.isChecked() && mSelectedImages.size() >= selectLimit) {
Toast.makeText(mActivity.getApplicationContext(), mActivity.getString(R.string.select_limit, selectLimit), Toast.LENGTH_SHORT).show();
cbCheck.setChecked(false);
mask.setVisibility(View.GONE);
} else {
if(cbCheck.isChecked()){
//选择只管自增即可
maxIndex +=1;
imageItem.setUploadIndex(maxIndex);
}else {
int currentIndex;
boolean isSelected = imagePicker.isSelect(imageItem);
if(isSelected){
currentIndex = mSelectedImages.get(mSelectedImages.indexOf(imageItem)).getUploadIndex();
}else {
currentIndex = imageItem.getUploadIndex();
}
if(currentIndex < maxIndex){
//小于的要遍历所有的entity数据,设置大于自己的uploadIndex的Entity对应的uploadIndex都要自减
for (ImageItem image : mSelectedImages) {
int index = image.getUploadIndex();
if(index > currentIndex){
index -=1;
image.setUploadIndex(index);
}
}
notifyDataSetChanged();
}
imageItem.setUploadIndex(0);
maxIndex -=1;
}
imagePicker.addSelectedImageItem(position, imageItem, cbCheck.isChecked());
mask.setVisibility(View.VISIBLE);
}
}
});
//根据是否多选,显示或隐藏checkbox
if (imagePicker.isMultiMode()) {
cbCheck.setVisibility(View.VISIBLE);
boolean checked = mSelectedImages.contains(imageItem);
if (checked) {
ImageItem selectImage = mSelectedImages.get(mSelectedImages.indexOf(imageItem));
mask.setVisibility(View.VISIBLE);
cbCheck.setChecked(true);
indexTV.setVisibility(View.VISIBLE);
LogUtils.w("index----->"+selectImage.getUploadIndex());
indexTV.setText(selectImage.getUploadIndex()+"");
} else {
mask.setVisibility(View.GONE);
indexTV.setVisibility(View.GONE);
cbCheck.setChecked(false);
}
} else {
indexTV.setVisibility(View.GONE);
cbCheck.setVisibility(View.GONE);
}
imagePicker.getImageLoader().displayImage(mActivity, "file://"+imageItem.getPath(), ivThumb, mImageSize, mImageSize); //显示图片
}
}
private class CameraViewHolder extends ViewHolder{
View mItemView;
CameraViewHolder(View itemView) {
super(itemView);
mItemView = itemView;
}
void bindCamera(){
mItemView.setTag(null);
mItemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!((ImageBaseActivity) mActivity).checkPermission(Manifest.permission.CAMERA)) {
ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.CAMERA}, ImageGridActivity.REQUEST_PERMISSION_CAMERA);
} else {
imagePicker.takePicture(mActivity, ImagePicker.REQUEST_CODE_TAKE);
}
}
});
}
}
}
对应的逻辑是,对于选中的图片,只管获取当前选择图片list的size(),之后自增就可以,取消选中图片,则相对于复杂点,首先要获取当前item是否在mSelectedImages中,并取出对应的index,和最大的标识做对比,等于就直接把对应的index归0并且移除选择list,小于则还要多一步操作,遍历比自己index大的item,大于的index自减。我在代码中加了注释,基本能看懂
6.大图对应的Activity也要做相应的逻辑,具体代码
public class ImagePreviewActivity extends ImagePreviewBaseActivity implements ImagePicker.OnImageSelectedListener, View.OnClickListener, CompoundButton.OnCheckedChangeListener {
public static final String ISORIGIN = "isOrigin";
private boolean isOrigin; //是否选中原图
private SuperCheckBox mCbCheck; //是否选中当前图片的CheckBox
private SuperCheckBox mCbOrigin; //原图
private Button mBtnOk; //确认图片的选择
private View bottomBar;
private TextView indexTV;
private int maxIndex = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isOrigin = getIntent().getBooleanExtra(ImagePreviewActivity.ISORIGIN, false);
imagePicker.addOnImageSelectedListener(this);
mBtnOk = (Button) topBar.findViewById(R.id.btn_ok);
mBtnOk.setVisibility(View.VISIBLE);
mBtnOk.setOnClickListener(this);
bottomBar = findViewById(R.id.bottom_bar);
bottomBar.setVisibility(View.VISIBLE);
mCbCheck = (SuperCheckBox) findViewById(R.id.cb_check);
mCbOrigin = (SuperCheckBox) findViewById(R.id.cb_origin);
indexTV = (TextView) findViewById(R.id.indexTV);
mCbOrigin.setText(getString(R.string.origin));
mCbOrigin.setOnCheckedChangeListener(this);
mCbOrigin.setChecked(isOrigin);
//初始化当前页面的状态
onImageSelected(0, null, false);
ImageItem item = mImageItems.get(mCurrentPosition);
boolean isSelected = imagePicker.isSelect(item);
mTitleCount.setText(getString(R.string.preview_image_count, mCurrentPosition + 1, mImageItems.size()));
mCbCheck.setChecked(isSelected);
showIndex(isSelected,item);
//滑动ViewPager的时候,根据外界的数据改变当前的选中状态和当前的图片的位置描述文本
mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
mCurrentPosition = position;
ImageItem item = mImageItems.get(mCurrentPosition);
boolean isSelected = imagePicker.isSelect(item);
showIndex(isSelected,item);
LogUtils.w("addOnPageChangeListener----->index="+item.getUploadIndex());
mTitleCount.setText(getString(R.string.preview_image_count, mCurrentPosition + 1, mImageItems.size()));
}
});
//当点击当前选中按钮的时候,需要根据当前的选中状态添加和移除图片
mCbCheck.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
maxIndex = selectedImages.size();
ImageItem imageItem = mImageItems.get(mCurrentPosition);
int selectLimit = imagePicker.getSelectLimit();
if (mCbCheck.isChecked() && selectedImages.size() >= selectLimit) {
Toast.makeText(ImagePreviewActivity.this, ImagePreviewActivity.this.getString(R.string.select_limit, selectLimit), Toast.LENGTH_SHORT).show();
mCbCheck.setChecked(false);
} else {
if(mCbCheck.isChecked()){
//选择只管自增即可
maxIndex +=1;
imageItem.setUploadIndex(maxIndex);
indexTV.setVisibility(View.VISIBLE);
indexTV.setText(maxIndex+"");
}else {
indexTV.setVisibility(View.GONE);
int currentIndex;
boolean isSelected = imagePicker.isSelect(imageItem);
if(isSelected){
currentIndex = selectedImages.get(selectedImages.indexOf(imageItem)).getUploadIndex();
}else {
currentIndex = imageItem.getUploadIndex();
}
if(currentIndex < maxIndex){
//小于的要遍历所有的entity数据,设置大于自己的uploadIndex的Entity对应的uploadIndex都要自减
for (ImageItem image : selectedImages) {
int index = image.getUploadIndex();
if(index > currentIndex){
LogUtils.w("currentIndex-----"+currentIndex+"-----------index="+index);
index -=1;
image.setUploadIndex(index);
}
LogUtils.w("-------index="+index);
}
}
maxIndex -=1;
imageItem.setUploadIndex(0);
mAdapter.notifyDataSetChanged();
}
imagePicker.addSelectedImageItem(mCurrentPosition, imageItem, mCbCheck.isChecked());
}
}
});
}
private void showIndex(boolean isSelected,ImageItem item){
if(isSelected){
ImageItem selectImage = selectedImages.get(selectedImages.indexOf(item));
indexTV.setVisibility(View.VISIBLE);
indexTV.setText(selectImage.getUploadIndex()+"");
LogUtils.w("showIndex------>"+selectImage.getUploadIndex());
mCbCheck.setChecked(true);
}else {
indexTV.setVisibility(View.GONE);
mCbCheck.setChecked(false);
}
}
/**
* 图片添加成功后,修改当前图片的选中数量
* 当调用 addSelectedImageItem 或 deleteSelectedImageItem 都会触发当前回调
*/
@Override
public void onImageSelected(int position, ImageItem item, boolean isAdd) {
if (imagePicker.getSelectImageCount() > 0) {
mBtnOk.setText(getString(R.string.select_complete, imagePicker.getSelectImageCount(), imagePicker.getSelectLimit()));
mBtnOk.setEnabled(true);
} else {
mBtnOk.setText(getString(R.string.complete));
mBtnOk.setEnabled(false);
}
if (mCbOrigin.isChecked()) {
long size = 0;
for (ImageItem imageItem : selectedImages) {
size += imageItem.size;
}
String fileSize = Formatter.formatFileSize(this, size);
mCbOrigin.setText(getString(R.string.origin_size, fileSize));
}
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btn_ok) {
Intent intent = new Intent();
intent.putExtra(ImagePicker.EXTRA_RESULT_ITEMS, imagePicker.getSelectedImages());
setResult(ImagePicker.RESULT_CODE_ITEMS, intent);
finish();
} else if (id == R.id.btn_back) {
Intent intent = new Intent();
// intent.putExtra(ImagePreviewActivity.ISORIGIN, isOrigin);
intent.putExtra(ImagePreviewActivity.ISORIGIN, imagePicker.getSelectedImages());
for (ImageItem imageItem : imagePicker.getSelectedImages()) {
LogUtils.w("onClick"+imageItem.getUploadIndex());
}
setResult(ImagePicker.RESULT_CODE_BACK, intent);
finish();
}
}
@Override
public void onBackPressed() {
Intent intent = new Intent();
// intent.putExtra(ImagePreviewActivity.ISORIGIN, isOrigin);
intent.putExtra(ImagePreviewActivity.ISORIGIN, imagePicker.getSelectedImages());
for (ImageItem imageItem : imagePicker.getSelectedImages()) {
LogUtils.w("onBackPressed"+imageItem.getUploadIndex());
}
setResult(ImagePicker.RESULT_CODE_BACK, intent);
finish();
super.onBackPressed();
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int id = buttonView.getId();
if (id == R.id.cb_origin) {
if (isChecked) {
long size = 0;
for (ImageItem item : selectedImages) {
size += item.size;
}
String fileSize = Formatter.formatFileSize(this, size);
isOrigin = true;
mCbOrigin.setText(getString(R.string.origin_size, fileSize));
} else {
isOrigin = false;
mCbOrigin.setText(getString(R.string.origin));
}
}
}
@Override
protected void onDestroy() {
imagePicker.removeOnImageSelectedListener(this);
super.onDestroy();
}
/** 单击时,隐藏头和尾 */
@Override
public void onImageSingleTap() {
if (topBar.getVisibility() == View.VISIBLE) {
topBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.top_out));
bottomBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_out));
topBar.setVisibility(View.GONE);
bottomBar.setVisibility(View.GONE);
tintManager.setStatusBarTintResource(R.color.transparent);//通知栏所需颜色
//给最外层布局加上这个属性表示,Activity全屏显示,且状态栏被隐藏覆盖掉。
// if (Build.VERSION.SDK_INT >= 16) content.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
} else {
topBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.top_in));
bottomBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_in));
topBar.setVisibility(View.VISIBLE);
bottomBar.setVisibility(View.VISIBLE);
tintManager.setStatusBarTintResource(R.color.status_bar);//通知栏所需颜色
//Activity全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态遮住
// if (Build.VERSION.SDK_INT >= 16) content.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
}
}
逻辑类似,其中有一个坑,就是我开始认为,只从所有图片对应的item中获取index即可,然后debug则会发现,出现重复的数字排序,debug才发现,再添加index只对选中的mSelectedImages做了操作,而全部itemImage没有做,所以才会有重复的问题。由于demo代码没来得及整理,后续看有没有时间添加