Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

[Spec] Add TouchStates To Visual State Manager #10314

Closed
PureWeen opened this issue Apr 13, 2020 · 1 comment
Closed

[Spec] Add TouchStates To Visual State Manager #10314

PureWeen opened this issue Apr 13, 2020 · 1 comment

Comments

@PureWeen
Copy link
Contributor

Additional credit for this spec should also go to Chase Florell, who provided the original proposal and proof-of-concept project.

#5494
#5494 (comment)

Existing work. Can we make this work match our existing spec?
#9740

Summary

The current implementation of the VisualStateManager is simple, allowing for three basic states of Normal, Disabled, and Focused. While these VisualStates may be useful, in the context of a Xamarin.Forms application, they do not handle the state of actively being pressed on by the user, or even unpressed and hover states. There is also the potential for multiple fingers touching the screen, as well. By extending the VSM's capabilities for handling these states, developers will be able to more easily implement complex touch or click-based behaviors in their applications, and set a foundation for other enhancements such as those discussed in issue #4232.

Supporting APIs

#3492

API

TouchState

[Flags]
public enum TouchState
{
    Entered = 1<<0,
    Exited = 1<<2,
    Cancelled = 1<<3,
    Failed = 1<<4,
    Changed = 1<<5,
    Pressed = 1<<6, 
    Released = 1<<7,
    Hover = 1<<8
}

TouchEventArgs

public class TouchEventArgs : EventArgs
{   
    public TouchState TouchState { get; }
    public IReadOnlyList<TouchPoint> TouchPoints { get; }
    public long Id { get; }
    public bool IsInContact { get; }
}

TouchPoint

public struct TouchPoint
{
    public Xamarin.Forms.Point Point { get; }
    public bool IsInOriginalView { get; }
}

Usage

The TouchState enum defines various states that can occur to the view, which apply to the VisualStates, such as the following:

<VisualStateGroup x:Name="PressedStates">
    <VisualState x:Name="Entered" />
    <VisualState x:Name="Exited" />
    <VisualState x:Name="Cancelled" />
    <VisualState x:Name="Failed" />
    <VisualState x:Name="Changed" />
    <VisualState x:Name="Pressed" />
    <VisualState x:Name="Released" />
    <VisualState x:Name="Hover" />
</VisualStateGroup>

A sample repo can be found here that provides a basic proof of concept for how developers can benefit from these additional states. Using the following snippet of code, while remaining in a pressed state, the bottom right square's text will rotate (as shown in the below GIF):

Note: As a proof-of-concept, this project uses Effects as the functionality is not built-in, as commented.

        <Grid Style="{StaticResource Grid}"
              BackgroundColor="White"
              HorizontalOptions="Center"
              VerticalOptions="Center"
              WidthRequest="400"
              HeightRequest="200">
            <!-- we could just as easily use the VisualElement.ObservesTouches property -->
            <!-- but this shows how we can do the same thing with a gesture recognizer -->
            <!-- also, if this lands in Xamarin.Forms, there's no need for the Effect-->
            <Grid.Effects>
                <pressed:TouchEffect Touched="TouchGestureRecognizer_OnTouched" />
            </Grid.Effects>
            <Grid.GestureRecognizers>
                <TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped" />
                <!-- adding this gesture recognizer would automatically toggle "VisualElement.ObservesTouches = true" for the View -->
                <pressed:TouchGestureRecognizer Command="{Binding OnTouchedCommand}" />
            </Grid.GestureRecognizers>

            <Label x:Name="InnerLabel" Style="{StaticResource TextStyle}">
                <Label.Text>
                Welcome to Xamarin.Forms!

                I Rotate!
                </Label.Text>
            </Label>
        </Grid>

        
    private async void RotateTheView(VisualElement element, TouchState touchState)
    {
        switch (touchState)
        {
            case TouchState.Pressed:
                _isPressed = true;
                break;
            case TouchState.Released:
                _isPressed = false;
                break;
            default: return;
        }

        while (_isPressed)
        {
            await element.RotateTo(360, 500, Easing.Linear);
            await element.RotateTo(0, 0); // reset to initial position
        }
    }

Image

Difficulty: Medium/High

@jfversluis
Copy link
Member

Thanks for this suggestion! As Xamarin.Forms is now in maintenance mode, this will not happen anymore for Xamarin.Forms. We're only adding bugfixes and stability fixes.

If this is still important to you, make sure to check the .NET MAUI repo and see if it's already on the roadmap. If not, feel free to open a discussion to discuss a change first or open an issue with a detailed feature request. Thanks!

@jfversluis jfversluis closed this as not planned Won't fix, can't repro, duplicate, stale Aug 23, 2022
# for free to subscribe to this conversation on GitHub. Already have an account? #.
Projects
None yet
Development

No branches or pull requests

2 participants