【问题标题】:Keep bottom sheet on top of any pages in masterDetailPage Xamarin将底页保留在 masterDetailPage Xamarin 中任何页面的顶部
【发布时间】:2020-07-11 16:52:11
【问题描述】:

我对在 c# 中使用 xamarin 为 android 和 ios 开发应用程序非常陌生。所以我为我的音乐台创建了一个应用程序来播放音乐,它包含一个 MasterDetailPage。左上角是选择不同类型页面的菜单。但是我想在底部有一个静态的底部滑块表单,您可以在其中启动或停止必须一直显示的音乐,并在切换其他页面时继续播放。但我也想让用户可以选择向上滑动这个特定的表格,以查看正在播放的歌曲和其他一些信息。并且在浏览其他页面时必须继续播放音乐。 到目前为止,我的应用开始于:

MainPage = new MainPage();

而在 MainPage.xaml 中是:

<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            xmlns:d="http://xamarin.com/schemas/2014/forms/design"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            mc:Ignorable="d"
            xmlns:views="clr-namespace:Test.Views"
            x:Class="Test.Views.MainPage">

    <MasterDetailPage.Master>
        <views:MenuPage />
    </MasterDetailPage.Master>

    <MasterDetailPage.Detail>
        <NavigationPage>
            <NavigationPage.Icon>
                <OnPlatform x:TypeArguments="FileImageSource">
                    <On Platform="iOS" Value="tab_feed.png"/>
                </OnPlatform>
            </NavigationPage.Icon>
            <x:Arguments>
                <views:ItemsPage />
            </x:Arguments>
        </NavigationPage>
    </MasterDetailPage.Detail>
    
</MasterDetailPage>

然后它调用 MenuPage 来加载菜单和内容。

什么是最好的方法,我该怎么做?

Example

【问题讨论】:

  • 你的意思是底部表做菜单页的事情吗?你想做截图之类的事情吗:imgur.com/HeY3j0Y 使用底部工作表作为菜单页?
  • @WendyZang-MSFT 确实如此。但当我打开另一个页面时,在所有页面上也可见。我想让该滑块始终可见,因为它显示了流媒体音乐播放器和曲目信息。所以我认为当显示另一个页面并且用户无法控制它时它会停止播放,例如停止或暂停音乐。谢谢!

标签: android ios xamarin


【解决方案1】:

底部表格可以参考下面的代码。

  <RelativeLayout>

    <StackLayout Padding="10,20,0,0">
        <Label Text="Page7" />
    </StackLayout>
    <Frame
        x:Name="bottomSheet"
        Padding="1,4,1,0"
        BackgroundColor="#faf9f8"
        CornerRadius="8"
        HasShadow="true"
        RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent,
                                                               Property=Height,
                                                               Factor=1,
                                                               Constant=0}"
        RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,
                                                              Property=Width,
                                                              Factor=1,
                                                              Constant=0}"
        RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
                                                          Property=Height,
                                                          Factor=.9,
                                                          Constant=0}">
        <Frame.GestureRecognizers>
            <PanGestureRecognizer PanUpdated="OnPanUpdated" />
        </Frame.GestureRecognizers>
        <StackLayout Spacing="5">
            <BoxView
                BackgroundColor="Gray"
                CornerRadius="2"
                HeightRequest="5"
                HorizontalOptions="Center"
                WidthRequest="50" />
            <SearchBar
                x:Name="SearchBox"
                BackgroundColor="Transparent"
                Focused="SearchBar_Focused"
                Placeholder="Search by Ingredient"
                 />
            <StackLayout x:Name="GridFilter">
                <Button />
            </StackLayout>
        </StackLayout>
    </Frame>
</RelativeLayout>

代码背后:

public Page7()
    {
        InitializeComponent();
    }
    public double getProportionCoordinate(double proportion)
    {
        return proportion * Height;
    }

    private void SearchBar_Focused(object sender, FocusEventArgs e)
    {
        GridFilter.IsVisible = true;
        openBottomSheet();
    }
    void openBottomSheet()
    {
        var finalTranslation = Math.Max(Math.Min(0, -1000), -Math.Abs(getProportionCoordinate(.85)));
        bottomSheet.TranslateTo(bottomSheet.X, finalTranslation, 150, Easing.SpringIn);
    }
    // Important Code Lives Below
    double x, y;
    private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
    {
        // Handle the pan
        switch (e.StatusType)
        {
            case GestureStatus.Running:
                // Translate and ensure we don't y + e.TotalY pan beyond the wrapped user interface element bounds.
                var translateY = Math.Max(Math.Min(0, y + e.TotalY), -Math.Abs((Height * .25) - Height));
                bottomSheet.TranslateTo(bottomSheet.X, translateY, 20);
                break;
            case GestureStatus.Completed:
                // Store the translation applied during the pan
                y = bottomSheet.TranslationY;

                //at the end of the event - snap to the closest location
                var finalTranslation = Math.Max(Math.Min(0, -1000), -Math.Abs(getClosestLockState(e.TotalY + y)));

                //depending on Swipe Up or Down - change the snapping animation
                if (isSwipeUp(e))
                {
                    bottomSheet.TranslateTo(bottomSheet.X, finalTranslation, 250, Easing.SpringIn);
                }
                else
                {
                    bottomSheet.TranslateTo(bottomSheet.X, finalTranslation, 250, Easing.SpringOut);
                }

                //dismiss the keyboard after a transition
                SearchBox.Unfocus();
                y = bottomSheet.TranslationY;

                break;

        }
    }

    public bool isSwipeUp(PanUpdatedEventArgs e)
    {
        if (e.TotalY < 0)
        {
            return true;
        }
        return false;
    }
    //TO-DO: Make this cleaner
    public double getClosestLockState(double TranslationY)
    {
        //Play with these values to adjust the locking motions - this will change depending on the amount of content ona  apge
        var lockStates = new double[] { 0, .5, .85 };

        //get the current proportion of the sheet in relation to the screen
        var distance = Math.Abs(TranslationY);
        var currentProportion = distance / Height;

        //calculate which lockstate it's the closest to
        var smallestDistance = 10000.0;
        var closestIndex = 0;
        for (var i = 0; i < lockStates.Length; i++)
        {
            var state = lockStates[i];
            var absoluteDistance = Math.Abs(state - currentProportion);
            if (absoluteDistance < smallestDistance)
            {
                smallestDistance = absoluteDistance;
                closestIndex = i;
            }
        }

        var selectedLockState = lockStates[closestIndex];
        var TranslateToLockState = getProportionCoordinate(selectedLockState);

        return TranslateToLockState;
    }

截图:

【讨论】:

  • 好的,但是如果我有一个 MasterDetailPage 来显示我的所有页面?效果一样吗?
  • 您可以为详情页添加代码或使用底页创建一个基本页。
  • 我已经使用了这个选项。一切正常,但在 StackLayout(主体内容)中使用 ListView 时,最后两项没有显示
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-10
  • 2020-10-09
  • 1970-01-01
  • 2013-01-01
相关资源
最近更新 更多