0

我正在制作一个必须能够在两种视图模式之间切换的应用程序:

  • 全屏:视图应该显示在整个屏幕上,没有标题栏/导航栏/操作栏。
  • 半全屏:视图仍应填满整个屏幕,但标题/导航/操作栏现在应出现在视图前面,根本无需调整视图大小。

为了测试在这两种模式之间切换的行为,我创建了一个简单的测试项目,每两秒在这两种模式之间切换一次。

全屏模式按预期工作,但半全屏模式存在两个问题,如下图所示:

  1. 视图内容(带有五行文本的标签)被下推。我希望它保持在屏幕顶部,部分隐藏在系统栏后面。
  2. 操作栏显示在状态栏的后面。我希望它显示在状态栏下方。

为了获得我想要的行为,我需要改变什么?(我假设必须在 Page1.xaml.cs 或 MainActivity.cs 的 ToggleFullscreen 函数中进行更改)

在此处输入图像描述

我的代码如下所示:

应用程序.xaml.cs

using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace ActionBarTest
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();

            var np = new NavigationPage(new Page1());
            np.Title = "ActionBarTest";
            MainPage = np;
        }
    }
}

Page1.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage 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"
             x:Class="ActionBarTest.Page1">
    <ContentPage.Content>
        <StackLayout>
            <Label Text="Welcome to Xamarin.Forms!"
                   VerticalOptions="Start" 
                   HorizontalOptions="CenterAndExpand" />
            <Label Text="Line one"
                   VerticalOptions="Start" 
                   HorizontalOptions="CenterAndExpand" />
            <Label Text="Line two"
                   VerticalOptions="Start" 
                   HorizontalOptions="CenterAndExpand" />
            <Label Text="Line three"
                   VerticalOptions="Start" 
                   HorizontalOptions="CenterAndExpand" />
            <Label Text="Line four"
                   VerticalOptions="Start" 
                   HorizontalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Page1.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace ActionBarTest
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class Page1 : ContentPage
    {
        public Page1()
        {
            InitializeComponent();

            Task.Factory.StartNew(() => {
                while (true)
                {
                    Thread.Sleep(2000);
                    ToggleFullscreen(true);
                    Thread.Sleep(2000);
                    ToggleFullscreen(false);
                }
            });
        }
    }

    private void ToggleFullscreen(bool isFullscreen){
        Xamarin.Forms.Device.BeginInvokeOnMainThread(() => { NavigationPage.SetHasNavigationBar(this, !isFullscreen); });
    }
}

MainActivity.cs

using System;
using System.Threading;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace ActionBarTest.Droid
{
    [Activity(Label = "ActionBarTest", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(savedInstanceState);

            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            LoadApplication(new App());

            System.Threading.Tasks.Task.Factory.StartNew(() => {
                while (true)
                {
                    Thread.Sleep(2000);
                    ToggleFullscreen(true);
                    Thread.Sleep(2000);
                    ToggleFullscreen(false);
                }
            });
        }

        private void ToggleFullscreen(bool isFullscreen)
        {
            RunOnUiThread(() =>
            {
                if (isFullscreen)
                {
                    Window.DecorView.SystemUiVisibility = (StatusBarVisibility)(
                        SystemUiFlags.Fullscreen
                        | SystemUiFlags.HideNavigation
                        | SystemUiFlags.Immersive
                        | SystemUiFlags.ImmersiveSticky
                        | SystemUiFlags.LowProfile
                        | SystemUiFlags.LayoutStable
                        | SystemUiFlags.LayoutHideNavigation
                        | SystemUiFlags.LayoutFullscreen
                    );
                }
                else
                {
                    Window.DecorView.SystemUiVisibility = (StatusBarVisibility)(
                        SystemUiFlags.LayoutStable
                        | SystemUiFlags.LayoutHideNavigation
                        | SystemUiFlags.LayoutFullscreen
                    );
                }
            });
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
}
4

1 回答 1

0

您可以添加Y offsetof stackLayoutwhen isFullScreen = false。例如,给stackLayoutinXaml和 in 代码隐藏的名称:

private void ToggleFullscreen(bool isFullscreen)
{
    Xamarin.Forms.Device.BeginInvokeOnMainThread(() => {

        if (isFullscreen)
        {
            myStackLayout.TranslationY = 0;
        }
        else
        {
            myStackLayout.TranslationY = -64;
        }

        NavigationPage.SetHasNavigationBar(this, !isFullscreen);

    });
}

在您的 MainActivity 中,删除 SystemUiFlags.LayoutHideNavigation ,SystemUiFlags.LayoutFullscreenwhen isFullScreen = false

private void ToggleFullscreen(bool isFullscreen)
{
    RunOnUiThread(() =>
    {
        if (isFullscreen)
        {
            Window.DecorView.SystemUiVisibility = (StatusBarVisibility)(
                SystemUiFlags.Fullscreen
                | SystemUiFlags.HideNavigation
                | SystemUiFlags.Immersive
                | SystemUiFlags.ImmersiveSticky
                | SystemUiFlags.LowProfile
                | SystemUiFlags.LayoutStable
                | SystemUiFlags.LayoutHideNavigation
                | SystemUiFlags.LayoutFullscreen
            );
        }
        else
        {
            Window.DecorView.SystemUiVisibility = (StatusBarVisibility)(
                SystemUiFlags.LayoutStable
            );
        }
    });
}

我已经上传了一个示例,您可以查看:toggle-model-xamarin.forms

在我的手机上,偏移量必须是 -74 - 有没有办法可靠地确定手机之间的偏移量?

您可以通过获取status barand的高度来获取偏移量action bar:使用依赖服务首先获取高度然后设置偏移量,您可以查看有关android-status-bar-height-in-xamarin-android 的线程

设计在重新定位时仍然闪烁 - 根本没有办法避免重新定位吗?

不知道闪光灯,它似乎在一张一张地显示视图。

我没有提到视图的元素应该留在屏幕的底部边缘,并且在使用 TranslateY 时,这些元素也会向上移动

在这种情况下,您只能将偏移量设置为要更改的视图,而不是整个视图。

于 2019-06-14T02:30:55.530 回答