Макет (Cardview), перекрывающийся под строкой состояния

Я пытаюсь отображать уведомления в режиме «Карточка» с анимацией, но строка состояния закрывает его!

Я не знаю, в чем проблема. Я попробовал несколько способов решения проблемы (перечислены ниже).

Я также пытался исправить использование fromDeltaX и toDeltaX в анимации, но безрезультатно.

Вы можете увидеть изображение этого поведения:

Пробовал (не работает):

1.

ViewCompat.setOnApplyWindowInsetsListener(notificationView) { view, insets ->
            val systemInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            view.setPadding(0, systemInsets.top, 0, 0)
            insets
        }

2.

@SuppressLint("InternalInsetResource")
    private fun getStatusBarHeight(activity: Activity): Int {
        val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android")
        return if (resourceId > 0) activity.resources.getDimensionPixelSize(resourceId) else 0
    }

3.

подходитSystemWindows = истина

Мой код:

import android.app.Activity
import android.os.Handler
import android.os.Looper
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.FrameLayout
import android.widget.TextView
import androidx.cardview.widget.CardView

object NotificationUtil {

    fun showSuccessMessage(activity: Activity, message: String,autoClose: Boolean = true) {
        showNotification(activity, message, R.layout.item_success_snackbar,autoClose)
    }

    fun showErrorMessage(activity: Activity, message: String,autoClose: Boolean = true) {
        showNotification(activity, message, R.layout.item_error_snackbar,autoClose)
    }

    private fun showNotification(activity: Activity, message: String, layoutId: Int,autoClose: Boolean) {
        val decorView = activity.window.decorView as ViewGroup

        val inflater = LayoutInflater.from(activity)
        val notificationView = inflater.inflate(layoutId, null) as CardView

        val layoutParams = FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.MATCH_PARENT,
            FrameLayout.LayoutParams.WRAP_CONTENT
        ).apply {
            gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
        }

        val tvMessage: TextView = notificationView.findViewById(if (layoutId == R.layout.item_success_snackbar) R.id.tv_success_message else R.id.tv_error_message)
        val tvOk: TextView = notificationView.findViewById(if (layoutId == R.layout.item_success_snackbar) R.id.tv_success_ok else R.id.tv_error_ok)

        notificationView.layoutParams = layoutParams
        tvMessage.text = message

        notificationView.setOnClickListener {
            hideNotification(decorView, notificationView)
        }

        tvOk.setOnClickListener {
            hideNotification(decorView, notificationView)
        }

        decorView.addView(notificationView)

        val slideDown = AnimationUtils.loadAnimation(activity, R.anim.slide_down)
        notificationView.startAnimation(slideDown)

        if (autoClose) {
            Handler(Looper.getMainLooper()).postDelayed({
                hideNotification(decorView, notificationView)
            }, 3000)
        }
    }

    private fun hideNotification(decorView: ViewGroup, notificationView: View) {
        val slideUp = AnimationUtils.loadAnimation(notificationView.context, R.anim.slide_up)
        slideUp.setAnimationListener(object : Animation.AnimationListener {
            override fun onAnimationStart(animation: Animation?) {}

            override fun onAnimationEnd(animation: Animation?) {
                decorView.removeView(notificationView)
            }

            override fun onAnimationRepeat(animation: Animation?) {}
        })
        notificationView.startAnimation(slideUp)
    }
}

Мне нужно показать это под строкой состояния и сверху всех макетов. Заранее спасибо за ответы.

0
0
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы обновить верхнее поле notificationView для учета системных вставок (например, строки состояния), вы можете использовать WindowInsets API. Вот два решения: одно с использованием последней версии WindowInsets API, а другое, если у вас уже есть размер строки состояния.

Решение 1. Использование WindowInsets API

Шаг 01. Создайте метод для получения вставок окон.

Сначала создайте метод в расширении View для получения вставок окна:

import android.view.View
import androidx.core.graphics.Insets
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat

fun View.fetchWindowInsets(block: (Insets) -> Unit) {
    ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets ->
        val inset = insets.getInsets(WindowInsetsCompat.Type.systemBars())
        block.invoke(inset)
        WindowInsetsCompat.CONSUMED
    }
}

Шаг 2. Обновите метод showNotification.

Теперь обновите метод showNotification, чтобы настроить верхнее поле notificationView с помощью вставок:

Поместите этот код ниже строки notificationView.layoutParams = layoutParams

import androidx.core.view.updateMargins

notificationView.layoutParams = layoutParams
// Updated Code...
notificationView.fetchWindowInsets { inset ->
    layoutParams.updateMargins(0, inset.top, 0, 0)
}
// ...
tvMessage.text = message

Ой! Отлично, вы успешно выполнили код.


Решение 2. Использование предопределенного размера строки состояния

Если вы уже знаете размер строки состояния в пикселях, вы можете напрямую обновить верхнее поле:

— Обновите метод showNotification, добавив параметр размера строки состояния.

import androidx.core.view.updateMargins

val layoutParams = FrameLayout.LayoutParams(
    FrameLayout.LayoutParams.MATCH_PARENT,
    FrameLayout.LayoutParams.WRAP_CONTENT
).apply {
    gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
    // Updated Code...
    updateMargins(0, YOUR_STATUS_BAR_SIZE, 0, 0)
    // ...
}

Это должно помочь вам правильно настроить верхнее поле notificationView на основе системных вставок или предопределенного размера. — Спасибо.

Чем вы ** updateMargins()** сработали для меня!

Diyorbek Hamdamov 27.05.2024 08:14

Другие вопросы по теме