Dimezis / BlurView

Dynamic iOS-like blur of underlying Views for Android
Apache License 2.0
3.52k stars 334 forks source link

dynamic blur in dialog #167

Closed maximlozhechnikov closed 2 years ago

maximlozhechnikov commented 2 years ago

i need any advise to make blur working on dialog, while activity under it is scrolling `class CustomDialog(@LayoutRes private val layoutId: Int, private val title: Text?, private val message: Text?, private val cancellable: Boolean = true) : DialogFragment() {

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    return inflater.inflate(layoutId, container, false)
}

override fun onStart() {
    super.onStart()
    val width = (resources.displayMetrics.widthPixels * 0.9).toInt()
    val window = dialog!!.window
    window?.setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT)
    window?.setGravity(Gravity.TOP)
    window?.setBackgroundDrawable(ColorDrawable())
    val attributes : WindowManager.LayoutParams? = window?.attributes
    attributes?.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
    window?.attributes = attributes
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val blurView: BlurView = view.findViewById(R.id.blurview)
    val decorView = activity?.window?.decorView
    val rootView = decorView?.findViewById<ViewGroup>(android.R.id.content)
    val windowBackground = decorView?.background

    rootView?.let {
        blurView.setupWith(it)
                .setFrameClearDrawable(windowBackground)
                .setBlurAlgorithm(RenderScriptBlur(activity))
                .setBlurAutoUpdate(true)
                .setHasFixedTransformationMatrix(false)
    }
    val titleTextView = view.findViewById<TextView>(R.id.textview_dialog_title)
    titleTextView.setText(title)
    view.findViewById<TextView>(R.id.textview_dialog_message).setText(message)
    view.findViewById<ImageView>(R.id.imageview_cancel).isVisible = cancellable
    view.findViewById<ImageView>(R.id.imageview_cancel).setOnClickListener {
        dismiss()
    }
}

}

<?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="335dp" android:layout_height="wrap_content" android:background="@color/transparent" app:cardCornerRadius="12dp" app:cardElevation="0dp">

<eightbitlab.com.blurview.BlurView
        android:id="@+id/blurview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/transparent_background_red">

        <ImageView
                android:id="@+id/imageview_icon_info"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:layout_marginStart="16dp"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/ic_info"
                tools:ignore="ContentDescription" />

        <TextView
                android:id="@+id/textview_dialog_title"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="4dp"
                android:layout_marginTop="16dp"
                android:textSize="16sp"
                android:textColor="@color/black_blue"
                app:layout_constraintEnd_toStartOf="@+id/imageview_cancel"
                app:layout_constraintStart_toEndOf="@+id/imageview_icon_info"
                app:layout_constraintTop_toTopOf="parent"
                tools:text="Данный СНИЛС уже\nзарегистрирован" />

        <TextView
                android:id="@+id/textview_dialog_message"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="4dp"
                android:layout_marginTop="4dp"
                android:layout_marginBottom="16dp"
                android:lineSpacingMultiplier="1.21"
                android:textColor="@color/gray70"
                android:textSize="14sp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toStartOf="@+id/imageview_cancel"
                app:layout_constraintStart_toEndOf="@+id/imageview_icon_info"
                app:layout_constraintTop_toBottomOf="@+id/textview_dialog_title"
                tools:text="Возможно, СНИЛС введен\nнекорректно либо связан с другим\nномером телефона. Пожалуйста,\nпроверьте правильность ввода,\nавторизуйтесь с другим номером\nтелефона или обратитесь в службу\nподдержки по номеру\n8 800700-43-44." />

        <ImageView
                android:id="@+id/imageview_cancel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="12dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/ic_cancel" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</eightbitlab.com.blurview.BlurView>

</androidx.cardview.widget.CardView>`

Here is how i use blur on dialog, its all working fine but not overdrawing while activity is scrolling

maximlozhechnikov commented 2 years ago

i've tried to change setHasFixedTransformationMatrix, but it doesnt helps

chriscross12324 commented 2 years ago

Edit: This was the workaround solution that I used for my own project. The developer posted his own official solution below.

The BlurView only re-renders if the focused area has something moving in it (aka the dialog). I was able to get scrolling to work if I added a small View inside the dialog that was constantly animating (for me it was scaling), and then make the View transparent.

Dialog | --> Animating Object --> /Rest of Content/

You can choose how long to animate it for, but I chose a minute since the scrollview wouldn't be able to scroll for that long without user input.

maximlozhechnikov commented 2 years ago

@chriscross12324 thanks a lot, just placed progress bar under blur view with transparent color and all works fine

chriscross12324 commented 2 years ago

Glad it worked

Dimezis commented 2 years ago

The BlurView only re-renders if the focused area has something moving in it (aka the dialog)

That's not exactly true, but thanks for the workaround suggestion.

The fix is probably to change the ViewTreeObserver used here from blurView.getViewTreeObserver() to rootView.getViewTreeObserver()

    public BlurViewFacade setBlurAutoUpdate(final boolean enabled) {
        blurView.getViewTreeObserver().removeOnPreDrawListener(drawListener);
        if (enabled) {
            blurView.getViewTreeObserver().addOnPreDrawListener(drawListener);
        }
        return this;
    }

This way it will redraw on changes in the rootView's Window, which makes more sense and should fix this particular bug. The reason is that the Dialog has its own Window and seems like the OnPreDrawListener works per window.

chriscross12324 commented 2 years ago

Learn something new everyday. Thanks @Dimezis

Dimezis commented 2 years ago

This should be fixed in 2.0.0