Как изменить внешний вид MenuFlyout в Windows Phone?

1

Я читаю в основном всю эту статью, но я просто не могу узнать, как я могу изменить, например, переход на тему входа в MenuFlyout, как и в приложении календаря. Существует нечто похожее на горизонтальный поворот вместо стандартной анимации MenuFlyout.

Изображение 174551


<MenuFlyout>
   <MenuFlyout.MenuFlyoutPresenterStyle>
       <Style...../>
   </MenuFlyout.MenuFlyoutPresenterStyle>
   <MenuFlyoutItem Text="Test"/>
</MenuFlyout>

С#:

 MenuFlyout mf = (MenuFlyout)this.Resources["AddButtonFlyout"];
 mf.Placement = FlyoutPlacementMode.Bottom;
 mf.ShowAt(this.CommandBar);
Теги:
xaml
user-interface
windows-phone-8.1

1 ответ

4
Лучший ответ

MenuFlyout имеет стандартный стиль, который установлен для TargetType = "MenuFlyoutPresenter" и может быть найден в.. \Program Files (x86)\Windows Phone Kits\8.1\Include\abi\Xaml\Design\generic.xaml (я не буду скопируйте/вставьте сюда, потому что он довольно длинный). Этот стиль определяет ControlTemplate, который вы можете изменить, чтобы указать, как работает MenuFlyout при его изменении в BottomPortrait VisualState.

Из того, что я вижу в приложении "Календарь", функция MenuFlyout переворачивается при ее открытии. В предопределенном стиле он сначала отображает верхнюю границу, а затем рисует остальную часть сверху вниз.

Итак, прежде всего вам нужно скопировать весь стиль в свои ресурсы. Затем вам нужно найти BottomPortrait VisualState и очистить все от раскадровки, чтобы иметь возможность определять свои собственные с нуля.

Я буду использовать класс PlaneProjection - он дает такой вид 3D-эффекта, который вы ищете. Я добавил его к элементу CenterBorder Border и установил значение по умолчанию на -90. Я установил его на -90, потому что это означает, что он перпендикулярен экрану, и MenuFlyout, следовательно, не отображается при первом показе.

// ... rest of the code
<Border x:Name="CenterBorder" FlowDirection="LeftToRight" BorderBrush="{TemplateBinding Background}">
    <Border.Projection>
        <PlaneProjection RotationX="-90"/>
    </Border.Projection>
// ... rest of the code

Следующий (и окончательный) шаг - определить новую раскадровку в BottomPortrait VisualState, как упоминалось ранее, - и это действительно просто:

// ... rest of the code
<VisualState x:Name="BottomPortrait">
    <Storyboard>
        <DoubleAnimation Duration="0:0:0.18" 
                         To="0" 
                         Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" 
                         Storyboard.TargetName="CenterBorder" />
     </Storyboard>
</VisualState>
// ... rest of the code

Он просто анимирует границу с -90 до 0 градусов за очень короткий промежуток времени, что позволяет перейти от невидимого к видимому с приятной флип-анимацией, что и есть то, что вы ищете.

Стиль (с нерелевантными частями, опущенными для краткости - вы все равно должны их иметь!):

<Style TargetType="MenuFlyoutPresenter">
    <!-- OTHER PROPERTY SETTERS -->
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="MenuFlyoutPresenter">
                <Border x:Name="OuterBorder" FlowDirection="LeftToRight" BorderBrush="{TemplateBinding BorderBrush}">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="PlacementStates">
                            <VisualState x:Name="None" />
                            <VisualState x:Name="TopPortrait">
                                <!-- TOP PORTRAIT STORYBOARD -->
                            </VisualState>
                            <VisualState x:Name="BottomPortrait">
                                <Storyboard>
                                    <DoubleAnimation Duration="0:0:0.18" 
                                                     To="0" 
                                                     Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" 
                                                     Storyboard.TargetName="CenterBorder" />
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="LeftLandscape">
                                <!-- LEFT LANDSCAPE STORYBOARD -->
                            </VisualState>
                            <VisualState x:Name="RightLandscape">
                                <!-- RIGHT LANDSCAPE STORYBOARD -->
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border.RenderTransform>
                        <ScaleTransform x:Name="OuterScaleTransform" />
                    </Border.RenderTransform>
                    <Border x:Name="CenterBorder" FlowDirection="LeftToRight" BorderBrush="{TemplateBinding Background}">
                        <Border.Projection>
                            <PlaneProjection RotationX="-90"/>
                        </Border.Projection>
                        <StackPanel x:Name="InnerBorder" FlowDirection="{TemplateBinding FlowDirection}" Background="{TemplateBinding Background}">
                            <StackPanel.RenderTransform>
                                <ScaleTransform x:Name="InnerScaleTransform" />
                            </StackPanel.RenderTransform>
                            <ItemsPresenter x:Name="ItemsPresenter" Margin="{TemplateBinding Padding}" FlowDirection="{TemplateBinding FlowDirection}" />
                        </StackPanel>
                    </Border>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

РЕДАКТИРОВАТЬ:

Отображение MenuFlyout лучше всего делать на фрейме.

MenuFlyout mf = (MenuFlyout)this.Resources["AddButtonFlyout"];
mf.Placement = FlyoutPlacementMode.Bottom;

Frame fr = Window.Current.Content as Frame;
mf.ShowAt(fr);
  • 0
    Спасибо, но я почти уверен, что сделал что-то не так, потому что с этим стилем ничего не появляется, только остальная часть пользовательского интерфейса немного уменьшается. Я отредактировал свой вопрос, чтобы показать, что я пытался.
  • 0
    @ Cort3vl Вы установили размещение MenuFlyout в FlyoutPlacementMode.Bottom?
Показать ещё 8 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню