Android圖片上傳九宮格(添加,刪除,預覽)
越來越多的功能需要圖片上傳,所以封裝了一個圖片選取,展示的九宮格控件.包含了添加,刪除,以及預覽(為方便自定義,預覽只提供點擊方式外部自定義預覽實現(xiàn))的功能,如圖所示:

思路:
自定義ViewGroup 包含RecycleView 實現(xiàn)九宮格
自定義屬性 設置展示的行數(shù),最大添加的個數(shù)設置AddItem 圖片的展示樣式,以及設置關閉按鈕和錯誤頁展示的央視
利用RecycleView 的 GridLayoutManager 設置九宮格展示
根據(jù)邏輯需要在RecyclerView.Adapter中動態(tài)添加圖片和Add頁面的兩種不同他的Item
根據(jù)添加數(shù)據(jù)有沒有AddItem類型動態(tài)處理數(shù)據(jù)
實現(xiàn):
1.attrs.xml自定義屬性
2.九宮格RecycleView的Adapter
class AddImagesAdapter(mContext: Context,limtNum: Int,addImgs: Int,addCloseImgs: Int,addErrImgs: Int,addLimitNums: Int) :RecyclerView.Adapter() { var mContext: Contextvar limtNum = 5var addImgs = -1var addCloseImgs = -1var addErrImgs = -1var addLimitNums = 9var addImages = ArrayList() init {this.mContext = mContextthis.limtNum = limtNumthis.addCloseImgs = addCloseImgsthis.addImgs = addImgsthis.addErrImgs = addErrImgsthis.addLimitNums = addLimitNums}var listener: OnAddClickListener? = nullfun setOnAddListener(listener: OnAddClickListener) {this.listener = listener}fun getHeight(): Int {return (getScreenWidth(mContext)) / 5}private fun dip2px(context: Context, dp: Int): Int {val density = context.resources.displayMetrics.densityreturn (dp * density + 0.5).toInt()}private fun getScreenWidth(context: Context): Int {val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManagerval outMetrics = DisplayMetrics()wm.defaultDisplay.getMetrics(outMetrics)return outMetrics.widthPixels}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {var viedataBinding: ItemAddImagesBinding =DataBindingUtil.inflate(LayoutInflater.from(mContext),R.layout.item_add_images,parent,false)var layout = RelativeLayout.LayoutParams(getHeight(), getHeight())layout.setMargins(dip2px(mContext,1), dip2px(mContext,1), dip2px(mContext,1), dip2px(mContext,1))viedataBinding.root.layoutParams = layoutvar dataBindingViewHolder: AddImagesViewHolder = AddImagesViewHolder(viedataBinding.root)dataBindingViewHolder.setBinding(viewBinding = viedataBinding)return dataBindingViewHolder}override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {var ktHolder = holder as? AddImagesViewHoldervar binding = ktHolder!!.getBinding() as ItemAddImagesBindingktHolder?.getBinding()?.executePendingBindings()if (addImgs!=-1){binding!!.ivAdd.setBackgroundResource(addImgs)}else{binding!!.ivAdd.setBackgroundResource(R.drawable.iv_add_images_add)}if (addCloseImgs!=-1){binding!!.ivClose.setBackgroundResource(addCloseImgs)}else{binding!!.ivClose.setBackgroundResource(R.drawable.iv_add_img_close)}binding.rlClose.setOnClickListener {processDelete(getItem(position))}binding.rlAdd.setOnClickListener {if (listener != null) listener!!.onAddClick(binding.rlAdd, getItem(position))}binding.ivContent.setOnClickListener {if (listener != null) listener!!.onAddClick(binding.ivContent, getItem(position))}if (getItem(position)!!.type.equals("2")) {binding.ivContent.visibility = View.VISIBLEbinding.rlClose.visibility = View.VISIBLEbinding.rlAdd.visibility = View.GONEif (addErrImgs!=-1){var requestOptions= RequestOptions().error(addErrImgs)Glide.with(mContext).load(getItem(position)!!.imgUrl).apply(requestOptions).into(binding.ivContent)}else{var requestOptions= RequestOptions().error(R.drawable.iv_add_err)Glide.with(mContext).load(getItem(position)!!.imgUrl).apply(requestOptions).into(binding.ivContent)}} else {binding.ivContent.visibility = View.GONEbinding.rlAdd.visibility = View.VISIBLEbinding.rlClose.visibility = View.GONE}}private fun processDelete(item: AddImagesInfo?) {addImages.remove(item)if (!hasAdd()) {addItem(AddImagesInfo(R.drawable.iv_add_images_add, "1"))} else {notifyDataSetChanged()????????}}fun addItems(lists: List) { processData(lists)}fun addItem(info: AddImagesInfo) {addImages.add(info)notifyDataSetChanged()}fun getItems(): ArrayList? { if (this.addImages == null) this.addImages = ArrayList()return this.addImages}private fun processData(addDatas: List) { if (addDatas == null) returnvar newList = processEnd(getItems()!!)if (newList.size >= limtNum) returnif (newList!!.size + addDatas.size < addLimitNums) {newList!!.addAll(addDatas)newList!!.add(AddImagesInfo("", "1"))} else {newList!!.addAll(addDatas.subList(0, addLimitNums - newList.size))}????????notifyDataSetChanged()}private fun processEnd(addDatas: ArrayList): ArrayList { if (addDatas == null) return addDatasvar iterator = addDatas.iterator()while (iterator.hasNext()) {var info = iterator.next()if (info.type.equals("1")) iterator.remove()}return addDatas}private fun hasAdd(): Boolean {getItems()!!.forEach {if (it.type.equals("1")) {return true}}return false????}override fun getItemCount(): Int {return addImages.size}fun getItem(position: Int): AddImagesInfo? {if (addImages != null && position < addImages!!.size) {return this.addImages!!.get(position)}return null}interface OnAddClickListener {fun onAddClick(view: View?, item: AddImagesInfo?)}}
3.自定義ViewGroup
class AddImagesView constructor(mContext: Context,attrs: AttributeSet? = null,defStyleAttr: Int = 0) : FrameLayout(mContext, attrs, defStyleAttr) {private var mContext: Context// 添加的圖片資源private var addImgs = -1//關閉的圖片資源private var addCloseImgs = -1//錯誤頁的圖片資源private var addErrImgs = -1//列數(shù)private var columnNums = 5//最大圖片數(shù)private var add_limit_nums = 9private var mAdapter: AddImagesAdapter? = nullinit {this.mContext = mContextval tapeArray = mContext.obtainStyledAttributes(attrs, R.styleable.AddImagesStyle)addImgs = tapeArray.getResourceId(R.styleable.AddImagesStyle_add_imgs, -1)addCloseImgs = tapeArray.getResourceId(R.styleable.AddImagesStyle_add_close_imgs, -1)addErrImgs = tapeArray.getResourceId(R.styleable.AddImagesStyle_add_err_imgs, -1)columnNums = tapeArray.getInt(R.styleable.AddImagesStyle_column_nums, 5)add_limit_nums = tapeArray.getInt(R.styleable.AddImagesStyle_add_limit_nums, 9)initView()}var listener: AddImagesViewListener? = nullfun setAddImagesViewListener(listener: AddImagesViewListener) {this.listener = listener}//初始換數(shù)據(jù)private fun initView() {var binding = DataBindingUtil.inflate( LayoutInflater.from(mContext),R.layout.layout_add_images,this,false)addView(binding.root)if (columnNums>5)columnNums=5binding.rvContent.layoutManager = GridLayoutManager(mContext, columnNums)mAdapter = AddImagesAdapter(mContext, columnNums,addImgs,addCloseImgs,addErrImgs,add_limit_nums)binding.rvContent.adapter = mAdaptermAdapter!!.addItem(AddImagesInfo("", "1"))mAdapter!!.setOnAddListener(object : AddImagesAdapter.OnAddClickListener {override fun onAddClick(view: View?, item: AddImagesInfo?) {when (view!!.id) {R.id.rl_add -> {if (listener!=null)listener!!.onAdd()}R.id.iv_content -> {if (listener!=null)listener!!.onPreview(item,mAdapter!!.getItems())}}}})}//添加數(shù)據(jù)fun addAddImages(lists: List<AddImagesInfo>) {mAdapter!!.addItems(lists)}interface AddImagesViewListener {fun onAdd()fun onPreview(item:AddImagesInfo?,lists: List<AddImagesInfo>?)}}
總結(jié):
自定義ViewGroup 中間的布局可以設置成動態(tài)添加RecycleView,圖片預覽功能可以根據(jù)項目需要封裝在庫中,在此沒做單獨設置(需要封裝通用傳遞的數(shù)據(jù)),用到的小伙伴可以根據(jù)自己需要再單獨擴展。
源碼地址:
https://github.com/wukuiqing49/AddImageViews
到這里就結(jié)束啦。
評論
圖片
表情
