Skip to content

Add View.shader and move decoration Container behind the main content#6123

Open
bl1nch wants to merge 1 commit intoflet-dev:mainfrom
bl1nch:view-decoration-and-shader
Open

Add View.shader and move decoration Container behind the main content#6123
bl1nch wants to merge 1 commit intoflet-dev:mainfrom
bl1nch:view-decoration-and-shader

Conversation

@bl1nch
Copy link
Contributor

@bl1nch bl1nch commented Feb 4, 2026

Description

The View rendering order has been updated so the decoration container is moved to the background and is now rendered fully behind the main content, including foreground_decoration. This fixes issues where decorations could overlap or interfere with content rendering. In addition, a new shader property (with configurable blend_mode) is introduced to preserve the previous behavior where foreground_decoration was visually applied on top of all other content.

Fixes #6094

Test Code

# Test code for the review of this PR

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist

  • I signed the CLA.
  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • New and existing tests pass locally with my changes
  • I have made corresponding changes to the documentation (if applicable)

Summary by Sourcery

Adjust View rendering order and add shader support for applying gradient effects over view content.

New Features:

  • Add a shader gradient with configurable blend_mode to View for applying visual effects via a ShaderMask.
  • Expose shader and blend_mode properties on the Python View control API.

Enhancements:

  • Render the decoration container behind the main view content by restructuring the View layout.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've reviewed this pull request using the Sourcery rules engine

@ndonkoHenri
Copy link
Contributor

Can you please share code example to best see the effect of your addition/usecase?

@bl1nch
Copy link
Contributor Author

bl1nch commented Feb 5, 2026

# Base app
import flet as ft


async def before_main(page: ft.Page):
    container = ft.Container(
        width=500,
        height=300,
        bgcolor=ft.Colors.SURFACE_CONTAINER,
        alignment=ft.Alignment.CENTER,
        border_radius=15,
        content=ft.Text(
            value="Hello World!",
            size=26,
            weight=ft.FontWeight.W_600,
        ),
    )

    view = ft.View(
        route="/",
        bgcolor=ft.Colors.TRANSPARENT,
        vertical_alignment=ft.MainAxisAlignment.CENTER,
        horizontal_alignment=ft.CrossAxisAlignment.CENTER,
        controls=[container],
    )

    view.decoration = ft.BoxDecoration(
        image=ft.DecorationImage(
            src="https://fedoraproject.org/w/uploads/d/de/F34_default_wallpaper_night.jpg",
            fit=ft.BoxFit.COVER,
        ),
    )

    page.views.clear()
    page.views.append(view)


async def main(page: ft.Page):
    pass


ft.run(main, before_main=before_main)



# Image is rendering on top of gradient
import flet as ft


async def before_main(page: ft.Page):
    container = ft.Container(
        width=500,
        height=300,
        bgcolor=ft.Colors.SURFACE_CONTAINER,
        alignment=ft.Alignment.CENTER,
        border_radius=15,
        content=ft.Text(
            value="Hello World!",
            size=26,
            weight=ft.FontWeight.W_600,
        ),
    )

    view = ft.View(
        route="/",
        bgcolor=ft.Colors.TRANSPARENT,
        vertical_alignment=ft.MainAxisAlignment.CENTER,
        horizontal_alignment=ft.CrossAxisAlignment.CENTER,
        controls=[container],
    )

    view.decoration = ft.BoxDecoration(
        image=ft.DecorationImage(
            src="https://fedoraproject.org/w/uploads/d/de/F34_default_wallpaper_night.jpg",
            fit=ft.BoxFit.COVER,
        ),
        gradient=ft.RadialGradient(
            colors=[
                ft.Colors.TRANSPARENT,
                ft.Colors.with_opacity(0.9, ft.Colors.RED)
            ],
            stops=[0.1, 1.0],
            radius=1,
        ),
    )

    page.views.clear()
    page.views.append(view)


async def main(page: ft.Page):
    pass


ft.run(main, before_main=before_main)



# Gradient is rendering on top of main content (in current flet version)
# Main content is rendering on top of gradient (with PR)
import flet as ft


async def before_main(page: ft.Page):
    page.theme_mode = ft.ThemeMode.LIGHT

    container = ft.Container(
        width=500,
        height=300,
        bgcolor=ft.Colors.SURFACE_CONTAINER,
        alignment=ft.Alignment.CENTER,
        border_radius=15,
        content=ft.Text(
            value="Hello World!",
            size=26,
            weight=ft.FontWeight.W_600,
        ),
    )

    view = ft.View(
        route="/",
        bgcolor=ft.Colors.TRANSPARENT,
        vertical_alignment=ft.MainAxisAlignment.CENTER,
        horizontal_alignment=ft.CrossAxisAlignment.CENTER,
        controls=[container],
    )

    view.decoration = ft.BoxDecoration(
        image=ft.DecorationImage(
            src="https://fedoraproject.org/w/uploads/d/de/F34_default_wallpaper_night.jpg",
            fit=ft.BoxFit.COVER,
        ),
    )
    view.foreground_decoration = ft.BoxDecoration(
        gradient=ft.RadialGradient(
            colors=[
                ft.Colors.TRANSPARENT,
                ft.Colors.with_opacity(0.9, ft.Colors.RED)
            ],
            stops=[0.1, 1.0],
            radius=1,
        ),
    )

    page.views.clear()
    page.views.append(view)


async def main(page: ft.Page):
    pass


ft.run(main, before_main=before_main)



# Gradient is rendering on top of main content (with PR)
# (Use View.shader for previous behavior instead of View.foreground_decoration)
import flet as ft


async def before_main(page: ft.Page):
    page.theme_mode = ft.ThemeMode.LIGHT

    container = ft.Container(
        width=500,
        height=300,
        bgcolor=ft.Colors.SURFACE_CONTAINER,
        alignment=ft.Alignment.CENTER,
        border_radius=15,
        content=ft.Text(
            value="Hello World!",
            size=26,
            weight=ft.FontWeight.W_600,
        ),
    )

    view = ft.View(
        route="/",
        bgcolor=ft.Colors.TRANSPARENT,
        vertical_alignment=ft.MainAxisAlignment.CENTER,
        horizontal_alignment=ft.CrossAxisAlignment.CENTER,
        controls=[container],
    )

    view.decoration = ft.BoxDecoration(
        image=ft.DecorationImage(
            src="https://fedoraproject.org/w/uploads/d/de/F34_default_wallpaper_night.jpg",
            fit=ft.BoxFit.COVER,
        ),
    )
    view.shader = ft.RadialGradient(
        colors=[
            ft.Colors.TRANSPARENT,
            ft.Colors.with_opacity(0.9, ft.Colors.RED)
        ],
        stops=[0.1, 1.0],
        radius=1,
    )

    page.views.clear()
    page.views.append(view)


async def main(page: ft.Page):
    pass


ft.run(main, before_main=before_main)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feature: Add shader_mask property to the View class

2 participants