我正在开发一个Android项目,该项目中我想通过向右或向左滑动项目来从垂直回收器视图中删除该项目。至于删除项目,我能够正确地做到这一点。我删除项目并致电notifyDataSetChanged().
现在,在刷新项目时,适配器使用以前的视图支架显示卡。但是在删除项目时,我将其某些布局向左和向右移动。因此,当新项目占据相同的视图持有者时,所有翻译都将保留并 因此,会在屏幕范围之外创建新项目的某些视图(当我在删除占据该位置的前一个项目的同时删除了该视图持有者时)。
所以我的问题是(以下任一解决方案都可以解决我面临的问题)
- Java中是否有像c ++这样的“免费”功能?这样我就可以释放该视图持有者。
- 如何确保回收者视图不会重复使用特定的视图持有者?
- 如何在完成所有动画之前将的布局重置为原始状态?这样我就可以重置所有翻译
谢谢。
编辑:
下面是适配器和视图持有者的代码,如果有人想看一看的话。 由于视图持有者太大而无法直接理解,因此这里使用的功能太过复杂了:
- init->只需在点击监听器上进行设置。
- updateUI->设置更多的侦听器,并设置card中的文本和其他字段。
- pressDown->在MotionEvent.ACTION_DOWN时调用。
- pressUP->在MotionEvent.ACTION_UP时调用。
- animateViewDisappear->动画的侦听器。
- 存档->删除元素并告知适配器数据已更改。
- pressMove->点击按钮后何时发生运动。
- toggleShowHideView->更改某些视图的可见性。
- closeOpenedLayout->关闭一些展开的布局。
适配器:
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
}
}