.Net Maui(XAML)垂直GridView布局D-Pad导航

avwztpqn  于 2023-05-11  发布在  .NET
关注(0)|答案(1)|浏览(203)

我是Xamarin/.Net Maui开发的新手。我正在开发一个电影应用程序(最初将针对宽屏)。我试图创建一个可滚动的垂直网格视图,以显示类似于下面布局的电影列表

我开始使用CollectionView,但我没有接近所需的输出。我想有方向键(D-垫)的支持,使每个单独的项目可以使用D-垫重点。此外,网格中的每个项目需要点击,以便我可以导航到电影细节视图。同样,当项目被选中时,我需要以不同的方式设置该项目的样式(就像在图像中一样,所选项目具有白色背景)。
下面是我当前的XAML的样子

<CollectionView ItemSizingStrategy="MeasureAllItems"
                    ItemsLayout="VerticalGrid, 6"
                    ItemsSource="{Binding Movies}"
                    SelectedItem="{Binding SelectedMovie, Mode=TwoWay}"
                    SelectionMode="Single"
                    SelectionChangedCommand="{Binding GetMovieDetailsCommand}"
                    SelectionChangedCommandParameter="{Binding SelectedItem, Source={RelativeSource Self}}">                        
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <Grid Margin="10">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="200"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
                    <Image
                        AutomationId="ImageViewCell"
                        WidthRequest="500"
                        Source="{Binding PosterPath}" />
                    <StackLayout 
                        Grid.Row="1"
                        Margin="5" Orientation="Vertical">
                        <Label Text="{Binding Title}"
                            AutomationId="LabelTitle"
                            LineBreakMode="NoWrap"
                            Style="{DynamicResource ListItemTextStyle}"
                            FontSize="10" />
                    </StackLayout>
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>

下面是我的输出。

如果有人能指导我或为我提供一个如何实现此功能的示例,我将非常感激,这样我就可以使用D-Pad在项目之间导航,并在选择项目时垂直滚动。
谢谢

r55awzrz

r55awzrz1#

官方上,Maui.Net应用程序不支持Android TV D-Pad。这是一个非官方的方法来使它工作。
使用OnPageKeyDown方法创建Interface类(IPageKeyDown)类。

#if ANDROID
     using Android.Views;
    #endif
    namespace YourApp.Model
    {
        public interface IPageKeyDown
        {
           #if ANDROID       
              public bool OnPageKeyDown(Keycode keyCode, KeyEvent e);    
           #endif
        }
    }

在呈现集合视图的ViewPage中,添加以下代码。
首先,继承接口

public partial class ContentListPage : ContentPage<ContentViewModel>,IPageKeyDown

在ContentListPage中,实现带有所有键left、right、up、down和center事件的接口。
作为键右事件的一部分,从选定项开始将集合索引递增1。对于向左键事件,从所选索引递减1。对于向上和向下,按行中无项递增。此外,如果我们最终达到最大项目计数,请将所选索引重置为0。不要使用onselecteditemchanged事件,因为它将为每个D-PAD移动触发事件。相反,连接中心事件并调用项目选择逻辑以导航到其他页面。

#if ANDROID
        public bool OnPageKeyDown(Keycode keyCode, KeyEvent e)
        {
            index = 0;
            switch (keyCode)
            {
                case Keycode.DpadUp:                   
                        ExecuteDpadUp();                
                    break;
                case Keycode.DpadDown:                   
                        ExecuteDpadDown();
                    break;
                case Keycode.DpadLeft:                   
                        ExecuteDpadLeft();                    
                    break;
                case Keycode.DpadRight:                  
                        ExecuteDpadRight();                    
                    break;
                case Keycode.DpadCenter:                    
                        ExecuteDpadCenter();
                        break;
                default: break;
            }              
            return false;
        }
    #endif

 public void ExecuteDpadDown()
    {
        index = Math.Min(Math.Max(BindingContext.ContentModels.IndexOf(BindingContext.SelectedContentModel) + BindingContext.DefaultNoOfColumn, 0), BindingContext.ContentModels.Count - 1);
        BindingContext.SelectedContentModel = BindingContext.ContentModels[index];
    }

    public void ExecuteDpadLeft()
    {
        index = Math.Min(Math.Max(BindingContext.ContentModels.IndexOf(BindingContext.SelectedContentModel) - 1, 0), BindingContext.ContentModels.Count - 1);
        BindingContext.SelectedContentModel = BindingContext.ContentModels[index];
    }

    public void ExecuteDpadRight()
    {
        index = Math.Min(Math.Max(BindingContext.ContentModels.IndexOf(BindingContext.SelectedContentModel) + 1, 0), BindingContext.ContentModels.Count - 1);
        BindingContext.SelectedContentModel = BindingContext.ContentModels[index];
    }

    public void ExecuteDpadCenter()
    {       
        OnItemSelected();        
    }
    
    private async void OnItemSelected()
{
    var contentModel = BindingContext.SelectedContentModel;
    if (contentModel != null)
    {
        var navigationParameters = new Dictionary<string, object>();
        var stream = await BindingContext.FetchStream(contentModel.Id);
        if (contentModel.TargetType == typeof(StreamPage))
        {
            navigationParameters = new Dictionary<string, object>
            {
                { "stream", stream }
            };
        }           

        await Shell.Current.GoToAsync(contentModel.TargetType.Name, navigationParameters);
    }
}

要在D-Pad中导航时更改颜色,我们需要在Styles.Xaml中应用样式设置器

<Style TargetType="Grid" x:Key="GridItemStyle">
        <Setter Property="VisualStateManager.VisualStateGroups">
            <VisualStateGroupList>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="Selected">
                        <VisualState.Setters>
                            <Setter Property="BackgroundColor"
                                        Value="LightSkyBlue" />
                        </VisualState.Setters>
                    </VisualState>                        
                </VisualStateGroup>
            </VisualStateGroupList>
        </Setter>
    </Style>

最后,在Platforms/Android文件夹下的MainActivity.cs中,连接onkeydown事件。

public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent e)
    {
        Page p = Shell.Current.CurrentPage;

        if (p is IPageKeyDown)
        {
            bool handled =  (p as IPageKeyDown).OnPageKeyDown(keyCode, e);
            if (handled) return true;
        }

        return base.OnKeyDown(keyCode, e);
    }

相关问题