Skip to content

Commit

Permalink
chore: fix GridViewItem initial selection state
Browse files Browse the repository at this point in the history
  • Loading branch information
Xiaoy312 committed Oct 7, 2024
1 parent 27e0fed commit 22dddc7
Showing 1 changed file with 39 additions and 21 deletions.
60 changes: 39 additions & 21 deletions src/Uno.UI/UI/Xaml/Controls/Primitives/SelectorItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ public SelectorItem()
AddHandler(PointerCaptureLostEvent, _onPointerExitedOrCanceled, handledEventsToo: true);
}

protected override void OnApplyTemplate()
{
base.OnApplyTemplate();

UpdateVisualStates(false);
}

private protected Selector Selector => ItemsControl.ItemsControlFromItemContainer(this) as Selector;

internal override UIElement VisualParent => Selector ?? base.VisualParent;
Expand All @@ -108,8 +115,7 @@ private bool IsItemClickEnabled

private protected override void OnIsEnabledChanged(IsEnabledChangedEventArgs e)
{
var disabledStates = e.NewValue ? DisabledStates.Enabled : DisabledStates.Disabled;
VisualStateManager.GoToState(this, disabledStates, true);
UpdateDisabledStates(IsLoaded);

base.OnIsEnabledChanged(e);
}
Expand Down Expand Up @@ -140,28 +146,37 @@ internal void ApplyMultiSelectState(bool isSelectionMultiple)

partial void OnIsSelectedChangedPartial(bool oldIsSelected, bool newIsSelected)
{
UpdateCommonStates();
UpdateCommonStates(IsLoaded);
OnIsSelectedChanged();

Selector?.NotifyListItemSelected(this, oldIsSelected, newIsSelected);
}

internal protected virtual void OnIsSelectedChanged() { }

private void UpdateCommonStatesWithoutNeedsLayout(PointerDeviceType deviceType, ManipulationUpdateKind manipulationUpdate)
private void UpdateCommonStatesWithoutNeedsLayout(bool useTransitions, PointerDeviceType deviceType, ManipulationUpdateKind manipulationUpdate)
{
using (InterceptSetNeedsLayout())
{
UpdateCommonStates(deviceType == PointerDeviceType.Mouse, manipulationUpdate);
UpdateCommonStates(useTransitions, deviceType == PointerDeviceType.Mouse, manipulationUpdate);
}
}

private void UpdateVisualStates(bool useTransitions)
{
if (GetTemplateRoot() is { })
{
UpdateCommonStates(useTransitions);
UpdateDisabledStates(useTransitions);
}
}

private void UpdateCommonStates(bool isMouse = false, ManipulationUpdateKind manipulationUpdate = ManipulationUpdateKind.None)
private void UpdateCommonStates(bool useTransitions, bool isMouse = false, ManipulationUpdateKind manipulationUpdate = ManipulationUpdateKind.None)
{
// On Windows, the pressed state appears only after a few, and won't appear at all if you quickly start to scroll with the finger.
// So here we make sure to delay the beginning of a manipulation to match this behavior (and avoid flickering when scrolling)
// We also make sure that when user taps (Enter->Pressed->Move*->Release->Exit) on the item, he is able to see the pressed (selected) state.
var state = GetState(IsEnabled, IsSelected, IsPointerOver, _canRaiseClickOnPointerRelease);
var state = GetCommonState(IsEnabled, IsSelected, IsPointerOver, _canRaiseClickOnPointerRelease);
var requestId = ++_goToStateRequest; // Request ID is use to ensure to apply only the last requested state.

TimeSpan delay; // delay to apply the 'state'
Expand All @@ -172,9 +187,9 @@ private void UpdateCommonStates(bool isMouse = false, ManipulationUpdateKind man
{
// When clicked (i.e. pointer released), but not yet in pressed state, we force to go immediately in pressed state
// Then we let the standard go to state process (i.e. with delay handling) reach the final expected state.
var pressedState = GetState(IsEnabled, IsSelected, IsPointerOver, isPressed: true);
var pressedState = GetCommonState(IsEnabled, IsSelected, IsPointerOver, isPressed: true);
_currentState = pressedState;
VisualStateManager.GoToState(this, pressedState, true);
VisualStateManager.GoToState(this, pressedState, useTransitions);

_pauseStateUpdateUntil = _chronometer.Elapsed + MinTimeBetweenPressStates;

Expand All @@ -188,7 +203,7 @@ private void UpdateCommonStates(bool isMouse = false, ManipulationUpdateKind man
if (isMouse)
{
_currentState = state;
VisualStateManager.GoToState(this, state, true);
VisualStateManager.GoToState(this, state, useTransitions);
return;
}

Expand All @@ -204,7 +219,7 @@ private void UpdateCommonStates(bool isMouse = false, ManipulationUpdateKind man
if (delay <= TimeSpan.Zero)
{
_currentState = state;
VisualStateManager.GoToState(this, state, true);
VisualStateManager.GoToState(this, state, useTransitions);
}
else
{
Expand Down Expand Up @@ -234,7 +249,14 @@ private void UpdateCommonStates(bool isMouse = false, ManipulationUpdateKind man
}
}

private string GetState(bool isEnabled, bool isSelected, bool isOver, bool isPressed)
private void UpdateDisabledStates(bool useTransitions)
{
// TODO: This may need to be adjusted later when we remove the Visual State mixins.
var state = IsEnabled ? DisabledStates.Enabled : DisabledStates.Disabled;
VisualStateManager.GoToState(this, state, useTransitions);
}

private string GetCommonState(bool isEnabled, bool isSelected, bool isOver, bool isPressed)
{
var state = CommonStates.Normal;

Expand Down Expand Up @@ -293,11 +315,7 @@ private protected override void OnLoaded()
FocusableInTouchMode = true;
#endif

UpdateCommonStates();

// TODO: This may need to be adjusted later when we remove the Visual State mixins.
var state = IsEnabled ? DisabledStates.Enabled : DisabledStates.Disabled;
VisualStateManager.GoToState(this, state, true);
UpdateVisualStates(true);
}

#if __IOS__
Expand Down Expand Up @@ -329,7 +347,7 @@ internal void LegacySetPressed(bool isPressed)
protected override void OnPointerEntered(PointerRoutedEventArgs args)
{
base.OnPointerEntered(args);
UpdateCommonStatesWithoutNeedsLayout((global::Windows.Devices.Input.PointerDeviceType)args.Pointer.PointerDeviceType, ManipulationUpdateKind.Begin);
UpdateCommonStatesWithoutNeedsLayout(true, (PointerDeviceType)args.Pointer.PointerDeviceType, ManipulationUpdateKind.Begin);
}

/// <inheritdoc />
Expand All @@ -349,7 +367,7 @@ protected override void OnPointerPressed(PointerRoutedEventArgs args)
args.Handled = ShouldHandlePressed;

base.OnPointerPressed(args);
UpdateCommonStatesWithoutNeedsLayout((global::Windows.Devices.Input.PointerDeviceType)args.Pointer.PointerDeviceType, ManipulationUpdateKind.Begin);
UpdateCommonStatesWithoutNeedsLayout(true, (PointerDeviceType)args.Pointer.PointerDeviceType, ManipulationUpdateKind.Begin);
}

/// <inheritdoc />
Expand All @@ -374,7 +392,7 @@ private void OnPointerReleasedPrivate(PointerRoutedEventArgs args)
}

args.Handled = ShouldHandlePressed;
UpdateCommonStatesWithoutNeedsLayout((global::Windows.Devices.Input.PointerDeviceType)args.Pointer.PointerDeviceType, update);
UpdateCommonStatesWithoutNeedsLayout(true, (PointerDeviceType)args.Pointer.PointerDeviceType, update);
}
}

Expand All @@ -383,7 +401,7 @@ private void CleanUpPointerState(PointerRoutedEventArgs args)
{
// Not like a Button, if the pointer goes out of this item, we abort the ItemClick
_canRaiseClickOnPointerRelease = false;
UpdateCommonStatesWithoutNeedsLayout((global::Windows.Devices.Input.PointerDeviceType)args.Pointer.PointerDeviceType, ManipulationUpdateKind.End);
UpdateCommonStatesWithoutNeedsLayout(true, (PointerDeviceType)args.Pointer.PointerDeviceType, ManipulationUpdateKind.End);
}

protected override void OnGotFocus(RoutedEventArgs e)
Expand Down

0 comments on commit 22dddc7

Please sign in to comment.