Как изменить кнопку для поддержки мультитач на Windows Phone? - PullRequest
3 голосов
/ 05 сентября 2011

Мне нужна кнопка, которая реагирует на события Touch.FrameReported Up & Down вместо обычных событий MouseDown и MouseUp, которые можно было бы использовать, чтобы эту кнопку можно было одновременно использовать в Windows Phone в качестве другой кнопки.
У меня уже есть пользовательский элемент управления Button с состояниями MouseDown и MouseUp, но я не уверен, как заставить события «Вверх» и «Вниз» вызвать правильный взгляд - возможно, что-то с установленным VisualStateManager необходимо, но не могу понять, как его использовать - решениенеобходимо использовать стандартный элемент управления Button, поскольку я просто расширяю его для двух состояний - в качестве элемента управления кнопками с нормальным и «нажатым» состоянием.
Это для игрового экрана в более крупном проекте Silverlight, остальныепроект является стандартным Silverlight со стандартными кнопками и их нормальным поведением, однако в одном месте это должен быть Multitouch, поэтому это не может быть проект XNA, так как для этого потребуется перенести 99% приложения на XNA, где другие используемые функции не поддерживаютсяЯ смог расширить пользовательские элементы управления для поддержки мультитач, но хочу, чтобы кнопка реагировала и таким образом - плюс я уверен, что это будет полезно для других, особенно потому, что это, скорее всего, относится к разработке под Windows 7/8.тоже.


Редактировать: Вот код и Generic.xaml для моей кнопки с нормальным поведением (OnMouseUp / OnMouseDown)

Код:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Windows.Input;
using System.Diagnostics;

namespace UXLibrary
{
    [TemplatePart(Name = "Pressed", Type = typeof(BitmapSource))]
    [TemplatePart(Name = "Normal", Type = typeof(BitmapSource))]
    public class UXButton : Button
    {
        public static readonly DependencyProperty  PressedProperty =
        DependencyProperty.Register("Pressed", typeof(BitmapSource),
        typeof(UXButton), null);

        public static readonly DependencyProperty NormalProperty =
        DependencyProperty.Register("Normal", typeof(BitmapSource),
        typeof(UXButton), null);

        public BitmapSource Pressed
        {
            get { return (BitmapSource)GetValue(PressedProperty); }
            set { SetValue(PressedProperty, value); }
        }

        public BitmapSource Normal
        {
            get { return (BitmapSource)GetValue(NormalProperty); }
            set { SetValue(NormalProperty, value); }
        }

        /// <summary>Constructor</summary>
        public UXButton()
        {
            DefaultStyleKey = typeof(UXButton);
        }

        /// <summary>OnApplyTemplate</summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();     
        }

    }
}

Generic.xaml

<Style TargetType="local:UXButton">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:UXButton">
                    <Grid>
                        <vsm:VisualStateManager.VisualStateGroups>
                            <vsm:VisualStateGroup x:Name="CommonStates">
                                <vsm:VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <DoubleAnimation Duration="0" Storyboard.TargetName="NormalImage" Storyboard.TargetProperty="(UIElement.Opacity)" To="0.5"/>
                                    </Storyboard>
                                </vsm:VisualState>
                                <vsm:VisualState x:Name="Normal">
                                    <Storyboard>
                                        <DoubleAnimation Duration="0" Storyboard.TargetName="NormalImage" Storyboard.TargetProperty="(UIElement.Opacity)" To="1"/>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PressedImage" Storyboard.TargetProperty="(UIElement.Visibility)">
                                            <ObjectAnimationUsingKeyFrames.KeyFrames>
                                                <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Collapsed</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames.KeyFrames>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalImage" Storyboard.TargetProperty="(UIElement.Visibility)">
                                            <ObjectAnimationUsingKeyFrames.KeyFrames>
                                                <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Visible</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames.KeyFrames>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                                <vsm:VisualState x:Name="MouseOver"/>
                                <vsm:VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <DoubleAnimation Duration="0" Storyboard.TargetName="NormalImage" Storyboard.TargetProperty="(UIElement.Opacity)" To="1"/>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PressedImage" Storyboard.TargetProperty="(UIElement.Visibility)">
                                            <ObjectAnimationUsingKeyFrames.KeyFrames>
                                                <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Visible</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames.KeyFrames>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalImage" Storyboard.TargetProperty="(UIElement.Visibility)">
                                            <ObjectAnimationUsingKeyFrames.KeyFrames>
                                                <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Collapsed</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames.KeyFrames>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                            </vsm:VisualStateGroup>
                            <vsm:VisualStateGroup x:Name="FocusStates">
                                <vsm:VisualState x:Name="Focused"/>
                                <vsm:VisualState x:Name="Unfocused"/>
                            </vsm:VisualStateGroup>
                        </vsm:VisualStateManager.VisualStateGroups>
                        <Image x:Name="PressedImage" Stretch="Uniform" Source="{TemplateBinding Pressed}"/>
                        <Image x:Name="NormalImage" Stretch="Uniform" Source="{TemplateBinding Normal}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Решение

<Style TargetType="local:UXButton">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:UXButton">
                    <Grid>
                        <vsm:VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="MultiTouchStates">
                                <vsm:VisualState x:Name="Normal">
                                    <Storyboard>
                                        <DoubleAnimation Duration="0" Storyboard.TargetName="NormalImage" Storyboard.TargetProperty="(UIElement.Opacity)" To="1"/>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PressedImage" Storyboard.TargetProperty="(UIElement.Visibility)">
                                            <ObjectAnimationUsingKeyFrames.KeyFrames>
                                                <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Collapsed</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames.KeyFrames>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalImage" Storyboard.TargetProperty="(UIElement.Visibility)">
                                            <ObjectAnimationUsingKeyFrames.KeyFrames>
                                                <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Visible</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames.KeyFrames>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                                <VisualState x:Name="SpecialTouch">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="PressedImage">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Visible</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="NormalImage">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Collapsed</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </vsm:VisualStateManager.VisualStateGroups>
                        <Image x:Name="PressedImage" Stretch="Uniform" Source="{TemplateBinding Pressed}"/>
                        <Image x:Name="NormalImage" Stretch="Uniform" Source="{TemplateBinding Normal}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Код:

/// <summary>Button</summary>
[TemplatePart(Name = "Wrapper", Type = typeof(Grid))]
[TemplateVisualState(Name = "SpecialTouch", GroupName = "MultiTouchStates")]
public class UXButton : Button
{
    public static readonly DependencyProperty PressedProperty =
    DependencyProperty.Register("Pressed", typeof(BitmapSource),
    typeof(UXButton), null);

    public static readonly DependencyProperty NormalProperty =
    DependencyProperty.Register("Normal", typeof(BitmapSource),
    typeof(UXButton), null);

    public BitmapSource Pressed
    {
        get { return (BitmapSource)GetValue(PressedProperty); }
        set { SetValue(PressedProperty, value); }
    }

    public BitmapSource Normal
    {
        get { return (BitmapSource)GetValue(NormalProperty); }
        set { SetValue(NormalProperty, value); }
    }

    /// <summary>Constructor</summary>
    public UXButton()
    {
        DefaultStyleKey = typeof(UXButton);

    }

    /// <summary>OnApplyTemplate</summary>
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        Touch.FrameReported += (object sender, TouchFrameEventArgs e) =>
        {
            Image pressed = (Image)GetTemplateChild("PressedImage");
            Image normal = (Image)GetTemplateChild("NormalImage");
            TouchPointCollection points = e.GetTouchPoints(null);
            foreach (TouchPoint point in points)
            {
                if (point.Action == TouchAction.Down && (point.TouchDevice.DirectlyOver == normal || point.TouchDevice.DirectlyOver == pressed))
                {
                    VisualStateManager.GoToState(this, "SpecialTouch", false);
                }
                else if (point.Action == TouchAction.Up)
                {
                    VisualStateManager.GoToState(this, "Normal", false);
                }
            } 
        };
    }
}

1 Ответ

3 голосов
/ 13 сентября 2011

Если я правильно понимаю ваш вопрос, я думаю, вам нужно создать еще одно визуальное состояние, а не две части («нажата» и «нормальна»).

// UPDATE: you need to get the Grid in order to know the touch area
[TemplatePart(Name = "Wrapper", Type = typeof(Grid))]
[TemplateVisualState(Name = "SpecialTouch", GroupName = "MultiTouchStates")]
public class UXButton : Button

Затем в конструкторе вашей пользовательской кнопки подпишитесь на событие FrameReported,

    public UXButton()
    {
        DefaultStyleKey = typeof(UXButton);

        Touch.FrameReported += new TouchFrameEventHandler(Touch_FrameReported);
    }

    void Touch_FrameReported(object sender, TouchFrameEventArgs e)
    {
        // UPDATE: get the Grid
        var wrapper = GetTemplateChild("Wrapper") as Grid;

        TouchPointCollection points = e.GetTouchPoints(null);

        foreach (TouchPoint point in points)
        {
            // UPDATE: also do the touch area check here
            // specify what touch you want
            if (point.Action == TouchAction.Down && point.TouchDevice.DirectlyOver == wrapper)
            {
                VisualStateManager.GoToState(this, "SpecialTouch", false);
            }
        }
    }

Затем в стиле вы делаете скрытие и показывает изображения в этом визуальном состоянии, которое вы только что создали. Если вы хотите иметь возможность динамически изменять обычные и сжатые изображения, конечно, вы можете просто добавить свои TemplateParts обратно.

ОБНОВЛЕНИЕ: Также вам нужно дать корневому элементу, который является Сетка, имя и цвет фона, как это,

<Grid x:Name="Wrapper" Background="Transparent">

                        <VisualStateGroup x:Name="MultiTouchStates">
                            <VisualState x:Name="SpecialTouch">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="PressedImage">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="NormalImage">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Collapsed</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>

Надеюсь, это поможет.

...