如何在RecyclerView中处理链接到某些卡的视图持有人?

时间:2018-06-21 12:34:12

标签: android android-recyclerview recycler-adapter android-viewholder

我正在开发一个Android项目,该项目中我想通过向右或向左滑动项目来从垂直回收器视图中删除该项目。至于删除项目,我能够正确地做到这一点。我删除项目并致电notifyDataSetChanged().

之后,就会出现此问题

现在,在刷新项目时,适配器使用以前的视图支架显示卡。但是在删除项目时,我将其某些布局向左和向右移动。因此,当新项目占据相同的视图持有者时,所有翻译都将保留并  因此,会在屏幕范围之外创建新项目的某些视图(当我在删除占据该位置的前一个项目的同时删除了该视图持有者时)。

所以我的问题是(以下任一解决方案都可以解决我面临的问题)

  
      
  1. Java中是否有像c ++这样的“免费”功能?这样我就可以释放该视图持有者。
  2.   
  3. 如何确保回收者视图不会重复使用特定的视图持有者?
  4.   
  5. 如何在完成所有动画之前将的布局重置为原始状态?这样我就可以重置所有翻译
  6.   

谢谢。

编辑:

下面是适配器和视图持有者的代码,如果有人想看一看的话。 由于视图持有者太大而无法直接理解,因此这里使用的功能太过复杂了:

  
      
  1. init->只需在点击监听器上进行设置。
  2.   
  3. updateUI->设置更多的侦听器,并设置card中的文本和其他字段。
  4.   
  5. pressDown->在MotionEvent.ACTION_DOWN时调用。
  6.   
  7. pressUP->在MotionEvent.ACTION_UP时调用。
  8.   
  9. animateViewDisappear->动画的侦听器。
  10.   
  11. 存档->删除元素并告知适配器数据已更改。
  12.   
  13. pressMove->点击按钮后何时发生运动。
  14.   
  15. toggleShowHideView->更改某些视图的可见性。
  16.   
  17. closeOpenedLayout->关闭一些展开的布局。
  18.   

适配器:

class LocalAdapter(var localCardsInfo : ArrayList<LocalModel>?,var fragment: LocalListingFragment) : RecyclerView.Adapter<LocalHolder>() {

    fun refreshDataOnOrientationChange(mLocalCards : ArrayList<LocalModel>?){
        if (localCardsInfo!!.size>0)
            localCardsInfo!!.clear()
        localCardsInfo = mLocalCards
        notifyDataSetChanged()
    }

    override fun getItemCount(): Int {
        return localCardsInfo!!.size
    }

    override fun onBindViewHolder(holder: LocalHolder, position: Int) {
        if (localCardsInfo!=null)
            holder.updateUI(position,localCardsInfo!![position])
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocalHolder {
        val card_a : View = LayoutInflater.from(parent.context).inflate(R.layout.card_local_a,parent,false)
        return LocalHolder(card_a,fragment)
    }

}

观看者:

class LocalHolder(itemView : View,val fragment: LocalListingFragment) : RecyclerView.ViewHolder(itemView),OpenedLayoutManagerLocal{

    private val TAG = "iotcontrollerapp.@Debug"
    private var _xDelta: Float = 0f
    private var originalDelta : Float = 0f
    private var directionOut1 = false
    private var directionOut = false
    private var previousX = 0f

    var isFavourite : Boolean = false
    var isPropertyPanelOpen : Boolean = false

    val deviceName : TextView = itemView.findViewById(R.id.deviceNameLocal)
    val deviceRoom : TextView = itemView.findViewById(R.id.deviceRoomLocal)
    val deviceOnOff : TextView = itemView.findViewById(R.id.deviceOnOffLocal)

    val showHideLayout : LinearLayout = itemView.findViewById(R.id.showHideLayoutLocal)
    val showHideProperties : TextView = itemView.findViewById(R.id.showHidePropertiesLocal)
    val showHideButton : ImageView = itemView.findViewById(R.id.showHideButtonLocal)

    val favouriteButton : ImageButton = itemView.findViewById(R.id.imageFavouriteButtonLocal)
    val moveButton : MoveableViewImageButton = itemView.findViewById(R.id.imageMoveButtonLocal)

    val changeFragmentToDetail : Button = itemView.findViewById(R.id.changePropertiesLocal)

    val layoutForProperties : LinearLayout = itemView.findViewById(R.id.layoutForPropertyLocal)
    val baseForProperties : LinearLayout = itemView.findViewById(R.id.baseForPropertyLocal)
    private var model : LocalModel? = null
    init {
        itemView.elevation = 0f
        showHideLayout.setOnClickListener({

            isPropertyPanelOpen = !isPropertyPanelOpen
            if (isPropertyPanelOpen){
                if (openedLayoutManagerLocal != this)
                    openedLayoutManagerLocal?.closeOpenedLayout()
                openedLayoutManagerLocal = this
                showHideProperties.text = fragment.getString(R.string.close_property_panel)
                showHideButton.setImageResource(R.drawable.animated_more_button_local)
            }
            else{
                showHideProperties.text = fragment.getString(R.string.open_property_panel)
                showHideButton.setImageResource(R.drawable.animated_more_button_reverse_local)
            }
            val mDrawable = showHideButton.drawable
            if (mDrawable is Animatable)
            {
                (mDrawable as Animatable).start()
            }
            toggleShowHideView()
        })
    }

    fun changeFavouriteButtonState(localModel: LocalModel){
        isFavourite = !isFavourite
        if (isFavourite){
            favouriteButton.setImageResource(R.drawable.avd_heart_fill)
            val a = favouriteButton.drawable
            if(a is Animatable){
                a.start()
            }
            ALL_STATIC_CONSTANTS_AND_METHODS.saveIsFavourite(fragment.activity as Context,localModel.roomName.trim() + "$" + localModel.deviceName,true)
        }
        else{
            favouriteButton.setImageResource(R.drawable.avd_heart_break)
            val a = favouriteButton.drawable
            if(a is Animatable){
                a.start()
            }
            ALL_STATIC_CONSTANTS_AND_METHODS.saveIsFavourite(fragment.activity as Context,localModel.roomName.trim() + "$" + localModel.deviceName,false)
        }
    }

    fun updateUI(position : Int , localModel: LocalModel){
        itemView.elevateLayoutLocal.visibility = View.VISIBLE
        itemView.archiveLayout.visibility = View.VISIBLE

        model = localModel
        originalDelta = itemView.elevateLayoutLocal.x
        changeFragmentToDetail.setOnClickListener({
            fragment.handlerForDetail.sendEmptyMessage(position)
        })
        favouriteButton.setOnClickListener({
            changeFavouriteButtonState(localModel)
        })
        moveButton.setOnTouchListener({v: View?, event: MotionEvent? ->
            if (v == null || event == null) return@setOnTouchListener true
            when (event.action){
                MotionEvent.ACTION_UP -> {
                    v.performClick()
                    pressUP(v,event)
                }
                MotionEvent.ACTION_DOWN -> {
                    pressDown(v,event)
                }
                MotionEvent.ACTION_MOVE -> {
                    pressMove(v,event)
                }
                else -> {
                    Log.e(TAG,"Something happened")
                }
            }
            return@setOnTouchListener true
        })
        isFavourite = (ALL_STATIC_CONSTANTS_AND_METHODS.getIsFavourite(fragment.activity as Context,localModel.roomName.trim() + "$" + localModel.deviceName) ?: false)

        favouriteButton.setImageResource(if (isFavourite) R.drawable.vd_trimclip_heart_full else R.drawable.vd_trimclip_heart_empty)

        deviceRoom.text = localModel.roomName.split("_").dropLast(1).toTypedArray().joinToString(" ")
        deviceName.text = localModel.deviceName.split("_").dropLast(1).toTypedArray().joinToString(" ")
        deviceOnOff.text = if (localModel.isON) fragment.getString(R.string.device_on_off_on) else fragment.getString(R.string.device_on_off_off)

        val components = localModel.componentName.split(" ")
        val value = localModel.value.split(" ")
        val maxValue = localModel.maxValue.split(" ")
        val minValue = localModel.minValue.split(" ")
        if (layoutForProperties.childCount > 0)
            layoutForProperties.removeAllViews()
        if (components.size == value.size && minValue.size == maxValue.size && components.size == minValue.size){
            for (i in 0 until components.size){
                val layout : LinearLayout = LinearLayout.inflate(fragment.activity , R.layout.card_local_b , null) as LinearLayout
                layout.findViewById<TextView>(R.id.propertyLocal).text = components[i].replace("_"," ")
                layout.findViewById<TextView>(R.id.valueLocal).text = value[i]
                layout.findViewById<TextView>(R.id.rangeLocal).text = minValue[i] + " to " + maxValue[i]
                layoutForProperties.addView(layout)
            }

        }

    }

    private fun pressDown(imageButton: View, event: MotionEvent){
        fragment.mLayoutManager?.setScrollEnabled(false)
        openedLayoutManagerLocal?.closeOpenedLayout()
        _xDelta = itemView.elevateLayoutLocal.x - event.rawX
    }

    private fun pressUP(imageButton: View, event: MotionEvent){

        Log.e(TAG,"itemView.elevateLayoutLocal.x :: ${(itemView.elevateLayoutLocal.width / 3.toFloat()) - itemView.elevateLayoutLocal.x}")
        val status = (itemView.elevateLayoutLocal.width / 3.toFloat()) < itemView.elevateLayoutLocal.x
        val status1 = (itemView.elevateLayoutLocal.width / 2.toFloat()) < itemView.elevateLayoutLocal.x
        itemView.elevateLayoutLocal.animate()
                .x(if ((directionOut && status) || (status1 && directionOut1)) itemView.elevateLayoutLocal.width.toFloat() else originalDelta)
                .setDuration(100)
                .setListener(object : Animator.AnimatorListener{
                    override fun onAnimationCancel(animation: Animator?) {
                        if ((directionOut && status) || (status1 && directionOut1)) {
                            itemView.elevateLayoutLocal.visibility = View.GONE
                            val anim = ValueAnimator.ofInt(itemView.archiveLayout.measuredHeight, 0)
                            anim.addUpdateListener { valueAnimator ->
                                val `val` = valueAnimator.animatedValue as Int
                                val layoutParams = itemView.archiveLayout.layoutParams
                                layoutParams.height = `val`
                                itemView.archiveLayout.layoutParams = layoutParams
                            }
                            anim.addListener(animateViewDisappear(this@LocalHolder))
                            anim.duration = 1000
                            anim.start()
                        }else{
                            fragment.mLayoutManager?.setScrollEnabled(true)
                        }
                    }

                    override fun onAnimationEnd(animation: Animator?) {
                        if ((directionOut && status) || (status1 && directionOut1)) {
                            itemView.elevateLayoutLocal.visibility = View.GONE
                            val anim = ValueAnimator.ofInt(itemView.archiveLayout.measuredHeight, 0)
                            anim.addUpdateListener { valueAnimator ->
                                val `val` = valueAnimator.animatedValue as Int
                                val layoutParams = itemView.archiveLayout.layoutParams
                                layoutParams.height = `val`
                                itemView.archiveLayout.layoutParams = layoutParams
                            }
                            anim.addListener(animateViewDisappear(this@LocalHolder))
                            anim.duration = 1000
                            anim.start()
                        }else{
                            fragment.mLayoutManager?.setScrollEnabled(true)
                        }
                    }

                    override fun onAnimationRepeat(animation: Animator?) {

                    }

                    override fun onAnimationStart(animation: Animator?) {

                    }
                }).start()
    }

    class animateViewDisappear(var i : LocalHolder) :Animator.AnimatorListener {
        override fun onAnimationCancel(animation: Animator?) {
            i.itemView.archiveLayout.visibility = View.GONE
            i.itemView.elevateLayoutLocal.visibility = View.GONE
            i.itemView.elevateLayoutLocal.x = i.originalDelta
            val layoutParams = i.itemView.archiveLayout.layoutParams
            layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT
            i.itemView.archiveLayout.layoutParams = layoutParams
            i.archived()
        }
        override fun onAnimationEnd(animation: Animator?) {
            i.itemView.archiveLayout.visibility = View.GONE
            i.itemView.elevateLayoutLocal.visibility = View.GONE
            i.itemView.elevateLayoutLocal.x = i.originalDelta
            val layoutParams = i.itemView.archiveLayout.layoutParams
            layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT
            i.itemView.archiveLayout.layoutParams = layoutParams
            i.archived()
        }
        override fun onAnimationRepeat(animation: Animator?) {

        }
        override fun onAnimationStart(animation: Animator?) {

        }

    }

    private fun archived(){
        fragment.mLayoutManager?.setScrollEnabled(true)
        if (model != null) {
            ALL_STATIC_CONSTANTS_AND_METHODS.addToArchive(fragment.activity!!, model!!.roomName, model!!.deviceName)
            fragment.mAdapter?.refreshDataOnOrientationChange(LocalDataService.ourInstance.getNonArchivedItems(fragment.activity!!))
        }

    }


    private fun pressMove(imageButton: View, event: MotionEvent){
        directionOut1 = itemView.elevateLayoutLocal.x >= (previousX)
        directionOut = itemView.elevateLayoutLocal.x >= (previousX + 20)
        previousX = itemView.elevateLayoutLocal.x
        fragment.mLayoutManager?.setScrollEnabled(false)
        itemView.elevateLayoutLocal.animate()
                .x(event.rawX + _xDelta)
                .setDuration(0)
                .start()
    }

    fun toggleShowHideView(){
        changeFragmentToDetail.visibility = if (isPropertyPanelOpen) View.VISIBLE else View.GONE
        layoutForProperties.visibility = if (isPropertyPanelOpen) View.VISIBLE else View.GONE
        baseForProperties.visibility = if (isPropertyPanelOpen) View.VISIBLE else View.GONE
    }

    override fun closeOpenedLayout() {
        if (isPropertyPanelOpen){
            isPropertyPanelOpen = !isPropertyPanelOpen
            showHideProperties.text = fragment.getString(R.string.open_property_panel)
            showHideButton.setImageResource(R.drawable.animated_more_button_reverse_local)
            val mDrawable = showHideButton.drawable
            if (mDrawable is Animatable)
            {
                (mDrawable as Animatable).start()
            }
            toggleShowHideView()
        }
    }

    companion object {
        var openedLayoutManagerLocal : OpenedLayoutManagerLocal? = null
    }

}

0 个答案:

没有答案