Skip to content

[iOS, Android] Fix for CollectionView IsEnabled=false allows touch interactions#31403

Merged
kubaflo merged 2 commits intodotnet:inflight/currentfrom
praveenkumarkarunanithi:fix-19771
Feb 24, 2026
Merged

[iOS, Android] Fix for CollectionView IsEnabled=false allows touch interactions#31403
kubaflo merged 2 commits intodotnet:inflight/currentfrom
praveenkumarkarunanithi:fix-19771

Conversation

@praveenkumarkarunanithi
Copy link
Copy Markdown
Contributor

Root Cause

iOS
The underlying UICollectionView does not inherit from UIControl, so it has no native Enabled property. In ViewExtensions.UpdateIsEnabled, this caused an early return for non-UIControl views, leaving touch interactions active when IsEnabled = false.

Android
RecyclerView does not support a native enabled/disabled state. While UpdateIsEnabled is called when IsEnabled = false, there was no platform-specific handling, so touch interactions remained functional.

Description of Change

iOS
Modified ViewExtensions.UpdateIsEnabled to branch between UIControl and non-UIControl views. For UIControl, the native Enabled property is applied to block interactions and provide visual feedback. For non-UIControl views such as UICollectionView, UserInteractionEnabled is set to disable touch input while preserving visual appearance.

Android
Enhanced MauiRecyclerView with touch event overrides to handle the disabled state. OnInterceptTouchEvent returns true when the CollectionView is disabled, blocking child interactions. OnTouchEvent returns false to prevent RecyclerView itself from processing gestures. Both methods check ItemsView?.IsEnabled to ensure correct state handling.

Issues Fixed

Fixes #19771

Tested the behaviour in the following platforms

  • Android
  • Windows
  • iOS
  • Mac

Output Video

Before Issue Fix After Issue Fix
BeforeFix.mov
afterfix.mov

@dotnet-policy-service dotnet-policy-service bot added the community ✨ Community Contribution label Aug 29, 2025
@praveenkumarkarunanithi praveenkumarkarunanithi added platform/macos macOS / Mac Catalyst platform/ios area-controls-collectionview CollectionView, CarouselView, IndicatorView partner/android Issues for the Android SDK and removed community ✨ Community Contribution labels Aug 29, 2025
@praveenkumarkarunanithi praveenkumarkarunanithi marked this pull request as ready for review August 29, 2025 13:38
Copilot AI review requested due to automatic review settings August 29, 2025 13:38
@praveenkumarkarunanithi praveenkumarkarunanithi requested a review from a team as a code owner August 29, 2025 13:38
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 fixes a bug where CollectionView with IsEnabled=false still allowed touch interactions on iOS and Android platforms. The root cause was that the underlying native views (UICollectionView on iOS and RecyclerView on Android) don't have built-in disabled state handling like typical UI controls.

Key changes:

  • Updated iOS ViewExtensions.UpdateIsEnabled to handle non-UIControl views by disabling UserInteractionEnabled
  • Enhanced Android MauiRecyclerView with touch event overrides to block interactions when disabled
  • Added comprehensive UI tests to validate the fix across platforms

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Core/src/Platform/iOS/ViewExtensions.cs Modified to handle UICollectionView disabled state by setting UserInteractionEnabled
src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs Added touch event overrides to block interactions when IsEnabled is false
src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt Updated public API surface with new touch event override methods
src/Controls/tests/TestCases.HostApp/Issues/Issue19771.cs Added test UI page demonstrating CollectionView disabled state behavior
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19771.cs Added automated test validating touch interactions are blocked when disabled

@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Hey there @@praveenkumarkarunanithi! 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 Aug 29, 2025
@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run MAUI-UITests-public

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@karthikraja-arumugam karthikraja-arumugam added the community ✨ Community Contribution label Dec 4, 2025
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Dec 9, 2025

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 31403

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 31403"

@sheiksyedm sheiksyedm added platform/android and removed partner/android Issues for the Android SDK labels Feb 12, 2026
@rmarinho
Copy link
Copy Markdown
Member

rmarinho commented Feb 16, 2026

🤖 AI Summary

📊 Expand Full Review
🔍 Pre-Flight — Context & Validation
📝 Review Sessiontest case updated · 61a5b56

Issue: #19771 - More issues with CollectionView IsEnabled, InputTransparent, Opacity via Styles and code behind
PR: #31403 - [iOS, Android] Fix for CollectionView IsEnabled=false allows touch interactions
Platforms Affected: iOS, Android, macOS
Files Changed: 3 implementation files, 2 test files

Key Findings

Root Cause (per PR):

  • iOS: UICollectionView doesn't inherit from UIControl, so ViewExtensions.UpdateIsEnabled returned early for non-UIControl views, leaving touch interactions active when IsEnabled=false
  • Android: RecyclerView has no native enabled/disabled state; UpdateIsEnabled was called but had no platform-specific handling, so touch interactions remained functional

Issue Description:

  • User reported CollectionView with IsEnabled=false still allows touch interactions (items can be selected)
  • Workarounds using InputTransparent and Opacity had inconsistent behavior depending on whether set via styles, code-behind, or VisualStates

PR's Approach:

  • iOS: Modified ViewExtensions.UpdateIsEnabled to branch between UIControl and non-UIControl views. For non-UIControl views (like UICollectionView), sets UserInteractionEnabled to disable touch input
  • Android: Enhanced MauiRecyclerView with touch event overrides (OnInterceptTouchEvent and OnTouchEvent) to block interactions when IsEnabled=false

Tests Included:

  • UI test page: Issue19771.cs in TestCases.HostApp
  • Automated test: Issue19771.cs in TestCases.Shared.Tests
  • Test type: UI Tests (Appium-based)

PR Discussion

No reviewer disagreements or edge cases flagged in comments.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #31403 iOS: Branch UpdateIsEnabled to handle non-UIControl views via UserInteractionEnabled; Android: Override OnInterceptTouchEvent/OnTouchEvent in MauiRecyclerView to block touch when disabled PASS (Gate) ViewExtensions.cs (+10/-4), MauiRecyclerView.cs (+22), PublicAPI.Unshipped.txt (+2) Original PR

Files Classification

Implementation files:

  1. src/Core/src/Platform/iOS/ViewExtensions.cs - iOS fix
  2. src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs - Android fix
  3. src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt - API surface update

Test files:

  1. src/Controls/tests/TestCases.HostApp/Issues/Issue19771.cs - UI test page
  2. src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19771.cs - Automated test

🚦 Gate — Test Verification
📝 Review Sessiontest case updated · 61a5b56

Result PASSED:
Platform: android
Mode: Full Verification

Test Behavior

  • Tests FAIL without fix (bug is present)
  • Tests PASS with fix (bug is fixed)

Verification Summary


              VERIFICATION PASSED                        
#

  Tests correctly detect the issue:                        
 FAIL without fix (bug is present)                    - 
 PASS with fix (bug is fixed)                         - 

Test Name: CollectionViewIsEnabledFalsePreventsInteractions
Device: Android emulator-5554
Test Count: 1 test validated

Conclusion

The tests properly validate the PR's fix. They catch the bug when the fix is not applied and pass when the fix is present.


🔧 Fix — Analysis & Comparison
📝 Review Sessiontest case updated · 61a5b56

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-sonnet-4.5) ItemTouchListener FAIL MauiRecyclerView.cs (+50) Intercepted too late in event chain interception
2 try-fix (claude-opus-4.6) Adapter SelectableClicked guard PASS SelectableItemsViewAdapter.cs (+6) Blocks selection at MAUI logic layer - allows scrolling
3 try-fix (gpt-5.2) Native Enabled/Clickable on RecyclerView and children PASS MauiRecyclerView.cs (+~40) Platform enabled-state plumbing
4 try-fix (gpt-5.2-codex) Toggle SelectableViewHolder.Clicked subscriptions PASS SelectableItemsViewAdapter.cs (+~30) Detach click handlers when disabled
5 try-fix (gemini-3-pro-preview) Override DispatchTouchEvent PASS MauiRecyclerView.cs (+8) Blocks at primary touch entry point
6 try-fix (gpt-5.2) Round 2 Guard SelectableViewHolder.OnClick PASS SelectableViewHolder.cs (+16/-7) Guards OnClick with Enabled checks
7 try-fix (gpt-5.2-codex) Round 2 Per-item OnTouchListener PASS SelectableItemsViewAdapter.cs (+~20), SelectableViewHolder.cs (+~10) Item-level touch consumption
8 try-fix (gemini-3-pro-preview) Round 2 Logical layer IsEnabled guards (Android + iOS PASS SelectableItemsViewAdapter.cs (+5), SelectableItemsViewController.cs (+10) Cross-platform selection guard )
PR PR #31403 iOS: UserInteractionEnabled for non-UIControl; Android: OnInterceptTouchEvent/OnTouchEvent overrides PASS (Gate) ViewExtensions.cs (+10/-4), MauiRecyclerView.cs (+22), PublicAPI.Unshipped.txt (+2) Original PR

Cross-Pollination Results

Round 2:

  • claude-sonnet-4.5: Suggested OnTouchListener (acknowledged might be redundant)
  • claude-opus-4.6: NO NEW IDEAS
    Attempt 6 PASS
    Attempt 7 PASS
    Attempt 8 PASS

Round 3:

  • claude-sonnet-4.5: NO NEW IDEAS
  • claude-opus-4.6: NO NEW IDEAS
  • gpt-5.2: Suggested OnInterceptTouchEvent (PR's approach - not new)
  • gpt-5.2-codex: NO NEW IDEAS
  • gemini-3-pro-preview: NO NEW IDEAS

Exhausted: Yes - all models confirmed no new ideas in Round 3

Selection Reasoning

PR's fix blocks ALL touches (selection + scrolling), matching platform conventions for disabled controls. Simpler alternatives (Candidates #2, #8) allow scrolling while disabled, creating inconsistent UX.

Selected Fix: PR's fix - PR's OnInterceptTouchEvent/OnTouchEvent approach is the most robust, providing complete interaction blocking consistent with platform conventions and MAUI's IsEnabled semantics.


📋 Report — Final Recommendation
📝 Review Sessiontest case updated · 61a5b56

Final Recommendation: APPROVE

Summary

PR #31403 successfully fixes CollectionView's IsEnabled=false bug on iOS and Android. The fix properly blocks touch interactions when disabled, passing all tests. 8 alternative approaches were the PR's approach was selected as the most robust, providing complete interaction blocking consistent with platform conventions.explored

Root Cause

iOS:
UICollectionView doesn't inherit from UIControl, causing ViewExtensions.UpdateIsEnabled to return early for non-UIControl views. This left touch interactions active even when IsEnabled=false.

Android:
RecyclerView lacks native enabled/disabled state handling. While UpdateIsEnabled was called, there was no platform-specific implementation to block touch interactions.

Fix Quality

PR's Approach:

  • iOS: Branch UpdateIsEnabled to handle non-UIControl views via UserInteractionEnabled
  • Android: Override OnInterceptTouchEvent (returns true to block children) and OnTouchEvent (returns false to prevent RecyclerView gesture processing)

Why this is the best approach:

  1. Complete interaction blocking - Blocks ALL touches (selection + scrolling), matching platform conventions for disabled controls
  2. Architecturally correct - Touch interception is the proper layer for IsEnabled behavior
  3. Consistent with MAUI - Other disabled controls block all interactions, not just selection
  4. Robust - Handles all touch scenarios at the right layer

Alternative approaches explored (8 total):

  • 7 passed tests; simpler approaches (Adapter guard, DispatchTouchEvent) allow scrolling while disabled, creating inconsistent UX
  • PR's complete blocking matches user expectations for disabled controls

Code Review

** Strengths:**

  • Clean, maintainable code with clear logic
  • Proper null checking (ItemsView?.IsEnabled == false)
  • Platform-specific implementations in correct files
  • Public API surface correctly documented in PublicAPI.Unshipped.txt
  • Comprehensive UI tests included with HostApp page and shared test

Verdict

APPROVE - This PR correctly fixes the reported issue with a robust, platform-appropriate solution. The implementation is clean, well-tested, and properly documented. The chosen approach (complete interaction blocking via touch event interception) is superior to simpler alternatives that would allow partial interactions on disabled controls.


🔧 Try-Fix Analysis: ✅ 1 passed
✅ Fix 1

Check IsEnabled Before Processing Selection

The fix successfully prevents CollectionView from allowing touch interactions when IsEnabled=false. The approach intercepts selection at the logical/handler level:

Android: Added guard in SelectableClicked() that returns early if ItemsView?.IsEnabled == false.

iOS: Added guards in both FormsSelectItem() and FormsDeselectItem() that return early if disabled.

Why it worked:

  • Selection logic is prevented from executing at the point where it matters
  • The SelectionChanged event does not fire because selection state is never modified
  • Simple null-check guards are easy to maintain and understand
  • Works symmetrically across both iOS and Android platforms
  • This approach is different from and more robust than the existing platform-level touch event suppression
📋 Expand PR Finalization Review
Title: ✅ Good

Current: [iOS, Android] Fix for CollectionView IsEnabled=false allows touch interactions

Description: ✅ Good

Description needs updates. See details below.

✨ Suggested PR Description

[!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!

Root Cause

iOS
UICollectionView does not inherit from UIControl, so it has no native Enabled property. In ViewExtensions.UpdateIsEnabled, non-UIControl views triggered an early return, leaving touch interactions fully active when IsEnabled = false.

Android
RecyclerView has no native enabled/disabled state. While UpdateIsEnabled was called when IsEnabled = false, there was no platform-specific handling to block touch events, so scrolling and item selection remained functional.

Description of Change

iOS (src/Core/src/Platform/iOS/ViewExtensions.cs)
Modified UpdateIsEnabled to branch between UIControl and non-UIControl views:

  • For UIControl views: sets the native Enabled property (preserves visual feedback such as alpha changes)
  • For non-UIControl views (e.g., UICollectionView): sets UserInteractionEnabled = false to block touch input

Note: This change affects all non-UIControl UIViews platform-wide, not just UICollectionView. This also applies to MacCatalyst since the iOS platform code is shared.

Android (src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs)
Added touch event overrides to MauiRecyclerView to handle the disabled state:

  • OnInterceptTouchEvent returns true when ItemsView.IsEnabled == false, blocking all child touch events (item selection, item click)
  • OnTouchEvent returns false when disabled, preventing RecyclerView itself from processing gestures (scroll, fling)

Both methods delegate to the base implementation when the view is enabled.

Issues Fixed

Fixes #19771

Platforms Tested

  • Android
  • iOS
  • Windows (no changes)
  • Mac (MacCatalyst affected implicitly via iOS code path, not explicitly tested)
Code Review: ✅ Passed

Code Review: PR #31403

🟡 Suggestions


1. iOS: ViewExtensions.UpdateIsEnabled — Change is broader than described

File: src/Core/src/Platform/iOS/ViewExtensions.cs

Problem:
The fix sets UserInteractionEnabled = view.IsEnabled for all non-UIControl UIViews, not just UICollectionView. The description says "non-UIControl views such as UICollectionView", but this will also affect any other MAUI control backed by a non-UIControl native view (e.g., WKWebView, MKMapView, custom views, etc.) that previously had no IsEnabled handling.

Previously these views silently returned (no-op). Now they will have UserInteractionEnabled toggled when IsEnabled changes.

This is likely the correct intended behavior — disabling interaction should work for all views — but it is a behavioral change for any non-UIControl UIView beyond UICollectionView. This broader impact should be acknowledged in the PR description.

Current code:

else
{
    // Non-UIControl views (like UICollectionView) only get interaction disable
    platformView.UserInteractionEnabled = view.IsEnabled;
}

Recommendation: The code logic is sound. Update the PR description to note this is a general fix for all non-UIControl views, not CollectionView-specific.


2. iOS/MacCatalyst: Title and description omit MacCatalyst

File: src/Core/src/Platform/iOS/ViewExtensions.cs

Problem:
The Platform/iOS/ folder compiles for both iOS and MacCatalyst. The title [iOS, Android] and platform checklist don't mention MacCatalyst, even though it benefits from (and is affected by) the same fix.

Recommendation: Update title to [iOS, MacCatalyst, Android] or add a note in the description that MacCatalyst is also covered.


3. Test: Mixed indentation (tabs vs spaces)

File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19771.cs

Problem:
The test method mixes tabs and 4-space indentation. The MAUI codebase uses tabs.

    App.WaitForElement("Item 1");
    App.Tap("Item 1");
        App.WaitForElement("DisableButton");   // ← 4 extra spaces (not tabs)
        App.Tap("DisableButton");              // ← 4 extra spaces (not tabs)
        App.WaitForElement("Item 3");          // ← 4 extra spaces (not tabs)
    App.Tap("Item 3");

Recommendation: Normalize to tabs throughout the test method.


4. Test: Missing newline at end of file

File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19771.cs

Problem:
The file is missing a newline at end of file (No newline at end of file in the diff).

Recommendation: Add a trailing newline.


5. Test: Scroll interaction not validated

File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19771.cs

Problem:
The Android fix intercepts both OnInterceptTouchEvent (which blocks child taps AND scrolling) and OnTouchEvent (which blocks RecyclerView's own scroll/fling handling). However, the test only validates that item selection is blocked — it does not test that scrolling is also blocked when disabled.

Recommendation: Consider adding a scroll-then-verify test step, or at minimum document in a comment that the fix also blocks scrolling even though the test only validates selection.


6. Test: No coverage for re-enabling

File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19771.cs

Problem:
The test verifies that interactions are blocked when IsEnabled = false, but does not verify that interactions resume when IsEnabled is set back to true. Re-enabling is equally important behavior to validate.

Recommendation: Add a test case (or extend the existing test) that:

  1. Disables the CollectionView
  2. Verifies interaction is blocked
  3. Re-enables the CollectionView
  4. Verifies interaction works again

✅ Looks Good

  • Android touch interception pattern is correctOnInterceptTouchEvent returning true + OnTouchEvent returning false is the standard Android idiom for fully blocking touch on a ViewGroup and its children.
  • ItemsView?.IsEnabled == false null-safe check — correctly handles the case where ItemsView is null (e.g., view disconnected).
  • PublicAPI.Unshipped.txt updated — the two new public override methods on MauiRecyclerView<TItemsView, TAdapter, TItemsViewSource> are correctly registered as unshipped public API.
  • UI test structure is correctIssue19771 HostApp page and test class follow project conventions; [Category(UITestCategories.CollectionView)] is appropriate.
  • Test assertion logic is correct — tapping once while enabled (count = 1), disabling, tapping again (should be blocked), and asserting count is still 1 correctly validates the fix.

@rmarinho rmarinho added s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-fix-lose Author adopted the agent's fix and it turned out to be bad s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Feb 16, 2026
@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented Feb 16, 2026

Looks like it is correct:

Looking at platform conventions:

iOS: Disabled UIControl typically blocks ALL interactions including scrolling
Android: Disabled views typically block ALL interactions
MAUI: Other controls with IsEnabled=false block all interactions

@kubaflo kubaflo added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-fix-lose Author adopted the agent's fix and it turned out to be bad labels Feb 20, 2026
@kubaflo kubaflo changed the base branch from main to inflight/current February 24, 2026 20:48
@kubaflo kubaflo merged commit 59583ad into dotnet:inflight/current Feb 24, 2026
122 of 194 checks passed
jfversluis pushed a commit that referenced this pull request Mar 2, 2026
…teractions (#31403)

### Root Cause

**iOS**
The underlying `UICollectionView` does not inherit from `UIControl`, so
it has no native Enabled property. In `ViewExtensions.UpdateIsEnabled`,
this caused an early return for non-UIControl views, leaving touch
interactions active when `IsEnabled = false`.

**Android**
`RecyclerView` does not support a native enabled/disabled state. While
`UpdateIsEnabled` is called when `IsEnabled = false`, there was no
platform-specific handling, so touch interactions remained functional.
 
### Description of Change

**iOS**
Modified `ViewExtensions.UpdateIsEnabled` to branch between UIControl
and non-UIControl views. For UIControl, the native Enabled property is
applied to block interactions and provide visual feedback. For
non-UIControl views such as `UICollectionView`, `UserInteractionEnabled`
is set to disable touch input while preserving visual appearance.

**Android**
Enhanced `MauiRecyclerView` with touch event overrides to handle the
disabled state. `OnInterceptTouchEvent` returns true when the
CollectionView is disabled, blocking child interactions. `OnTouchEvent`
returns false to prevent `RecyclerView` itself from processing gestures.
Both methods check `ItemsView?.IsEnabled` to ensure correct state
handling.
 
### Issues Fixed
Fixes #19771 
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Output Video
Before Issue Fix | After Issue Fix |
|----------|----------|
|<video width="40" height="60" alt="Before Fix"
src="https://github.com/user-attachments/assets/2bab10f4-f614-4457-a97b-193e1abab866">|<video
width="50" height="40" alt="After Fix"
src="https://github.com/user-attachments/assets/ed8e29f2-5bd6-4365-a928-cfca67a4ae6e">|
jfversluis pushed a commit that referenced this pull request Mar 2, 2026
…teractions (#31403)

### Root Cause

**iOS**
The underlying `UICollectionView` does not inherit from `UIControl`, so
it has no native Enabled property. In `ViewExtensions.UpdateIsEnabled`,
this caused an early return for non-UIControl views, leaving touch
interactions active when `IsEnabled = false`.

**Android**
`RecyclerView` does not support a native enabled/disabled state. While
`UpdateIsEnabled` is called when `IsEnabled = false`, there was no
platform-specific handling, so touch interactions remained functional.
 
### Description of Change

**iOS**
Modified `ViewExtensions.UpdateIsEnabled` to branch between UIControl
and non-UIControl views. For UIControl, the native Enabled property is
applied to block interactions and provide visual feedback. For
non-UIControl views such as `UICollectionView`, `UserInteractionEnabled`
is set to disable touch input while preserving visual appearance.

**Android**
Enhanced `MauiRecyclerView` with touch event overrides to handle the
disabled state. `OnInterceptTouchEvent` returns true when the
CollectionView is disabled, blocking child interactions. `OnTouchEvent`
returns false to prevent `RecyclerView` itself from processing gestures.
Both methods check `ItemsView?.IsEnabled` to ensure correct state
handling.
 
### Issues Fixed
Fixes #19771 
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Output Video
Before Issue Fix | After Issue Fix |
|----------|----------|
|<video width="40" height="60" alt="Before Fix"
src="https://github.com/user-attachments/assets/2bab10f4-f614-4457-a97b-193e1abab866">|<video
width="50" height="40" alt="After Fix"
src="https://github.com/user-attachments/assets/ed8e29f2-5bd6-4365-a928-cfca67a4ae6e">|
github-actions bot pushed a commit that referenced this pull request Mar 3, 2026
…teractions (#31403)

### Root Cause

**iOS**
The underlying `UICollectionView` does not inherit from `UIControl`, so
it has no native Enabled property. In `ViewExtensions.UpdateIsEnabled`,
this caused an early return for non-UIControl views, leaving touch
interactions active when `IsEnabled = false`.

**Android**
`RecyclerView` does not support a native enabled/disabled state. While
`UpdateIsEnabled` is called when `IsEnabled = false`, there was no
platform-specific handling, so touch interactions remained functional.
 
### Description of Change

**iOS**
Modified `ViewExtensions.UpdateIsEnabled` to branch between UIControl
and non-UIControl views. For UIControl, the native Enabled property is
applied to block interactions and provide visual feedback. For
non-UIControl views such as `UICollectionView`, `UserInteractionEnabled`
is set to disable touch input while preserving visual appearance.

**Android**
Enhanced `MauiRecyclerView` with touch event overrides to handle the
disabled state. `OnInterceptTouchEvent` returns true when the
CollectionView is disabled, blocking child interactions. `OnTouchEvent`
returns false to prevent `RecyclerView` itself from processing gestures.
Both methods check `ItemsView?.IsEnabled` to ensure correct state
handling.
 
### Issues Fixed
Fixes #19771 
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Output Video
Before Issue Fix | After Issue Fix |
|----------|----------|
|<video width="40" height="60" alt="Before Fix"
src="https://github.com/user-attachments/assets/2bab10f4-f614-4457-a97b-193e1abab866">|<video
width="50" height="40" alt="After Fix"
src="https://github.com/user-attachments/assets/ed8e29f2-5bd6-4365-a928-cfca67a4ae6e">|
HarishKumarSF4517 pushed a commit to HarishKumarSF4517/maui that referenced this pull request Mar 5, 2026
…teractions (dotnet#31403)

### Root Cause

**iOS**
The underlying `UICollectionView` does not inherit from `UIControl`, so
it has no native Enabled property. In `ViewExtensions.UpdateIsEnabled`,
this caused an early return for non-UIControl views, leaving touch
interactions active when `IsEnabled = false`.

**Android**
`RecyclerView` does not support a native enabled/disabled state. While
`UpdateIsEnabled` is called when `IsEnabled = false`, there was no
platform-specific handling, so touch interactions remained functional.
 
### Description of Change

**iOS**
Modified `ViewExtensions.UpdateIsEnabled` to branch between UIControl
and non-UIControl views. For UIControl, the native Enabled property is
applied to block interactions and provide visual feedback. For
non-UIControl views such as `UICollectionView`, `UserInteractionEnabled`
is set to disable touch input while preserving visual appearance.

**Android**
Enhanced `MauiRecyclerView` with touch event overrides to handle the
disabled state. `OnInterceptTouchEvent` returns true when the
CollectionView is disabled, blocking child interactions. `OnTouchEvent`
returns false to prevent `RecyclerView` itself from processing gestures.
Both methods check `ItemsView?.IsEnabled` to ensure correct state
handling.
 
### Issues Fixed
Fixes dotnet#19771 
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Output Video
Before Issue Fix | After Issue Fix |
|----------|----------|
|<video width="40" height="60" alt="Before Fix"
src="https://github.com/user-attachments/assets/2bab10f4-f614-4457-a97b-193e1abab866">|<video
width="50" height="40" alt="After Fix"
src="https://github.com/user-attachments/assets/ed8e29f2-5bd6-4365-a928-cfca67a4ae6e">|
github-actions bot pushed a commit that referenced this pull request Mar 6, 2026
…teractions (#31403)

### Root Cause

**iOS**
The underlying `UICollectionView` does not inherit from `UIControl`, so
it has no native Enabled property. In `ViewExtensions.UpdateIsEnabled`,
this caused an early return for non-UIControl views, leaving touch
interactions active when `IsEnabled = false`.

**Android**
`RecyclerView` does not support a native enabled/disabled state. While
`UpdateIsEnabled` is called when `IsEnabled = false`, there was no
platform-specific handling, so touch interactions remained functional.
 
### Description of Change

**iOS**
Modified `ViewExtensions.UpdateIsEnabled` to branch between UIControl
and non-UIControl views. For UIControl, the native Enabled property is
applied to block interactions and provide visual feedback. For
non-UIControl views such as `UICollectionView`, `UserInteractionEnabled`
is set to disable touch input while preserving visual appearance.

**Android**
Enhanced `MauiRecyclerView` with touch event overrides to handle the
disabled state. `OnInterceptTouchEvent` returns true when the
CollectionView is disabled, blocking child interactions. `OnTouchEvent`
returns false to prevent `RecyclerView` itself from processing gestures.
Both methods check `ItemsView?.IsEnabled` to ensure correct state
handling.
 
### Issues Fixed
Fixes #19771 
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Output Video
Before Issue Fix | After Issue Fix |
|----------|----------|
|<video width="40" height="60" alt="Before Fix"
src="https://github.com/user-attachments/assets/2bab10f4-f614-4457-a97b-193e1abab866">|<video
width="50" height="40" alt="After Fix"
src="https://github.com/user-attachments/assets/ed8e29f2-5bd6-4365-a928-cfca67a4ae6e">|
PureWeen added a commit that referenced this pull request Mar 11, 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 46 commits with various improvements,
bug fixes, and enhancements.


## Button
- [Android] Implemented material3 support for Button by @Dhivya-SF4094
in #33173
  <details>
  <summary>🔧 Fixes</summary>

- [Implement Material3 support for
Button](#33172)
  </details>

## CollectionView
- [Android] Fix RemainingItemsThresholdReachedCommand not firing when
CollectionView has Header and Footer both defined by @SuthiYuvaraj in
#29618
  <details>
  <summary>🔧 Fixes</summary>

- [Android : RemainingItemsThresholdReachedCommand not firing when
CollectionVew has Header and Footer both
defined](#29588)
  </details>

- [iOS/MacCatalyst] Fix CollectionView ScrollTo for horizontal layouts
by @Shalini-Ashokan in #33853
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS/MacCatalyst] CollectionView ScrollTo does not work with
horizontal Layout](#33852)
  </details>

- [iOS & Mac] Fixed IndicatorView Size doesnt update dynamically by
@SubhikshaSf4851 in #31129
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS, Catalyst] IndicatorView.IndicatorSize does not update
dynamically at runtime](#31064)
  </details>

- [Android] Fix for CollectionView Scrolled event is triggered on the
initial app load. by @BagavathiPerumal in
#33558
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] CollectionView Scrolled event is triggered on the initial
app load.](#33333)
  </details>

- [iOS, Android] Fix for CollectionView IsEnabled=false allows touch
interactions by @praveenkumarkarunanithi in
#31403
  <details>
  <summary>🔧 Fixes</summary>

- [More issues with CollectionView IsEnabled, InputTransparent, Opacity
via Styles and code behind](#19771)
  </details>

- [iOS] Fix VerticalOffset Update When Modifying
CollectionView.ItemsSource While Scrolled by @devanathan-vaithiyanathan
in #34153
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS]VerticalOffset Not Reset to Zero After Clearing ItemSource in
CollectionView](#26798)
  </details>

## DateTimePicker
- [Android] Fix DatePicker MinimumDate/MaximumDate not updating
dynamically by @HarishwaranVijayakumar in
#33687
  <details>
  <summary>🔧 Fixes</summary>

- [[regression/8.0.3] [Android] DatePicker control minimum date
issue](#19256)
- [[Android] DatePicker does not update MinimumDate / MaximumDate in the
Popup when set in the viewmodel after first
opening](#33583)
  </details>

## Drawing
- Android drawable perf by @albyrock87 in
#31567

## Editor
- [Android] Implemented material3 support for Editor by
@SyedAbdulAzeemSF4852 in #33478
  <details>
  <summary>🔧 Fixes</summary>

- [Implement Material3 Support for
Editor](#33476)
  </details>

## Entry
- [iOS, Mac] Fix for CursorPosition not updating when typing into Entry
control by @SyedAbdulAzeemSF4852 in
#30505
  <details>
  <summary>🔧 Fixes</summary>

- [Entry control CursorPosition does not update on TextChanged event
[iOS Maui 8.0.7] ](#20911)
- [CursorPosition not calculated correctly on behaviors events for iOS
devices](#32483)
  </details>

## Flyoutpage
- [Android, Windows] Fix for FlyoutPage toolbar button not updating on
orientation change by @praveenkumarkarunanithi in
#31962
  <details>
  <summary>🔧 Fixes</summary>

- [Flyout page in Android does not show flyout button (burger)
consistently](#24468)
  </details>

- Fix for First Item in CollectionView Overlaps in FlyoutPage.Flyout on
iOS by @praveenkumarkarunanithi in
#29265
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] CollectionView not rendering first item correctly in
FlyoutPage.Flyout](#29170)
  </details>

## Image
- [Android] Fix excessive memory usage for stream and resource-based
image loading by @Shalini-Ashokan in
#33590
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Unexpected high Bitmap.ByteCount when loading image via
ImageSource.FromResource() or ImageSource.FromStream() in .NET
MAUI](#33239)
  </details>

- [Android] Fix for Resize method returns an image that has already been
disposed by @SyedAbdulAzeemSF4852 in
#29964
  <details>
  <summary>🔧 Fixes</summary>

- [In GraphicsView, the Resize method returns an image that has already
been disposed](#29961)
- [IIMage.Resize bugged
behaviour](#31103)
  </details>

## Label
- Fixed Label Span font property inheritance when applied via Style by
@SubhikshaSf4851 in #34110
  <details>
  <summary>🔧 Fixes</summary>

- [`Span` does not inherit text styling from `Label` if that styling is
applied using `Style` ](#21326)
  </details>

- [Android] Implemented material3 support for Label by
@SyedAbdulAzeemSF4852 in #33599
  <details>
  <summary>🔧 Fixes</summary>

- [Implement Material3 Support for
Label](#33598)
  </details>

## Map
- [Android] Fix Circle Stroke color is incorrectly updated as Fill
color. by @NirmalKumarYuvaraj in
#33643
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Circle Stroke color is incorrectly updated as Fill
color.](#33642)
  </details>

## Mediapicker
- [iOS] Fix: invoke MediaPicker completion handler after
DismissViewController by @yuriikyry4enko in
#34250
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Media Picker UIImagePickerController closing
issue](#21996)
  </details>

## Navigation
- Fix ContentPage memory leak on Android when using NavigationPage
modally (fixes #33918) by @brunck in
#34117
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Modal TabbedPage whose tabs are NavigationPage(ContentPage)
is retained after
PopModalAsync()](#33918)
  </details>

## Picker
- [Android] Implement material3 support for TimePicker by
@HarishwaranVijayakumar in #33646
  <details>
  <summary>🔧 Fixes</summary>

- [Implement Material3 support for
TimePicker](#33645)
  </details>

- [Android] Implemented Material3 support for Picker by
@SyedAbdulAzeemSF4852 in #33668
  <details>
  <summary>🔧 Fixes</summary>

- [Implement Material3 support for
Picker](#33665)
  </details>

## RadioButton
- [Android] Implemented material3 support for RadioButton by
@SyedAbdulAzeemSF4852 in #33468
  <details>
  <summary>🔧 Fixes</summary>

- [Implement Material3 Support for
RadioButton](#33467)
  </details>

## Setup
- Clarify MA003 error message by @jeremy-visionaid in
#34067
  <details>
  <summary>🔧 Fixes</summary>

- [MA003 false positive with
9.0.21](#26599)
  </details>

## Shell
- [Android] Fix TabBar FlowDirection not updating dynamically by
@SubhikshaSf4851 in #33091
  <details>
  <summary>🔧 Fixes</summary>

- [[Android, iOS] FlowDirection RTL is not updated dynamically on Shell
TabBar](#32993)
  </details>

- [Android] Fix page not disposed on Shell replace navigation by
@Vignesh-SF3580 in #33426
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] [Shell] replace navigation leaks current
page](#25134)
  </details>

- [Android] Fixed Shell flyout does not disable scrolling when
FlyoutVerticalScrollMode is set to Disabled by @NanthiniMahalingam in
#32734
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Shell.FlyoutVerticalScrollMode="Disabled" does not disable
scrolling](#32477)
  </details>

## Single Project
- Fix: Throw a clear error when an SVG lacks dimensions instead of a
NullReferenceException by @Shalini-Ashokan in
#33194
  <details>
  <summary>🔧 Fixes</summary>

- [MAUI Fails To Convert Valid SVG Files Into PNG Files (Object
reference not set to an instance of an
object)](#32460)
  </details>

## SwipeView
- [iOS] Fix SwipeView stays open on iOS after updating content by
@devanathan-vaithiyanathan in #31248
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] - Swipeview with collectionview
issue](#19541)
  </details>

## TabbedPage
- [Windows] Fixed IsEnabled Property not works on Tabs by
@NirmalKumarYuvaraj in #26728
  <details>
  <summary>🔧 Fixes</summary>

- [ShellContent IsEnabledProperty does not
work](#5161)
- [[Windows] Shell Tab IsEnabled Not
Working](#32996)
  </details>

- [Android] Fix NavigationBar overlapping StatusBar when NavigationBar
visibility changes by @Vignesh-SF3580 in
#33359
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] NavigationBar overlaps with StatusBar when mixing
HasNavigationBar=true/false in TabbedPage on Android 15 (API
35)](#33340)
  </details>

## Templates
- Fix for unable to open task using keyboard navigation on windows
platform by @SuthiYuvaraj in #33647
  <details>
  <summary>🔧 Fixes</summary>

- [Unable to open task using keyboard: A11y_.NET maui_User can get all
the insights of
Dashboard_Keyboard](#30787)
  </details>

## TitleView
- Fix for NavigationPage.TitleView does not expand with host window in
iPadOS 26+ by @SuthiYuvaraj in #33088

## Toolbar
- [iOS] Fix toolbar items ignoring BarTextColor on iOS/MacCatalyst 26+
by @Shalini-Ashokan in #34036
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS 26] ToolbarItem color with custom BarTextColor not
working](#33970)
  </details>

- [Android] Fix for ToolbarItem retaining the icon from the previous
page on Android when using NavigationPage. by @BagavathiPerumal in
#32311
  <details>
  <summary>🔧 Fixes</summary>

- [Toolbaritem keeps the icon of the previous page on Android, using
NavigationPage (not shell)](#31727)
  </details>

## WebView
- [Android] Fix WebView in a grid expands beyond it's cell by
@devanathan-vaithiyanathan in #32145
  <details>
  <summary>🔧 Fixes</summary>

- [Android - WebView in a grid expands beyond it's
cell](#32030)
  </details>

## Xaml
- ContentPresenter: Propagate binding context to children with explicit
TemplateBinding by @HarishwaranVijayakumar in
#30880
  <details>
  <summary>🔧 Fixes</summary>

- [Binding context in
ContentPresenter](#23797)
  </details>


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

- [Revert] ContentPresenter: Propagate binding context to children with
explicit TemplateBinding by @Ahamed-Ali in
#34332

</details>

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

- [Testing] Feature Matrix UITest Cases for Shell Flyout Page by
@NafeelaNazhir in #32525
- [Testing] Feature Matrix UITest Cases for Brushes by
@LogishaSelvarajSF4525 in #31833
- [Testing] Feature Matrix UITest Cases for BindableLayout by
@LogishaSelvarajSF4525 in #33108
- [Android] Add UI tests for Material 3 CheckBox by
@HarishwaranVijayakumar in #34126
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Add UI tests for Material 3
CheckBox](#34125)
  </details>
- [Testing] Feature Matrix UITest Cases for Shell Tabbed Page by
@NafeelaNazhir in #33159
- [Testing] Fixed Test case failure in PR 34294 - [03/2/2026] Candidate
- 1 by @TamilarasanSF4853 in #34334

</details>

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

- Bumps Syncfusion.Maui.Toolkit dependency to version 1.0.9 by
@PaulAndersonS in #34178
- Fix crash when closing Windows based app when using TitleBar by
@MFinkBK in #34032
  <details>
  <summary>🔧 Fixes</summary>

- [Unhandled exception "Value does not fall within the expected range"
when closing Windows app](#32194)
  </details>

</details>
**Full Changelog**:
main...inflight/candidate
@github-actions github-actions bot locked and limited conversation to collaborators Mar 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-controls-collectionview CollectionView, CarouselView, IndicatorView community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android platform/ios platform/macos macOS / Mac Catalyst s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

More issues with CollectionView IsEnabled, InputTransparent, Opacity via Styles and code behind

7 participants