Android: отображать всплывающее окно динамического размера над привязкой - PullRequest
0 голосов
/ 31 октября 2019

Я пытаюсь отобразить всплывающее окно, которое будет варьироваться между размерами в зависимости от количества строк, которые оно имеет. Другими словами, я пытаюсь создать всплывающую подсказку над видом.

Однако у меня возникают проблемы с постоянным отображением всплывающей подсказки над видом привязки.

Я могу заставить его работать на один размер, используя showAtLocation, но как только он получит большестрок в тексте, который он охватывает.

Функция showAsDropDown прекрасно работает! За исключением того, что рисует всплывающую подсказку внизу, а не сверху вид. Я не могу понять, правильно ли я использую гравитацию или что-то в этом роде. Любая помощь здесь, я был бы очень признателен, я как бы застрял здесь.

Вот мой элементарный код на данный момент:

@SuppressWarnings("unused")
class SimpleTooltip : PopupWindow() {

    companion object {
        const val TAG = "SimpleTooltip"
    }

    private var popupWindow: PopupWindow? = null //The popup window the will be created in the builder.
    private var popupView: View? = null //The popup view that will inflate the popup window.
    private var focusable: Boolean? = false //dismiss PopupWindow when touch outside AND when press back button
    private var outsideTouchable: Boolean? = true // dismiss PopupWindow when touch outside
    private var drawable: Drawable? = null //The background drawable of the popup window. This is still visible even if we have a layout defined.
    private var anchorView: View? = null //The view to anchor the popup window to.
    private var gravity: Int? = null //The gravity of the popup -> where should it be displayed? Top, bottom?
    private var layout: Int? = null //The layout of the popup.
    private var xPosition: Int? = null //Move the view X amount horizontally.
    private var yPosition: Int? = null //Move the view Y amount vertically.
    private var message: String? = null //The message to be displayed.
    private var parentViewGroup: ViewGroup? = null // the parent view

    private var context: Context? = null //The context..duh

    fun withFocusableEnabled(isFocusable: Boolean) = apply { this.focusable = isFocusable }
    fun withTouchOutsideEnabled(isOutsideTouchable: Boolean) = apply { this.isOutsideTouchable = isOutsideTouchable }
    fun withContext(context: Context) = apply { this.context = context }
    fun withLayout(layout: Int) = apply { this.layout = layout }
    fun withAnchorView(anchorView: View) = apply { this.anchorView = anchorView }
    fun withGravity(gravity: Int) = apply { this.gravity = gravity }
    fun withOnDismissAction(action: () -> Unit) = apply { this.setOnDismissListener { action.invoke() } }
    fun withMessage(message: String) = apply { this.message = message }
    fun withBackgroundDrawable(drawable: Drawable?) = apply { this.drawable= drawable }
    fun withXPosition(paddingX: Int) = apply { this.xPosition = paddingX }
    fun withYPosition(paddingY: Int) = apply { this.yPosition = paddingY }
    fun withParentView(parentViewGroup: ViewGroup) = apply { this.parentViewGroup = parentViewGroup }


    fun build() = apply {
        Log.v(TAG, "Attempting to build the tooltip")
        if (context == null) throw InvalidContextProvidedException("No context provided to inflate the view. Please provide one.")
        if (layout == null) throw InvalidLayoutException("No layout provided to inflate the view. Please provide one.")

        layout?.let { layout ->
            popupView = (context?.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater).inflate(layout, parentViewGroup)
            popupWindow = PopupWindow(popupView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)

            focusable?.let { this.isFocusable = it }
            outsideTouchable?.let { this.isOutsideTouchable = it }
            drawable?.let { this.setBackgroundDrawable(it) }
            message?.let {
                val textView: TextView = popupView?.find(R.id.tooltip_layout_text_view)
                    ?: throw InvalidTextViewId("Please name the text view on your layout as \'tooltip_layout_text_view\'")
                textView.text = message
            }
        }
    }

    fun showPopup() {
        Log.v(TAG, "Attempting to show popup.")
        if (anchorView == null) throw InvalidAnchorViewException("No anchor view provided to place the popup window on. Please provide one.")
        if (popupView == null || popupWindow == null) throw InvalidStateException("The tooltip was not built. Please call the build() method.")

        gravity?.let {
            popupWindow?.showAsDropDown(anchorView, xPosition ?: 0, yPosition ?: 0, it)
        } ?: popupWindow?.showAsDropDown(anchorView, xPosition ?: 0, yPosition ?: 0)
    }

    fun dismissPopup() {
        popupWindow?.apply {
            if (isShowing) dismiss()
        }
    }

}

class InvalidAnchorViewException(message: String) : Exception(message)
class InvalidContextProvidedException(message: String) : Exception(message)
class InvalidTextViewId(message: String) : Exception(message)
class InvalidLayoutException(message: String) : Exception(message)
class InvalidStateException(message: String) : Exception(message)

И вот как я это называю:

        tooltip = SimpleTooltip()
                .withContext(this)
                .withLayout(R.layout.tooltip_layout)
                .withAnchorView(anchorView)
                .withFocusableEnabled(true)
                .withTouchOutsideEnabled(false)
                .withMessage(getPopupMessageFromDate(expiryDate))
                .withBackgroundDrawable(ColorDrawable())
                .build()
                .showPopup()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...