[net11.0][iOS/macOS] Fix CollectionView, RefreshView, and ScrollView interaction state after IsEnabled toggles - #36784
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 36784Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 36784" |
|
Azure Pipelines: Successfully started running 1 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
|
/azp run |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
This PR forward-ports the iOS/Mac Catalyst interaction fix to net11.0, ensuring InputTransparent is respected when IsEnabled changes (including for wrapper/container hit-testing). This prevents input-transparent layouts from becoming touch-blocking after a parent IsEnabled toggle.
Changes:
- Update iOS
UpdateIsEnabledfor non-UIControlviews to respectInputTransparentwhen settingUserInteractionEnabled. - Update iOS
UpdateInputTransparentto keep non-UIControlinteraction consistent with bothIsEnabledandInputTransparent. - Add iOS device tests covering
IsEnabled/InputTransparentcombinations and container (WrapperView) hit-testing synchronization.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/Core/tests/DeviceTests/Handlers/View/ViewHandlerTests.iOS.cs | Adds iOS device tests validating interaction behavior for non-UIControl views and WrapperView containers across IsEnabled toggles. |
| src/Core/src/Platform/iOS/ViewExtensions.cs | Ensures UserInteractionEnabled updates for non-UIControl views account for both IsEnabled and InputTransparent. |
| src/Core/src/Handlers/View/ViewHandler.cs | Keeps WrapperView container hit-testing synchronized when IsEnabled changes or a container is created (iOS/Mac Catalyst). |
#36784 review) ViewHandler.MapIsEnabled synchronizes the WrapperView container's hit-testing via MapInputTransparentToContainer, but ScrollView/SearchBar/Editor/RefreshView replace the IsEnabled mapper on iOS and only updated the inner platform view. So an iOS ScrollView/Editor/SearchBar/RefreshView that gets a WrapperView container (Clip, Shadow, or Border) kept the container hit-testable after IsEnabled=false, preserving the reachability bug for those controls (MauiBot NEEDS_CHANGES finding). Expose MapInputTransparentToContainer as internal and call it from each override's iOS MapIsEnabled so the container tracks IsEnabled/InputTransparent uniformly. Add a ScrollView device test asserting the container's UserInteractionEnabled follows IsEnabled through the override mapper. Also fix the stale non-UIControl comment in ViewExtensions (it now combines IsEnabled && !InputTransparent) and the missing trailing newline in ViewHandlerTests.iOS.cs. Note: local net11.0-ios build not feasible in this environment (CoreCLR/workload restore chain); relying on CI for the iOS build + device-test validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d00747b7-96f3-4e7a-8dfb-e3a48db04b2d
|
Addressed the review findings in
Note: I couldn't build net11.0-ios locally (CoreCLR/workload restore chain in this environment), so I'm relying on CI for the iOS build + device-test run. Ready for re-review — thanks! |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (4)
src/Core/src/Platform/iOS/ViewExtensions.cs:641
UpdateInputTransparent(UIView, handler, view)still has an early-return for non-editorITextInputwhich setsUserInteractionEnabledbased only onIsReadOnly/InputTransparentand ignoresview.IsEnabled. This can re-enable hit testing for disabled non-UIControltext inputs (and theirWrapperViewcontainers) whenInputTransparentor container mapping runs.
if (view is not IEditor && view is ITextInput textInput)
{
platformView.UpdateInputTransparent(textInput.IsReadOnly, view.InputTransparent);
return;
}
platformView.UpdateInteractionState(view);
}
src/Controls/src/Core/Handlers/Items/ItemsViewHandler.cs:35
- The
ItemsViewHandlermapper override forIsEnabledis guarded by#if IOS, butItemsViewHandler.iOS.csis compiled for both iOS and MacCatalyst. As written, MacCatalyst builds won’t callMapIsEnabled, so selection mode andUserInteractionEnabledsync won’t be updated there.
[Controls.ItemsView.ItemsUpdatingScrollModeProperty.PropertyName] = MapItemsUpdatingScrollMode,
#if IOS
[nameof(IView.IsEnabled)] = MapIsEnabled,
#endif
};
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34666.cs:24
- After scrolling, the test waits for the same element ("Baboon") that was already present before scrolling, so it no longer validates that the CollectionView actually scrolled. It should wait for an item that becomes visible only after scrolling (e.g., "Gelada").
public void CollectionViewScrollsWhenRefreshViewDisabled()
{
App.WaitForElement("Baboon");
App.ScrollDown("CollectionView");
App.ScrollDown("CollectionView");
App.WaitForElement("Baboon");
}
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34666.cs:1
- The file-level quarantine symbol was changed to
TEST_FAILS_ON_ANDROID, but the issue description (and HostApp issue metadata) indicates the scenario affects Windows as well. Consider using a combined guard so the intent stays accurate.
#if TEST_FAILS_ON_ANDROID
|
/azp run maui-pr |
|
/azp run maui-pr-devicetests |
|
/azp run maui-pr-uitests |
|
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command. |
2 similar comments
|
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command. |
|
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command. |
|
/azp run maui-pr |
|
/azp run maui-pr-devicetests |
|
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command. |
|
/azp run maui-pr-uitests |
|
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command. |
1 similar comment
|
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command. |
Respect InputTransparent when updating UserInteractionEnabled for non-UIControl iOS views so parent IsEnabled toggles do not make transparent layouts block touches. Keep disabled non-UIControl views from receiving interactions. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 1bf06fd)
Synchronize container hit testing when IsEnabled changes or a container is created. Move iOS interaction coverage from shared unit tests into Core device tests so the iOS target compiles it. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 0eba45a)
#36784 review) ViewHandler.MapIsEnabled synchronizes the WrapperView container's hit-testing via MapInputTransparentToContainer, but ScrollView/SearchBar/Editor/RefreshView replace the IsEnabled mapper on iOS and only updated the inner platform view. So an iOS ScrollView/Editor/SearchBar/RefreshView that gets a WrapperView container (Clip, Shadow, or Border) kept the container hit-testable after IsEnabled=false, preserving the reachability bug for those controls (MauiBot NEEDS_CHANGES finding). Expose MapInputTransparentToContainer as internal and call it from each override's iOS MapIsEnabled so the container tracks IsEnabled/InputTransparent uniformly. Add a ScrollView device test asserting the container's UserInteractionEnabled follows IsEnabled through the override mapper. Also fix the stale non-UIControl comment in ViewExtensions (it now combines IsEnabled && !InputTransparent) and the missing trailing newline in ViewHandlerTests.iOS.cs. Note: local net11.0-ios build not feasible in this environment (CoreCLR/workload restore chain); relying on CI for the iOS build + device-test validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d00747b7-96f3-4e7a-8dfb-e3a48db04b2d
…view) UpdateInputTransparent(UIView, handler, view) now factors IsEnabled for non-UIControl views, but its non-editor ITextInput early-return delegated to the (isReadOnly, inputTransparent) overload, which computes !(isReadOnly || inputTransparent) and ignores IsEnabled. When the container-sync path runs for a disabled non-UIControl text input (e.g. ISearchBar), its WrapperView container became hit-testable again, defeating the synchronization the previous commit added (Copilot follow-up finding). Compute the text-input case as IsEnabled && !(IsReadOnly || InputTransparent) so a disabled or input-transparent SearchBar/Entry (and its container) loses hit-testing, while enabled and read-only behavior is unchanged (editors remain excluded from this branch so read-only scrolling is preserved). Add a device test asserting a disabled SearchBar's WrapperView container is not interactive. Note: local net11.0-ios build not feasible here; relying on CI device tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d00747b7-96f3-4e7a-8dfb-e3a48db04b2d
Replace the PR-specific container workaround with the merged #36628 implementation. Route ScrollView, RefreshView, and both ItemsView handlers through ViewHandler.MapIsEnabled and share interaction-state calculation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 60fb173f-7de4-4b51-822d-b306a63c2bfc
ab92978 to
e3ef63a
Compare
|
/azp run maui-pr-devicetests |
|
/azp run maui-pr-uitests |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
1 similar comment
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
src/Core/src/Platform/iOS/ViewExtensions.cs:638
- In UpdateInputTransparent(UIView, handler, view), the non-editor ITextInput early-return sets UserInteractionEnabled via the (isReadOnly, inputTransparent) overload, which ignores view.IsEnabled. This can re-enable hit testing for disabled text inputs (and WrapperView containers) when InputTransparent/container mapping runs, leaving IsEnabled and interaction state out of sync.
if (view is not IEditor && view is ITextInput textInput)
{
platformView.UpdateInputTransparent(textInput.IsReadOnly, view.InputTransparent);
return;
}
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34666.cs:23
- After scrolling, the test waits for "Baboon" again, which is already present before scrolling and doesn't validate that scrolling succeeded. This makes the test non-assertive and could hide regressions in CollectionView scrolling when RefreshView is disabled.
App.WaitForElement("Baboon");
|
Fixed in SR10 so this pr is not needed |
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
Forward-ports #36305 and its follow-up regression fix from #36628 to
net11.0.UserInteractionEnabledcalculation soIsEnabledandInputTransparentremain synchronized.IsEnabledmappings throughViewHandler.MapIsEnabled, matching [inflight regression][iOS/macOS] Fix CollectionView, RefreshView, and ScrollView interaction state after IsEnabled toggles #36628.Issues Fixed
Addresses #36059 and #36501 for .NET 11.
Validation
dotnet build Microsoft.Maui.BuildTasks.slnf --no-restore --nologo -v:minimaldotnet build src/Controls/tests/TestCases.iOS.Tests/Controls.TestCases.iOS.Tests.csproj --no-restore --nologo -v:minimaldotnet build src/Core/tests/DeviceTests/Core.DeviceTests.csproj -p:TargetFramework=net11.0-ios -p:RuntimeIdentifier=iossimulator-arm64 --no-restore --nologo -v:minimal