Skip to content

Adopt DensityValue in Grid to Enable Precise Pixel-Aware Layout & Fixed label cropping inside the border control with a specific padding value on certain Android devices#30340

Closed
NanthiniMahalingam wants to merge 119 commits into
dotnet:mainfrom
NanthiniMahalingam:Fix-28117

Conversation

@NanthiniMahalingam
Copy link
Copy Markdown
Contributor

@NanthiniMahalingam NanthiniMahalingam commented Jul 1, 2025

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Description of Change

  1. DensityValue Struct
    Introduces an internal DensityValue struct that tracks both dp and pixel values:

internal readonly struct DensityValue
{
public double Dp => RawPx / Density;
public double Density { get; }
public double RawPx { get; }

// Distributes pixels with error accumulation like Android
public static int[] DistributePixels(double totalPixels, double density, double[] portions)

}

  1. Enhanced Grid Layout
    Modifies GridLayoutManager.ResolveStars() to use density-aware distribution when available, falling back to the original algorithm when density information is unavailable.

  2. Pixel-Perfect Distribution
    The DistributePixels method implements Android's approach of accumulating rounding errors and assigning remainder pixels to the final elements:

// 293.4dp × 2.625 density = 770.175px across 3 equal columns
// Result: [256, 257, 257] pixels (total: 770px) ✓
// Instead of: [257, 257, 257] pixels (total: 771px)

  1. Calculating the pixel
    To eliminate the pixel difference, the frame's right value was calculated as the sum of the frame's left value and width, while the frame's bottom value was calculated as the sum of the frame's top value and height in the ToPixels conversion method within ContextExtensions.

Issues Fixed

Fixes #28117
Fixes #30017

Output

Android platform

Before After
image image

@dotnet-policy-service dotnet-policy-service Bot added community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration labels Jul 1, 2025
@jsuarezruiz jsuarezruiz added area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter layout-grid labels Jul 1, 2025
@NanthiniMahalingam NanthiniMahalingam marked this pull request as ready for review July 18, 2025 14:23
Copilot AI review requested due to automatic review settings July 18, 2025 14:23
@NanthiniMahalingam NanthiniMahalingam requested a review from a team as a code owner July 18, 2025 14:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR introduces density-aware layout calculations to the Grid layout system to fix pixel precision issues that cause text cropping in border controls on Android devices. The changes implement an internal DensityValue struct that tracks both dp and pixel values, enabling precise pixel-perfect distribution following Android's rounding error accumulation approach.

Key Changes:

  • Added DensityValue struct for density-aware calculations with pixel-perfect distribution
  • Modified Grid layout to use density-aware distribution when available, falling back to original algorithm when not
  • Fixed Android pixel calculation to use width/height instead of right/bottom coordinates to eliminate rounding errors

Reviewed Changes

Copilot reviewed 11 out of 32 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/Core/src/Layouts/DensityValue.cs New struct for tracking dp/pixel values with distribution algorithm
src/Core/src/Layouts/GridLayoutManager.cs Modified to use DensityValue for precise star column distribution
src/Core/src/Platform/Android/ContextExtensions.cs Fixed ToPixels method to calculate right/bottom from left/top + width/height
src/Core/src/IViewWithWindow.cs New interface for views to provide window access
src/Core/src/Platform/ElementExtensions.cs Enhanced GetWindow method to use IViewWithWindow interface
src/Controls/src/Core/View/View.cs Implemented IViewWithWindow interface
src/Core/tests/UnitTests/Layouts/GridLayoutManagerDensityTest.cs Comprehensive tests for density-aware pixel distribution
src/Controls/tests/TestCases.HostApp/Issues/Issue28117.cs UI test page demonstrating the border/label cropping issue
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28117.cs NUnit test for validating the fix
src/Controls/tests/DeviceTests/Stubs/WindowHandlerStub.Android.cs Added command mapper for RequestDisplayDensity
src/Controls/tests/DeviceTests/Elements/View/ViewTests.Android.cs Enhanced test assertions with device info
Comments suppressed due to low confidence (1)

}

static void ExpandStarDefinitions(Definition[] definitions, double targetSize, double currentSize, double spacing, double starCount, bool limitStarSizes)
void ExpandStarDefinitions(Definition[] definitions, double targetSize, double currentSize, double spacing, double starCount, bool limitStarSizes)
Copy link

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

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

Changing the method signature from static to instance method is a potential breaking change. This alters the public API surface and should be flagged for review as it may not be appropriate for a minor version or service release.

Copilot uses AI. Check for mistakes.
}

static void ExpandStars(double targetSize, double currentSize, Definition[] defs, double targetStarSize, double starCount)
static void ExpandStars(double targetSize, double currentSize, Definition[] defs, double targetStarSize, double starCount, double density)
Copy link

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

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

Adding a density parameter to the method signature is a potential breaking change. This alters the method's interface and should be reviewed as it may not be appropriate for a minor version or service release.

Copilot uses AI. Check for mistakes.
public int ColumnSpan { get; }
public double MeasureWidth { get; set; } = double.NaN;
public double MeasureHeight { get; set; } = double.NaN;
public DensityValue MeasureWidth { get; set; } = new DensityValue(double.NaN);
Copy link

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

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

Changing the property type from double to DensityValue is a breaking change. This alters the public API surface and should be flagged for review as it may not be appropriate for a minor version or service release.

Copilot uses AI. Check for mistakes.
public double MeasureWidth { get; set; } = double.NaN;
public double MeasureHeight { get; set; } = double.NaN;
public DensityValue MeasureWidth { get; set; } = new DensityValue(double.NaN);
public DensityValue MeasureHeight { get; set; } = new DensityValue(double.NaN);
Copy link

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

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

Changing the property type from double to DensityValue is a breaking change. This alters the public API surface and should be flagged for review as it may not be appropriate for a minor version or service release.

Copilot uses AI. Check for mistakes.
/// The current size of this definition
/// </summary>
public double Size
public DensityValue Size
Copy link

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

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

Changing the property type from double to DensityValue is a breaking change. This alters the public API surface and should be flagged for review as it may not be appropriate for a minor version or service release.

Copilot uses AI. Check for mistakes.
/// For star definitions, this is the minimum size which can contain the contents of the row/column
/// </summary>
public double MinimumSize { get; set; }
public DensityValue MinimumSize { get; set; }
Copy link

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

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

Changing the property type from double to DensityValue is a breaking change. This alters the public API surface and should be flagged for review as it may not be appropriate for a minor version or service release.

Copilot uses AI. Check for mistakes.
public DensityValue MinimumSize { get; set; }

public void Update(double size)
public void Update(DensityValue size)
Copy link

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

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

Changing the method parameter type from double to DensityValue is a breaking change. This alters the public API surface and should be flagged for review as it may not be appropriate for a minor version or service release.

Copilot uses AI. Check for mistakes.
@PureWeen
Copy link
Copy Markdown
Member

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@PureWeen PureWeen removed this from the .NET 9 SR10 milestone Aug 4, 2025
TamilarasanSF4853 and others added 25 commits September 17, 2025 12:54
…mplate (dotnet#31618)

&gt; [!NOTE]
&gt; Are you waiting for the changes in this PR to be merged?
&gt; It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

This PR updates the Blazor Maui Web template to use the modern ASP.NET
Core `MapStaticAssets()` middleware instead of the legacy
`UseStaticFiles()` middleware.

## Changes Made

In
`src/Templates/src/templates/maui-blazor-solution/MauiApp.1.Web/Program.cs`:

- **Removed:** `app.UseStaticFiles();` call
- **Added:** `app.MapStaticAssets();` call placed before
`MapRazorComponents()`

```diff
  app.UseHttpsRedirection();

- app.UseStaticFiles();
  app.UseAntiforgery();

+ app.MapStaticAssets();
+
  #if (UseServer && UseWebAssembly)
  app.MapRazorComponents<App>()
```

## Benefits

`MapStaticAssets()` is the recommended approach for serving static
assets in modern ASP.NET Core applications as it:

- Provides better performance through optimized asset serving
- Enables improved caching strategies
- Offers better integration with the routing pipeline
- Follows current ASP.NET Core best practices

## Testing

- ✅ Template generation works correctly with `dotnet new
maui-blazor-web`
- ✅ Generated web projects build successfully
- ✅ Static assets (CSS, JS) are served correctly at runtime
- ✅ All HTTP requests to static files return expected responses

Fixes dotnet#31617.

## Progress

- [x] Implement the core change from UseStaticFiles() to
MapStaticAssets()
- [x] Revert unrelated changes to cgmanifest.json and
templatestrings.json files
- [x] Verify the template still works correctly

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 Share your feedback on Copilot coding agent for the chance to win a
$200 gift card! Click
[here](https://survey3.medallia.com/?EAHeSx-AP01bZqG0Ld9QLQ) to start
the survey.
…on in UI Tests (dotnet#31715)

* Added cropLeft and cropRight implementation

* Update src/Controls/tests/TestCases.Shared.Tests/UITest.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@NanthiniMahalingam
Copy link
Copy Markdown
Contributor Author

Closed PR #30340 in favor of new PR #31755 due to unwanted changes introduced during rebasing.

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

Labels

area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter community ✨ Community Contribution layout-grid partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android

Projects

Status: Done