Android自定义View实现多图片选择控件

Android自定义View实现多图片选择控件,第1张

概述前言相信很多朋友在开发中都会遇到图片上传的情况,尤其是多图上传,最经典的莫过于微信的图片选择了。所有很多情况下会使用到多图选择,所以就有了这篇文章,今天抽点时间写了个控件

前言

相信很多朋友在开发中都会遇到图片上传的情况,尤其是多图上传,最经典的莫过于微信的图片选择了。所有很多情况下会使用到多图选择,所以就有了这篇文章,今天抽点时间写了个控件。
 •支持自定义选择图片的样式
 •支持设置图片选择数量
 •支持图片预览,删除
 •支持图片拍照 

先来看看效果

实现分析

假如不定义控件,我们要实现这样一个功能,无非是写个GrIDVIEw在item点击的时候去显示图片进行选择,在返回界面的时候进行GrIDVIEw的数据刷新。我们把这些逻辑写在我们自定义的GrIDVIEw中,就成了一个新的控件。

1、GrIDVIEw的效果展示,逻辑实现。

public class ImagePickerVIEw extends GrIDVIEw{ //图片选择数量 int maxImageSize = 9; //添加item布局 private int noimgResource; //列选择数量 private int columnNumber = 3; Activity context; ImagesAdapter adapter; List<String> imageList;//图片选择List private static final int TYPE_SHOW_ADD = 0; private static final int TYPE_NO_SHOW_ADD = 1; private boolean isShowAdd = true; int imageGrIDSize; public voID setNoimgResource(int noimgResource) { this.noimgResource = noimgResource; } public voID setColumnNumber(int columnNumber) { if (columnNumber>5){  columnNumber = 5; } this.columnNumber = columnNumber; this.setNumColumns(columnNumber); } public voID setShowAdd(boolean showAdd) { isShowAdd = showAdd; } public voID setimageList(List<String> imageList) { this.imageList = imageList; adapter.setimageList(imageList); } public List<String> getimageList() { return imageList; } public ImagePickerVIEw(Context context) { this(context,null); } public ImagePickerVIEw(Context context,AttributeSet attrs) { this(context,attrs,0); } /** * 初始化ImagePickerVIEw的一些信息 * @param context * @param attrs * @param defStyle */ public ImagePickerVIEw(Context context,AttributeSet attrs,int defStyle) { super(context,defStyle); this.context = (Activity) context; adapter = new ImagesAdapter(); this.setAdapter(adapter); if (imageList==null){  imageList = new ArrayList<>(); } this.setNumColumns(columnNumber); this.setVerticalSpacing(10); this.setHorizontalSpacing(10); imageGrIDSize = (this.context.getwindowManager().getDefaultdisplay().getWIDth() - Util.dp2px(context,2) * 2) / columnNumber; } /** * 提供给外部调用用来再Activity返回时获取图片信息 * @param requestCode * @param resultCode * @param data */ public voID onActivityResult(int requestCode,int resultCode,Intent data) { if (data!=null&& !TextUtils.isEmpty(data.getStringExtra("photopath"))){//拍照  imageList.add(data.getStringExtra("photopath")); }else if (data!=null&&data.getSerializableExtra("images")!=null){//图片选择  imageList = (List<String>) data.getSerializableExtra("images"); }else{  List<ImageItem> List = AndroIDImagePicker.getInstance().getSelectedImages();  for (int i=0;i<List.size();i++){  imageList.add(List.get(i).path);  } } AndroIDImagePicker.getInstance().setSelectlimit(maxImageSize-imageList.size()); adapter.setimageList(imageList); } class ImagesAdapter extends BaseAdapter { List<String> imageList; public ImagesAdapter() {  this.imageList = new ArrayList(); } public voID setimageList(List<String> imageList) {  this.imageList = imageList;  notifyDataSetChanged(); } @OverrIDe public int getCount() {  if (isShowAdd){  if (imageList == null || imageList.isEmpty()) {   return 1;  }  if (imageList.size() >= maxImageSize) {   return maxImageSize;  }  return imageList.size() + 1;  }  if (imageList.size() >= maxImageSize) {  return maxImageSize;  }  return imageList.size()+1; } @OverrIDe public String getItem(int position) {  if (isShowAdd){  if (position==imageList.size()){   return null;  }  return imageList.get(position-1);  }  return imageList.get(position); } @OverrIDe public long getItemID(int position) {  return 0; } @OverrIDe public int getVIEwTypeCount() {  return 2; } @OverrIDe public int getItemVIEwType(int position) {  if (isShowAdd){  return position==imageList.size()?TYPE_SHOW_ADD:TYPE_NO_SHOW_ADD;  }else{  return TYPE_NO_SHOW_ADD;  } } @OverrIDe public VIEw getVIEw(final int position,VIEw convertVIEw,VIEwGroup parent) {  int itemVIEwType = getItemVIEwType(position);  if(itemVIEwType == TYPE_SHOW_ADD){//当前item为添加图片item  if (noimgResource!=0){//加载用户的添加item布局   convertVIEw = LayoutInflater.from(context).inflate(noimgResource,parent,false);  }else {//默认的添加item布局   convertVIEw = LayoutInflater.from(context).inflate(R.layout.grID_item_camera,false);  }  convertVIEw.setTag(null);  convertVIEw.setonClickListener(new VIEw.OnClickListener() {   @OverrIDe   public voID onClick(VIEw v) {//点击选择图片   Intent intent = new Intent(context,ImagesGrIDActivity.class);//图片选择   Activity activity = context;   activity.startActivityForResult(intent,1001);   }  });  }else{//普通item,加载图片,并对item设置点击进行预览  final VIEwHolder holder;  if(convertVIEw == null){   convertVIEw = LayoutInflater.from(context).inflate(R.layout.image_grID_item,null);   holder = new VIEwHolder();   holder.ivPic = (SimpleDraweeVIEw)convertVIEw.findVIEwByID(R.ID.iv_thumb);   holder.cbPanel = convertVIEw.findVIEwByID(R.ID.thumb_check_panel);   convertVIEw.setTag(holder);  }else{   holder = (VIEwHolder) convertVIEw.getTag();  }  convertVIEw.setonClickListener(new OnClickListener() {   @OverrIDe   public voID onClick(VIEw v) {//将选择的图片与当前postion传过去。   Intent intent = new Intent(context,PrevIEwDelActivity.class);   intent.putExtra("images",(Serializable) imageList);   intent.putExtra("position",position);   context.startActivityForResult(intent,1002);   }  });  ImageRequestBuilder requestBuilder = ImageRequestBuilder.newBuilderWithSource(   Uri.parse(String.format("file://%s",imageList.get(position))))   .setResizeOptions(new ResizeOptions(imageGrIDSize,imageGrIDSize))   .setautoRotateEnabled(true);  PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder()   .setoldController(holder.ivPic.getController())   .setimageRequest(requestBuilder.build())   .build();  holder.ivPic.setController(controller);  }  return convertVIEw; } } class VIEwHolder{ SimpleDraweeVIEw ivPic; VIEw cbPanel; }}

代码比较简单,都加了注释。在vIEw的初始化方法中获取一些信息和GrIDVIEw的展示信息,并且设置适配器关联。

在GrIDVIEw的 item中设置了点击事件,并且提供给外部用来刷新数据的onActivityResult方法。

大家看上面的代码应该就明白了。

2、图片预览和删除

这一步很简单,获取到传过来的imageList和postion对图片进行展示,在点击删除的时候remove掉imageList对应的数据,并且刷新vIEwPager

直接上代码

public class PrevIEwDelActivity extends AppCompatActivity implements VIEw.OnClickListener { private static final String TAG = ImagePrevIEwActivity.class.getSimplename(); TextVIEw mTitleCount; TextVIEw mBtnOk; private ImageVIEw backBtn; List<String> mImageList; int mShowItemposition = 0; VIEwPager mVIEwPager; touchImageAdapter mAdapter ; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_prevIEw_del); mImageList = (List<String>) getIntent().getSerializableExtra("images"); mShowItemposition = getIntent().getIntExtra("position",0); mBtnOk = (TextVIEw) findVIEwByID(R.ID.btn_del); backBtn = (ImageVIEw) findVIEwByID(R.ID.btn_backpress); mBtnOk.setonClickListener(this); backBtn.setonClickListener(this); mTitleCount = (TextVIEw) findVIEwByID(R.ID.tv_Title_count); mTitleCount.setText(mShowItemposition+1+"/" + mImageList.size());// 图片数量和当前图片信息展示 initVIEw(); AndroIDImagePicker.getInstance().clearSelectedImages(); } private voID initVIEw() { mVIEwPager = (VIEwPager)findVIEwByID(R.ID.vIEwpager); mAdapter = new touchImageAdapter(getSupportFragmentManager()); mVIEwPager.setAdapter(mAdapter); mVIEwPager.setCurrentItem(mShowItemposition,false);//设置显示当前的图片 mVIEwPager.addOnPagechangelistener(new VIEwPager.OnPagechangelistener() {  @OverrIDe  public voID onPageScrolled(int position,float positionOffset,int positionOffsetPixels) {  }  @OverrIDe  public voID onPageSelected(int position) {  mTitleCount.setText(position+1+"/" + mImageList.size());//滑动vIEwPager时更新显示信息  }  @OverrIDe  public voID onPageScrollStateChanged(int state) {  } }); } @OverrIDe public voID onClick(VIEw v) { int i = v.getID(); if (i == R.ID.btn_del) {//删除按钮点击  mAdapter.remove(mVIEwPager.getCurrentItem());//  mTitleCount.setText(mVIEwPager.getCurrentItem()+1+"/" + mImageList.size());  if (mImageList.size()==0){  Intent intent = new Intent();  intent.putExtra("images",(Serializable) mImageList);  setResult(RESulT_OK,intent);  finish();  } }else if (i==R.ID.btn_backpress){//返回  Intent intent = new Intent();  intent.putExtra("images",intent);  finish(); } } @OverrIDe public boolean onKeyDown(int keyCode,KeyEvent event) { if (keyCode==KeyEvent.KEYCODE_BACK){  Intent intent = new Intent();  intent.putExtra("images",intent);  finish();  return true; } return super.onKeyDown(keyCode,event); } class touchImageAdapter extends FragmentStatePagerAdapter { public touchImageAdapter(FragmentManager fm) {  super(fm); } @OverrIDe public int getCount() {  return mImageList.size(); } public voID remove(int position){  mImageList.remove(position);  notifyDataSetChanged(); } @OverrIDe public int getItemposition(Object object) {  return position_NONE; } @OverrIDe public Fragment getItem(int position) {  SinglePrevIEwFragment fragment = new SinglePrevIEwFragment();  Bundle bundle = new Bundle();  bundle.putSerializable(SinglePrevIEwFragment.KEY_URL,mImageList.get(position));  fragment.setArguments(bundle);  return fragment; } } @Suppresslint("ValIDFragment") private class SinglePrevIEwFragment extends Fragment { public static final String KEY_URL = "key_url"; private PhotoDraweeVIEw photoDraweeVIEw; private String url; @OverrIDe public voID onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  Bundle bundle = getArguments();  url = (String) bundle.getSerializable(KEY_URL);  Log.i(TAG,"=====current show image path:" + url);  photoDraweeVIEw = new PhotoDraweeVIEw(getActivity());  photoDraweeVIEw.setBackgroundcolor(0xff000000);  VIEwGroup.LayoutParams params = new VIEwGroup.LayoutParams(VIEwGroup.LayoutParams.MATCH_PARENT,VIEwGroup.LayoutParams.MATCH_PARENT);  photoDraweeVIEw.setLayoutParams(params);  photoDraweeVIEw.setonPhotoTapListener(new OnPhotoTapListener() {  @OverrIDe  public voID onPhotoTap(VIEw vIEw,float x,float y) {   getActivity().finish();  }  });  if (!url.startsWith("http://") && !url.startsWith("https://")) {  url = "file://"+url;  }  ImageRequestBuilder requestBuilder = ImageRequestBuilder.newBuilderWithSource(   Uri.parse(url))   .setResizeOptions(new ResizeOptions(768,1280))   .setautoRotateEnabled(true);  PipelineDraweeControllerBuilder controller = Fresco.newDraweeControllerBuilder();  controller.setoldController(photoDraweeVIEw.getController());  controller.setimageRequest(requestBuilder.build());  controller.setControllerListener(new BaseControllerListener<ImageInfo>() {  @OverrIDe  public voID onFinalimageset(String ID,ImageInfo imageInfo,Animatable animatable) {   super.onFinalimageset(ID,imageInfo,animatable);   if (imageInfo == null) {   return;   }   photoDraweeVIEw.update(imageInfo.getWIDth(),imageInfo.getHeight());  }  });  photoDraweeVIEw.setController(controller.build()); } @OverrIDe public VIEw onCreateVIEw(LayoutInflater inflater,VIEwGroup container,Bundle savedInstanceState) {  return photoDraweeVIEw; } }}

相信大家都能看懂上面代码,用VIEwPager对图片进行加载,在点击回退和删除完图片的时候把ImageList传回去。
这样在onActivityResult中获取到imageList,刷新adapter,grIDvIEw就重新渲染了。

使用

1、布局中引入ImagePickerVIEw

<?xml version="1.0" enCoding="utf-8"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:tools="http://schemas.androID.com/tools" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:paddingBottom="@dimen/activity_vertical_margin" androID:paddingleft="@dimen/activity_horizontal_margin" androID:paddingRight="@dimen/activity_horizontal_margin" androID:paddingtop="@dimen/activity_vertical_margin" androID:orIEntation="vertical" tools:context="com.qiangyu.test.imagepickervIEwdemo.MainActivity"> <com.redare.imagepicker.Widget.ImagePickerVIEw androID:ID="@+ID/imagePicker" androID:layout_wIDth="match_parent" androID:layout_height="wrap_content"> </com.redare.imagepicker.Widget.ImagePickerVIEw> <button androID:ID="@+ID/commit_btn" androID:layout_wIDth="match_parent" androID:layout_height="wrap_content" androID:text="提交"/></linearLayout>

2、在Activity中获得ImagePickerVIEw,并且在onActivityResult方法中调用ImagePickerVIEw数据刷新方法
imagePicker.onActivityResult(requestCode,resultCode,data);

3、获取选择图片的路径
调用imagePicker.getimageList()即返回图片选择的List

下面是一段代码示例

public class MainActivity extends AppCompatActivity { private ImagePickerVIEw imagePicker; private button commitBtn; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); Fresco.initialize(this); imagePicker = (ImagePickerVIEw) findVIEwByID(R.ID.imagePicker); commitBtn = (button) findVIEwByID(R.ID.commit_btn); commitBtn.setonClickListener(new VIEw.OnClickListener() {  @OverrIDe  public voID onClick(VIEw v) {  for (int i=0;i<imagePicker.getimageList().size();i++){   Log.d("yqy",imagePicker.getimageList().get(i));  }  } }); imagePicker.setNoimgResource(R.layout.add_img);//自定义imagePicker add item样式 imagePicker.setColumnNumber(5);//设置显示5列 } @OverrIDe protected voID onActivityResult(int requestCode,Intent data) { imagePicker.onActivityResult(requestCode,data); }}

结语

看了ImagePickerVIEw的实现,是不是发现一个自定义控件其实也很简单。在我们做自定义控件的时候,其实大部分情况只是在AndroID系统提供的功能上多加一点我们的需求而已。站在巨人的肩膀上,才可以看的更远嘛。

关于图片加载和图片选择本文没有提及,图片加载我参考了文章,感兴趣的朋友可以去github查看,https://github.com/easonline/AndroidImagePicker。我在自己的Demo中对源码做了修改,并统一使用了Fresco加载图片。

有需要参考源码的同学请参考:源码下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的Android自定义View实现多图片选择控件全部内容,希望文章能够帮你解决Android自定义View实现多图片选择控件所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1148617.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-31
下一篇2022-05-31

发表评论

登录后才能评论

评论列表(0条)

    保存