Skip to content

Comments

[iOS] Fix ContentPage BackgroundImageSource not working#33297

Merged
PureWeen merged 5 commits intodotnet:inflight/currentfrom
Shalini-Ashokan:fix-21594
Jan 2, 2026
Merged

[iOS] Fix ContentPage BackgroundImageSource not working#33297
PureWeen merged 5 commits intodotnet:inflight/currentfrom
Shalini-Ashokan:fix-21594

Conversation

@Shalini-Ashokan
Copy link
Contributor

Issue Details

ContentPage background images display incorrectly on iOS by tiling in a repeating pattern instead of showing a single scaled image.

Root Cause

The iOS implementation used a pattern color API that creates tiled patterns without scaling options. This tiles the image at original size rather than scaling it to fill the view.

Description of Change

Replaced the pattern color approach with a scalable layer that stretches the image to fill view bounds. This matches Android's scaling behavior and follows MAUI's standard layer management pattern used for gradient backgrounds.

Validated the behavior in the following platforms

  • Android
  • Windows
  • iOS
  • Mac

Issues Fixed

Fixes #21594

Test case

Test case Issue17789 is already included in the source.

Output ScreenShot

Before After
BeforeFix AfterFix

@dotnet-policy-service dotnet-policy-service bot added the community ✨ Community Contribution label Dec 26, 2025
@dotnet-policy-service
Copy link
Contributor

Hey there @@Shalini-Ashokan! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service dotnet-policy-service bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Dec 26, 2025
Copy link
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 fixes ContentPage BackgroundImageSource on iOS, which was incorrectly tiling images instead of scaling them. The fix replaces the pattern-based UIColor.FromPatternImage approach with a scalable CALayer that stretches the image to fill the view bounds, matching the behavior on other platforms.

Key changes:

  • Replaced UIColor.FromPatternImage with a StaticCALayer containing a CGImage
  • Added proper layer cleanup via RemoveBackgroundLayer() before setting new background
  • Set ContentsGravity = CALayer.GravityResize to scale the image instead of tiling

Comment on lines 414 to 433
var cgImage = backgroundImage.CGImage;
if (cgImage == null && backgroundImage.CIImage != null)
{
using var context = CoreImage.CIContext.Create();
cgImage = context.CreateCGImage(backgroundImage.CIImage, backgroundImage.CIImage.Extent);
}

if (cgImage == null)
return;

var imageLayer = new StaticCALayer
{
Name = BackgroundLayerName,
Contents = cgImage,
Frame = platformView.Bounds,
ContentsGravity = CoreAnimation.CALayer.GravityResize
};

platformView.BackgroundColor = UIColor.Clear;
platformView.InsertBackgroundLayer(imageLayer, 0);
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The CGImage created by CreateCGImage at line 418 is not being disposed, which will cause a memory leak. When CreateCGImage is called, it returns a new CGImage with +1 retain count that the caller owns and must dispose.

Since CALayer.Contents retains the CGImage when assigned, you should dispose the cgImage immediately after assigning it to the layer's Contents property (line 427). The layer will maintain its own reference, so disposing your reference won't affect the layer's ability to display the image.

Add a disposal call after line 433:

  • If cgImage came from backgroundImage.CGImage (line 414), it doesn't need disposal as it's owned by the UIImage
  • If cgImage came from CreateCGImage (line 418), it must be disposed after assignment to avoid a leak

You'll need to track which case applies, or alternatively, always use CreateCGImage and dispose it consistently.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Code Review - PR #33297

✅ Overall Assessment: APPROVE with minor recommendations

The fix is technically correct and well-implemented.


Summary

This PR fixes a long-standing iOS-specific bug where ContentPage.BackgroundImageSource would tile the image in a repeating pattern instead of scaling it to fill the view. The fix replaces the pattern-based approach with a layer-based solution that scales the image properly.


What's Fixed

Root Cause:

  • Previous implementation used UIColor.FromPatternImage() which creates tiled patterns without scaling
  • iOS's pattern color API doesn't support aspect fill/resize - it always tiles at original size
  • This is fundamentally incompatible with MAUI's expected behavior

Solution:

  • Replaces pattern color with StaticCALayer containing the image
  • Uses CALayer.ContentsGravity = GravityResize to scale/stretch the image
  • Follows existing MAUI pattern used for gradient backgrounds (StaticCAGradientLayer)
  • Properly manages layer lifecycle with RemoveBackgroundLayer() before adding new layer

Memory Management:

  • Properly tracks and disposes created CGImage
  • If CreateCGImage() was called, disposes after assignment (layer retains its own reference)
  • If CGImage comes from UIImage.CGImage, no disposal needed (owned by UIImage)

Code Quality: Excellent

Minimal, focused changes - Only 28 additions, 1 deletion
Proper resource management - Tracks and disposes CGImage when created
Defensive programming - Multiple null checks, early returns
Consistent with codebase - Follows existing patterns (StaticCAGradientLayer)
Clear comments - Explains CGImage disposal logic
No breaking changes - No public API changes


iOS Platform-Specific Considerations

✅ Excellent iOS-specific handling:

  1. Layer Management: Uses BackgroundLayerName constant for proper layer identification/removal
  2. Bounds Observation: StaticCALayer implements IAutoSizableCALayer which uses KVO to observe superlayer bounds changes
  3. CIImage Fallback: Handles both CGImage and CIImage sources (creates CGImage from CIImage if needed)
  4. Frame Initialization: Layer frame set to platformView.Bounds initially, then auto-updates
  5. BackgroundColor Clearing: Sets UIColor.Clear to avoid color bleeding through

Test Coverage

✅ Adequate test coverage:

  • Existing Test (Issue17789): Verifies via screenshot comparison
  • Test page: Issues17789.xaml - Sets BackgroundImageSource="oasis.jpg"
  • NUnit test: Issue17789.cs - Validates correct scaling behavior
  • Snapshot updated: ContentPageBackgroundImageSourceWorks.png

Assessment:

  • ✅ Basic functionality covered (image displays scaled, not tiled)
  • ✅ Platform-specific (marked as iOS)
  • ⚠️ Missing edge case tests (rotation, different aspect ratios, rapid changes)

Minor Concerns

  1. Async Race Condition (Low Priority)

    • If user rapidly changes BackgroundImageSource, multiple async GetImageAsync() calls are in flight
    • Last call to complete "wins" but earlier calls still execute
    • Could consider cancellation token for cleanup
    • Severity: Low - unlikely user scenario, minimal impact
  2. ContentsGravity Behavior (Documentation)

    • CALayer.GravityResize stretches/distorts image to fill bounds
    • Android/Windows might preserve aspect ratio differently
    • PR description says "matches Android's scaling behavior"
    • Recommendation: Document expected behavior vs. aspect-preserving options
  3. Test Coverage Gaps

    • No explicit test for rotation/resize scenarios
    • No test for rapid image source changes
    • No test for different image sizes/aspect ratios

Historical Context

  • Issue #17789 was previously "fixed" in commit 5dcb3406af (Nov 2023)
  • That fix created PageExtensions.cs but the root bug was in ViewExtensions.cs using FromPatternImage()
  • This fix addresses the root cause directly - more maintainable solution

Recommendation

✅ APPROVE - The fix is solid and addresses the root cause properly. The minor concerns are edge cases that don't block approval.

Optional Enhancements:

  • Document GravityResize stretching behavior for future reference
  • Consider adding rotation test case
  • Consider cancellation token for rapid image source changes

Great work fixing this long-standing issue! 🎉

Copy link
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Deep Independent Review - PR #33297

🤖 Copilot Deep Review Session Summary

This review was conducted through an interactive deep-dive session following the pr-reviewer-detailed workflow:

  1. "find reviewable prs" → Located PR #33297 (Syncfusion partner PR, iOS BackgroundImageSource fix)
  2. "yes, review #33297" → Standard review posted (basic code analysis)
  3. "please review #33297" → User requested deep independent review
  4. "yes" → Started deep review workflow with independent analysis
  5. Phase 1: Independent Analysis (WITHOUT looking at PR diff):
    • Researched git history: Found UIColor.FromPatternImage() has been there since 2022
    • Read issue #21594: Image tiles instead of scaling
    • Found previous fix attempt (#17789, Nov 2023) didn't address root cause
    • Designed my own fix approach using CALayer with GravityResize
  6. "Look at the PR's implementation and compare it to my approach" → Compared approaches
  7. Phase 2: Validation:
    • Ran UI test WITH fix → ✅ PASS
    • Ran UI test WITHOUT fix → ❌ FAIL (17.91% screenshot difference - tiling visible)
  8. Phase 3: Comparison → Identified critical memory leak in my approach that PR correctly handles

Recommendation: APPROVE

Summary: The PR's implementation is superior to my independent proposal and correctly fixes a long-standing root cause with proper memory management. The fix handles edge cases I initially missed, particularly CIImage sources and CGImage disposal.


Root Cause Analysis (Independent)

Historical Timeline:

  1. 2022 (commit f894684b60): Original BackgroundImageSource implementation used UIColor.FromPatternImage()
  2. Nov 2023 (PR #17789): Attempted fix created PageExtensions.cs but called the SAME buggy UpdateBackgroundImageSourceAsync()
  3. April 2024 (Issue #21594): Bug still reported - image tiles instead of scaling
  4. Dec 2024 (This PR #33297): Correctly fixes the root cause in ViewExtensions.cs

Root Cause:
UIColor.FromPatternImage() API creates tiled patterns at original image size with NO scaling options. This is fundamentally incompatible with MAUI's expected behavior (scale to fill). The bug has existed since the original 2022 implementation.


Fix Comparison: PR vs My Independent Approach

Aspect PR's Implementation My Initial Proposal Winner
Core Approach ✅ CALayer with GravityResize ✅ CALayer with GravityResize Tie
CGImage Handling ✅ Handles both CGImage and CIImage ❌ Assumed CGImage only PR
Memory Management ✅ Tracks and disposes created CGImage ❌ Memory leak for CIImage sources PR
Null Safety ✅ Multiple null checks ⚠️ Basic checks only PR
Code Comments ✅ Explains disposal logic ❌ Missing PR
Lines Changed 28 additions ~20 estimated Tie
Test Validation ✅ Passes with fix, fails without Not tested PR

Critical Issue I Missed: Memory Leak 🔴

The PR correctly handles a memory leak scenario I didn't consider:

// When UIImage has CIImage but no CGImage:
var cgImage = backgroundImage.CGImage;  // null
var shouldDisposeCGImage = false;

if (cgImage == null && backgroundImage.CIImage != null)
{
    using var context = CoreImage.CIContext.Create();
    // CreateCGImage() allocates NEW CGImage → we OWN it
    cgImage = context.CreateCGImage(backgroundImage.CIImage, backgroundImage.CIImage.Extent);
    shouldDisposeCGImage = true;  // ← Must dispose!
}

// ... later ...
if (shouldDisposeCGImage)
    cgImage?.Dispose();  // ← Clean up created CGImage

Why This Matters:

  • CreateCGImage() creates a NEW CGImage that the caller owns → must dispose
  • UIImage.CGImage property returns a reference owned by UIImage → don't dispose
  • My approach would have leaked memory for any CIImage-based sources

Test Validation ✅

Test: Issue17789.cs - ContentPage BackgroundImageSource

Scenario Result Screenshot Diff Evidence
WITH fix ✅ PASS Matches baseline Image scales correctly
WITHOUT fix ❌ FAIL 17.91% difference Tiled pattern visible

Test Quality: ✅ Excellent

  • Uses visual regression testing (screenshot comparison)
  • Correctly catches the bug (fails without fix, passes with fix)
  • Appropriate for this visual issue
  • Test existed from previous fix attempt (2023) - was incorrectly passing before

Validation command used:

pwsh .github/scripts/BuildAndRunHostApp.ps1 -Platform ios -TestFilter "Issue17789"

iOS Platform Considerations ✅

The PR demonstrates excellent iOS-specific handling:

  1. Layer Management: Uses BackgroundLayerName constant for proper layer identification/removal
  2. Bounds Auto-Resize: StaticCALayer implements IAutoSizableCALayer which uses KVO to observe superlayer bounds changes
  3. CIImage Fallback: Handles both CGImage and CIImage sources (creates CGImage from CIImage if needed)
  4. Z-Order: Inserts layer at index 0 (bottom of layer stack)
  5. BackgroundColor Clearing: Sets UIColor.Clear to avoid color bleeding through

iOS API Usage - All Correct:

  • CoreAnimation.CALayer.GravityResize - stretches image to fill bounds
  • InsertBackgroundLayer(imageLayer, 0) - proper z-order
  • CoreImage.CIContext.Create() - standard CIImage → CGImage conversion
  • RemoveBackgroundLayer() - cleanup before adding new layer

Edge Cases Handled ✅

Edge Case PR Handles It? How
CIImage-only sources ✅ Yes Converts via CreateCGImage() and disposes afterward
Null image sources ✅ Yes Multiple null checks with early returns
Memory management ✅ Yes Tracks and disposes created CGImage with shouldDisposeCGImage flag
View resize (rotation) ✅ Yes IAutoSizableCALayer auto-resizes on bounds changes
Rapid image changes ✅ Yes RemoveBackgroundLayer() cleans up previous layer first
Large images ✅ Yes Standard iOS memory management via CALayer

Potential Regressions: None Identified ✅

This fix:

  • ✅ Only affects iOS BackgroundImageSource rendering path
  • ✅ Doesn't change public APIs or method signatures
  • ✅ Follows existing MAUI pattern used for gradients (StaticCAGradientLayer)
  • ✅ No performance concerns (layer-based approach is standard iOS practice)
  • ✅ Backward compatible - replaces broken tiling with correct scaling

Regression testing not needed - this is a pure bug fix that makes iOS match Android/Windows behavior.


What I Learned from This Review 📚

What I Got Right:

  • ✅ Identified FromPatternImage() as the root cause (correct)
  • ✅ Proposed CALayer approach with GravityResize (same as PR)
  • ✅ Recognized need for RemoveBackgroundLayer() cleanup
  • ✅ Understood layer auto-resize requirement

What I Missed (and PR got right):

  • CIImage handling - Assumed CGImage always available (wrong!)
  • Memory management - Would have leaked for CIImage sources (critical bug!)
  • Comprehensive null checking - PR is more defensive

Key Takeaway: Always check for multiple image source types (CGImage vs CIImage) in iOS and understand their ownership semantics. The distinction between "we created it" (must dispose) vs "UIImage owns it" (don't dispose) is critical.


Code Quality Assessment ✅

Excellent code quality:

  • ✅ Minimal, focused changes (28 additions, 1 deletion)
  • ✅ Proper resource management with tracking flag
  • ✅ Defensive programming with multiple null checks
  • ✅ Consistent with codebase patterns (StaticCAGradientLayer)
  • ✅ Clear, explanatory comments for complex logic
  • ✅ No breaking changes to public APIs

Final Recommendation

✅ APPROVE - This PR correctly fixes the long-standing root cause with excellent memory management and iOS best practices.

Why This Fix is Superior:

  1. Handles edge cases my approach missed (CIImage sources)
  2. Prevents memory leaks (proper CGImage disposal)
  3. More defensive (comprehensive null checking)
  4. Well-documented (comments explain complex disposal logic)

No changes requested - the implementation is production-ready.


Optional Enhancement (Not Blocking)

Documentation suggestion: Consider adding a comment explaining GravityResize behavior:

// GravityResize stretches image to fill bounds without preserving aspect ratio
// This matches Android's ScaleType.FIT_XY and Windows' Stretch.Fill behavior
imageLayer.ContentsGravity = CoreAnimation.CALayer.GravityResize;

This would help future maintainers understand the intentional stretching behavior vs aspect-preserving alternatives.


Great work fixing this 3-year-old bug! 🎉

@kubaflo kubaflo added the t/bug Something isn't working label Dec 30, 2025
@PureWeen PureWeen changed the base branch from main to inflight/current January 2, 2026 20:19
@PureWeen PureWeen merged commit 6ec88b8 into dotnet:inflight/current Jan 2, 2026
20 of 23 checks passed
PureWeen pushed a commit that referenced this pull request Jan 5, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details
ContentPage background images display incorrectly on iOS by tiling in a
repeating pattern instead of showing a single scaled image.

### Root Cause
The iOS implementation used a pattern color API that creates tiled
patterns without scaling options. This tiles the image at original size
rather than scaling it to fill the view.


### Description of Change
Replaced the pattern color approach with a scalable layer that stretches
the image to fill view bounds. This matches Android's scaling behavior
and follows MAUI's standard layer management pattern used for gradient
backgrounds.

Validated the behavior in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
 
### Issues Fixed
  
Fixes #21594

### Test case

Test case Issue17789 is already included in the source.

### Output  ScreenShot

| Before  | After  |
|---------|--------|
| <img width="354" height="735" alt="BeforeFix"
src="https://github.com/user-attachments/assets/8520b49b-617c-46e5-a29a-3a9b26e5b0c0"
/> | <img width="354" height="735" alt="AfterFix"
src="https://github.com/user-attachments/assets/402a8975-4d2b-4e2f-a362-ae22bcedec56"
/> |
@PureWeen PureWeen mentioned this pull request Jan 7, 2026
PureWeen pushed a commit that referenced this pull request Jan 9, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details
ContentPage background images display incorrectly on iOS by tiling in a
repeating pattern instead of showing a single scaled image.

### Root Cause
The iOS implementation used a pattern color API that creates tiled
patterns without scaling options. This tiles the image at original size
rather than scaling it to fill the view.


### Description of Change
Replaced the pattern color approach with a scalable layer that stretches
the image to fill view bounds. This matches Android's scaling behavior
and follows MAUI's standard layer management pattern used for gradient
backgrounds.

Validated the behavior in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
 
### Issues Fixed
  
Fixes #21594

### Test case

Test case Issue17789 is already included in the source.

### Output  ScreenShot

| Before  | After  |
|---------|--------|
| <img width="354" height="735" alt="BeforeFix"
src="https://github.com/user-attachments/assets/8520b49b-617c-46e5-a29a-3a9b26e5b0c0"
/> | <img width="354" height="735" alt="AfterFix"
src="https://github.com/user-attachments/assets/402a8975-4d2b-4e2f-a362-ae22bcedec56"
/> |
PureWeen pushed a commit that referenced this pull request Jan 9, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details
ContentPage background images display incorrectly on iOS by tiling in a
repeating pattern instead of showing a single scaled image.

### Root Cause
The iOS implementation used a pattern color API that creates tiled
patterns without scaling options. This tiles the image at original size
rather than scaling it to fill the view.


### Description of Change
Replaced the pattern color approach with a scalable layer that stretches
the image to fill view bounds. This matches Android's scaling behavior
and follows MAUI's standard layer management pattern used for gradient
backgrounds.

Validated the behavior in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
 
### Issues Fixed
  
Fixes #21594

### Test case

Test case Issue17789 is already included in the source.

### Output  ScreenShot

| Before  | After  |
|---------|--------|
| <img width="354" height="735" alt="BeforeFix"
src="https://github.com/user-attachments/assets/8520b49b-617c-46e5-a29a-3a9b26e5b0c0"
/> | <img width="354" height="735" alt="AfterFix"
src="https://github.com/user-attachments/assets/402a8975-4d2b-4e2f-a362-ae22bcedec56"
/> |
PureWeen pushed a commit that referenced this pull request Jan 9, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details
ContentPage background images display incorrectly on iOS by tiling in a
repeating pattern instead of showing a single scaled image.

### Root Cause
The iOS implementation used a pattern color API that creates tiled
patterns without scaling options. This tiles the image at original size
rather than scaling it to fill the view.


### Description of Change
Replaced the pattern color approach with a scalable layer that stretches
the image to fill view bounds. This matches Android's scaling behavior
and follows MAUI's standard layer management pattern used for gradient
backgrounds.

Validated the behavior in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
 
### Issues Fixed
  
Fixes #21594

### Test case

Test case Issue17789 is already included in the source.

### Output  ScreenShot

| Before  | After  |
|---------|--------|
| <img width="354" height="735" alt="BeforeFix"
src="https://github.com/user-attachments/assets/8520b49b-617c-46e5-a29a-3a9b26e5b0c0"
/> | <img width="354" height="735" alt="AfterFix"
src="https://github.com/user-attachments/assets/402a8975-4d2b-4e2f-a362-ae22bcedec56"
/> |
@kubaflo kubaflo added the s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) label Jan 10, 2026
PureWeen pushed a commit that referenced this pull request Jan 13, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details
ContentPage background images display incorrectly on iOS by tiling in a
repeating pattern instead of showing a single scaled image.

### Root Cause
The iOS implementation used a pattern color API that creates tiled
patterns without scaling options. This tiles the image at original size
rather than scaling it to fill the view.


### Description of Change
Replaced the pattern color approach with a scalable layer that stretches
the image to fill view bounds. This matches Android's scaling behavior
and follows MAUI's standard layer management pattern used for gradient
backgrounds.

Validated the behavior in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
 
### Issues Fixed
  
Fixes #21594

### Test case

Test case Issue17789 is already included in the source.

### Output  ScreenShot

| Before  | After  |
|---------|--------|
| <img width="354" height="735" alt="BeforeFix"
src="https://github.com/user-attachments/assets/8520b49b-617c-46e5-a29a-3a9b26e5b0c0"
/> | <img width="354" height="735" alt="AfterFix"
src="https://github.com/user-attachments/assets/402a8975-4d2b-4e2f-a362-ae22bcedec56"
/> |
PureWeen pushed a commit that referenced this pull request Jan 13, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details
ContentPage background images display incorrectly on iOS by tiling in a
repeating pattern instead of showing a single scaled image.

### Root Cause
The iOS implementation used a pattern color API that creates tiled
patterns without scaling options. This tiles the image at original size
rather than scaling it to fill the view.


### Description of Change
Replaced the pattern color approach with a scalable layer that stretches
the image to fill view bounds. This matches Android's scaling behavior
and follows MAUI's standard layer management pattern used for gradient
backgrounds.

Validated the behavior in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
 
### Issues Fixed
  
Fixes #21594

### Test case

Test case Issue17789 is already included in the source.

### Output  ScreenShot

| Before  | After  |
|---------|--------|
| <img width="354" height="735" alt="BeforeFix"
src="https://github.com/user-attachments/assets/8520b49b-617c-46e5-a29a-3a9b26e5b0c0"
/> | <img width="354" height="735" alt="AfterFix"
src="https://github.com/user-attachments/assets/402a8975-4d2b-4e2f-a362-ae22bcedec56"
/> |
PureWeen added a commit that referenced this pull request Jan 13, 2026
## What's Coming

.NET MAUI inflight/candidate introduces significant improvements across
all platforms with focus on quality, performance, and developer
experience. This release includes 27 commits with various improvements,
bug fixes, and enhancements.

## CollectionView
- [iOS][CV2] Fix page can be dragged down, and it would cause an extra
space between Header and EmptyView text by @devanathan-vaithiyanathan in
#31840
  <details>
  <summary>🔧 Fixes</summary>

- [I8_Header_and_Footer_Null - The page can be dragged down, and it
would cause an extra space between Header and EmptyView
text.](#31465)
  </details>

- [iOS] Fixed the Items not displayed properly in CarouselView2 by
@Ahamed-Ali in #31336
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Items are not updated properly in
CarouselView2.](#31148)
  </details>

## Docs
- Improve Controls Core API docs by @jfversluis in
#33240

## Editor
- [iOS] Fixed an issue where an Editor with a small height inside a
ScrollView would cause the entire page to scroll by
@Tamilarasan-Paranthaman in #27948
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS][Editor] An Editor that has not enough height and resides inside
a ScrollView/CollectionView will scroll the entire
page](#27750)
  </details>

## Image
- [Android] Image control crashes on Android when image width exceeds
height by @KarthikRajaKalaimani in
#33045
  <details>
  <summary>🔧 Fixes</summary>

- [Image control crashes on Android when image width exceeds
height](#32869)
  </details>

## Mediapicker
- [Android 🤖] Add a log telling why the request is cancelled by @pictos
in #33295
  <details>
  <summary>🔧 Fixes</summary>

- [MediaPicker.PickPhotosAsync throwing TaskCancelledException in
net10-android](#33283)
  </details>

## Navigation
- [Android] Fix for App Hang When PopModalAsync Is Called Immediately
After PushModalAsync with Task.Yield() by @BagavathiPerumal in
#32479
  <details>
  <summary>🔧 Fixes</summary>

- [App hangs if PopModalAsync is called after PushModalAsync with single
await Task.Yield()](#32310)
  </details>

- [iOS 26] Navigation hangs after rapidly open and closing new page
using Navigation.PushAsync - fix by @kubaflo in
#32456
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS 26] Navigation hangs after rapidly open and closing new page
using Navigation.PushAsync](#32425)
  </details>

## Pages
- [iOS] Fix ContentPage BackgroundImageSource not working by
@Shalini-Ashokan in #33297
  <details>
  <summary>🔧 Fixes</summary>

- [.Net MAUI- Page.BackgroundImageSource not working for
iOS](#21594)
  </details>

## RadioButton
- [Issue-Resolver] Fix #33264 - RadioButtonGroup not working with
Collection View by @kubaflo in #33343
  <details>
  <summary>🔧 Fixes</summary>

- [RadioButtonGroup not working with
CollectionView](#33264)
  </details>

## SafeArea
- [Android] Fixed Label Overlapped by Android Status Bar When Using
SafeAreaEdges="Container" in .NET MAUI by @NirmalKumarYuvaraj in
#33285
  <details>
  <summary>🔧 Fixes</summary>

- [SafeAreaEdges works correctly only on the first tab in Shell. Other
tabs have content colliding with the display cutout in the landscape
mode.](#33034)
- [Label Overlapped by Android Status Bar When Using
SafeAreaEdges="Container" in .NET
MAUI](#32941)
- [[MAUI 10] Layout breaks on first navigation (Shell // route) until
soft keyboard appears/disappears (Android +
iOS)](#33038)
  </details>

## ScrollView
- [Windows, Android] Fix ScrollView Content Not Removed When Set to Null
by @devanathan-vaithiyanathan in
#33069
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows, Android] ScrollView Content Not Removed When Set to
Null](#33067)
  </details>

## Searchbar
- Fix Android crash when changing shared Drawable tint on Searchbar by
@tritter in #33071
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Crash on changing Tint of
Searchbar](#33070)
  </details>

## Shell
- [iOS] - Fix Custom FlyoutIcon from Being Overridden to Default Color
in Shell by @prakashKannanSf3972 in
#27580
  <details>
  <summary>🔧 Fixes</summary>

- [Change the flyout icon
color](#6738)
  </details>

- [iOS] Fix Shell NavBarIsVisible updates when switching ShellContent by
@Vignesh-SF3580 in #33195
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Shell NavBarIsVisible is not updated when changing
ShellContent](#33191)
  </details>

## Slider
- [C] Fix Slider and Stepper property order independence by
@StephaneDelcroix in #32939
  <details>
  <summary>🔧 Fixes</summary>

- [Slider Binding Initialization Order Causes Incorrect Value Assignment
in XAML](#32903)
- [Slider is very broken, Value is a mess when setting
Minimum](#14472)
- [Slider is buggy depending on order of
properties](#18910)
- [Stepper Value is incorrectly clamped to default min/max when using
bindableproperties in MVVM
pattern](#12243)
- [[Issue-Resolver] Fix #32903 - Sliderbinding initialization order
issue](#32907)
  </details>

## Stepper
- [Windows] Maui Stepper: Clamp minimum and maximum value by @OomJan in
#33275
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] Maui Stepper is not clamped to minimum or maximum
internally](#33274)
  </details>

- [iOS] Fixed the UIStepper Value from being clamped based on old higher
MinimumValue - Candidate PR test failure fix- 33363 by @Ahamed-Ali in
#33392

## TabbedPage
- [windows] Fixed Rapid change of selected tab results in crash. by
@praveenkumarkarunanithi in #33113
  <details>
  <summary>🔧 Fixes</summary>

- [Rapid change of selected tab results in crash on
Windows.](#32824)
  </details>

## Titlebar
- [Mac] Fix TitleBar Content Overlapping with Traffic Light Buttons on
Latest macOS Version by @devanathan-vaithiyanathan in
#33157
  <details>
  <summary>🔧 Fixes</summary>

- [TitleBar Content Overlapping with Traffic Light Buttons on Latest
macOS Version](#33136)
  </details>

## Xaml
- Fix for Control does not update from binding anymore after
MultiBinding.ConvertBack is called by @BagavathiPerumal in
#33128
  <details>
  <summary>🔧 Fixes</summary>

- [Control does not update from binding anymore after
MultiBinding.ConvertBack is
called](#24969)
- [The issue with the MultiBinding converter with two way binding mode
does not work properly when changing the
values.](#20382)
  </details>


<details>
<summary>🔧 Infrastructure (1)</summary>

- Avoid KVO on CALayer by introducing an Apple PlatformInterop by
@albyrock87 in #30861

</details>

<details>
<summary>🧪 Testing (2)</summary>

- [Testing] Enable UITest Issue18193 on MacCatalyst by @NafeelaNazhir in
#31653
  <details>
  <summary>🔧 Fixes</summary>

- [Test Issue18193 was disabled on Mac
Catalyst](#27206)
  </details>
- Set the CV2 handlers as the default by @Ahamed-Ali in
#33177

</details>

<details>
<summary>📦 Other (3)</summary>

- Update WindowsAppSDK to 1.8 by @mattleibow in
#32174
  <details>
  <summary>🔧 Fixes</summary>

- [Update to WindowsAppSDK](#30858)
  </details>
- Fix command dependency reentrancy by @simonrozsival in
#33129
- Fix SafeArea AdjustPan handling and add AdjustNothing mode tests by
@PureWeen via @Copilot in #33354

</details>
**Full Changelog**:
main...inflight/candidate
kubaflo pushed a commit to kubaflo/maui that referenced this pull request Jan 16, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details
ContentPage background images display incorrectly on iOS by tiling in a
repeating pattern instead of showing a single scaled image.

### Root Cause
The iOS implementation used a pattern color API that creates tiled
patterns without scaling options. This tiles the image at original size
rather than scaling it to fill the view.


### Description of Change
Replaced the pattern color approach with a scalable layer that stretches
the image to fill view bounds. This matches Android's scaling behavior
and follows MAUI's standard layer management pattern used for gradient
backgrounds.

Validated the behavior in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
 
### Issues Fixed
  
Fixes dotnet#21594

### Test case

Test case Issue17789 is already included in the source.

### Output  ScreenShot

| Before  | After  |
|---------|--------|
| <img width="354" height="735" alt="BeforeFix"
src="https://github.com/user-attachments/assets/8520b49b-617c-46e5-a29a-3a9b26e5b0c0"
/> | <img width="354" height="735" alt="AfterFix"
src="https://github.com/user-attachments/assets/402a8975-4d2b-4e2f-a362-ae22bcedec56"
/> |
@github-actions github-actions bot locked and limited conversation to collaborators Feb 10, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-controls-pages Page types community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/ios s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) t/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.Net MAUI- Page.BackgroundImageSource not working for iOS

4 participants