如何关闭自定义弹出窗口

问题描述

我遇到了弹出窗口和拖放问题。我想关闭弹出窗口并在将视图拖动到另一个视图时显示一个新窗口。我可以创建一个新的弹出窗口,但不能关闭旧的。我怎么解决这个问题?这总是会创建一个新的。

调用组件dismiss方法可以但是不能dismiss。

`
class SubstitutionPopUpComponent @JvmOverloads constructor(
    context: Context,attrs: AttributeSet? = null,defStyleAttr: Int = 0,) : PopupWindow(context,attrs,defStyleAttr) {
    val binding: ComponentPlayerSubstitutionPopupBinding = DataBindingUtil.inflate(
        LayoutInflater.from(context),R.layout.component_player_substitution_popup,null,false
    )

fun createPopup(
    view: View,playerInName: String,playerOutName: String,): PopupWindow {
    binding.apply {
        this.playerInName = playerInName
        this.playerOutName = playerOutName
    }
    val x = view.getScreenLocation()[0]
    val y = view.getScreenLocation()[1]

    return PopupWindow(
        binding.root,ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT
    ).apply {
        isOutsidetouchable = true
        isFocusable = true
        elevation = 10f
        setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        showAtLocation(view,Gravity.NO_GraviTY,x + view.width,y)
    }
}

fun dismisspopup() {
    dismiss()
}

}`

internal class MyDragListener(ctx: Context,popUpComponent: SubstitutionPopUpComponent?) :
        OnDragListener {
        val context = ctx
        val substitutionPopUpComponent = popUpComponent
        override fun onDrag(target: View,event: DragEvent): Boolean {
            when (event.action) {
                DragEvent.ACTION_DROP -> {
                    if (substitutionPopUpComponent.isNotNull()) {
                        substitutionPopUpComponent?.dismisspopup()
                    }

                    val dragged = event.localState as View
                    val oldplayer = dragged.parent as ViewGroup
                    val newPlayer = target.parent as ViewGroup

                    when {
                        (oldplayer as squadPlayerComponent).binding.player != null -> {
                            when ((newPlayer as squadPlayerComponent).playerPosition) {
                                oldplayer.playerPosition -> {
                                    if (oldplayer.binding.player != null && newPlayer.binding.player != null) {
                                        Utils.swapPlayers(
                                            oldplayer.binding.player!!,newPlayer.binding.player!!,oldplayer.isSubPlayer,newPlayer.isSubPlayer,newPlayer.playerPosition.toString()
                                        )
                                    }
                                }
                            }
                        }
                    }
                }
                DragEvent.ACTION_DRAG_ENTERED -> {
                    val dragged = event.localState as View
                    val oldplayer = dragged.parent as ViewGroup
                    val newPlayer = target.parent as ViewGroup

                    substitutionPopUpComponent?.apply {
                        createPopup(oldplayer,(newPlayer as squadPlayerComponent).binding.player?.name.toString(),(oldplayer as squadPlayerComponent).binding.player?.name.toString()
                        )
                    }
                }

                DragEvent.ACTION_DRAG_EXITED -> {
                    if (substitutionPopUpComponent.isNotNull()) {
                        substitutionPopUpComponent?.dismisspopup()
                    }
                }
            }
            return true
        }
    }

解决方法

看起来自 android api 级别 24 以来,视图具有方法 updateDragShadow,它更新正在进行的拖放操作的拖动阴影。也就是说,您可以将 DragShadowBuilder 的新实例传递给您的 DragListener 中的 target.updateDragShadow(emptyDragShadowBuilder),该实例将是透明的或不绘制任何内容,您就可以获得所需的内容。

我不确定,但我认为你可以在没有 updateDragShadow 的情况下做同样的事情: 当您调用 startDragAndDrop 方法时,您可以使用视图对象传递 DragShadowBuilder 的实例。考虑实施 DragShadowBuilder.onDrawShadow:

public void onDrawShadow(Canvas canvas) {
            final View view = mView.get();
            if (view != null) {
                view.draw(canvas);
            } else {
                Log.e(View.VIEW_LOG_TAG,"Asked to draw drag shadow but no view");
            }
        }

看起来您可以更改传递给 DragShadowBuilder 的视图并在此视图上调用无效。或者您可以扩展将缓存画布的 DragShadowBuilder,然后在更改视图后调用 onDrawShadow() 将使用缓存的画布:

public void onDrawShadow(Canvas canvas) {
            mCanvas = canvas;
            onDrawShadow();
        }

public void onDrawShadow() {
            final View view = mView.get();
            if (view != null && mCanvas != null) {
                view.draw(mCanvas);
            } else {
                Log.e(View.VIEW_LOG_TAG,"Asked to draw drag shadow but no view");
            }
        }