为啥滚动这个 xamarin 页面这么慢?

Posted

技术标签:

【中文标题】为啥滚动这个 xamarin 页面这么慢?【英文标题】:Why is scrolling this xamarin page so slow?为什么滚动这个 xamarin 页面这么慢? 【发布时间】:2020-09-09 13:05:56 【问题描述】:

我正在开发一个 xamarin 项目(android,尚未在 ios 中测试),并注意到我的 UI 在滚动时很慢(scrollview / observablecollection)。我在Xamarin official page 阅读了一些关于性能的建议,并尝试过,还进行了其他测试,但没有任何收获。

当用户尝试滚动某些东西时,感觉好像它正在反复快速冻结/释放用户界面。

这是我为测试目的而尝试的,但没有成功:

移除地图 将图像更改为 ffimageloading 缓存图像 移除标签 删除了不必要的 StackLayouts 从滚动视图标签中删除了 InputTransparent="True"

我的 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:ContentView="clr-namespace:MasterDetailPageNavigation.XAML"
             x:Class="MasterDetailPageNavigation.VisualizarProfissional"
             xmlns:views="clr-namespace:MasterDetailPageNavigation.XAML"
             xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
             xmlns:controls="clr-namespace:CustomControls.Controls"
             Title="My app" BackgroundColor="#58C8A2">
  <ContentPage.Resources>
    <Style x:Key="Especs" TargetType="Label">
        <Setter Property="Margin" Value="0" />
        <Setter Property="FontSize" Value="12" />
        <Setter Property="BackgroundColor" Value="#f0f0f0" />
        <Setter Property="Padding" Value="2" />
    </Style>
    <StyleSheet Source="VisualizarProfissional.css" />
  </ContentPage.Resources>
  <ContentPage.Content>
      <Grid>
          <Grid.RowDefinitions>
              <RowDefinition Height="50" />
              <RowDefinition Height="*" />
          </Grid.RowDefinitions>

          <ContentView:TopBarBack Grid.Row="0" Grid.Column="0" Margin="0">
            <x:Arguments>
                <x:String>Voltar para a lista</x:String>
            </x:Arguments>
         </ContentView:TopBarBack>

         <ScrollView InputTransparent="True" x:Name="ScrollProfissional" Grid.Row="1" Grid.Column="0" HorizontalOptions="FillAndExpand" VerticalScrollBarVisibility="Always" BackgroundColor="White">

             <Grid VerticalOptions="StartAndExpand" HorizontalOptions="Fill">

                 <Grid.ColumnDefinitions>
                     <ColumnDefinition Width="*"></ColumnDefinition>
                 </Grid.ColumnDefinitions>
                 <Grid.RowDefinitions>
                     <RowDefinition Height="40"></RowDefinition>
                     <RowDefinition Height="auto"></RowDefinition>
                     <RowDefinition Height="auto"></RowDefinition>
                     <RowDefinition Height="150"></RowDefinition>
                     <RowDefinition Height="40"></RowDefinition>
                     <RowDefinition Height="auto"></RowDefinition>
                     <RowDefinition Height="50"></RowDefinition>
                     <RowDefinition Height="220" x:Name="RowMap"></RowDefinition>
                     <RowDefinition Height="auto"></RowDefinition>
                     <RowDefinition Height="auto"></RowDefinition>
                     <RowDefinition Height="auto"></RowDefinition>
                     <RowDefinition Height="auto"></RowDefinition>
                 </Grid.RowDefinitions>


                 <Label x:Name="xCategoria" TextColor="#8e8e8e" FontSize="14" Grid.Column="0" Grid.Row="0" VerticalOptions="End" HorizontalOptions="StartAndExpand" Margin="20,0,0,0" />
                 <Label Text="&#xf005;&#xf005;&#xf005;&#xf5c0;&lt;span style=&quot;color:#e2e2e2&quot;&gt;&#xf005;&lt;span&gt;" TextType="html" TextColor="#ffad00" FontSize="14" Grid.Column="0" Grid.Row="0" VerticalOptions="End" HorizontalOptions="EndAndExpand" Margin="0,0,20,0">
                    <Label.FontFamily>
                        <OnPlatform x:TypeArguments="x:String" Android="Font-Awesome-Free-Solid.otf#FontAwesome5Free-Solid" iOS="FontAwesome5Free-Solid" />
                    </Label.FontFamily>
                 </Label>
                 <Label x:Name="xTitulo" FontAttributes="Bold" TextColor="#337760" FontSize="20" Grid.Column="0" Grid.Row="1" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" Margin="20,0,0,0"></Label>
                 <Label x:Name="xEndereco" TextColor="#8e8e8e" FontSize="12" Grid.Column="0" Grid.Row="2" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" Margin="20,0,0,0"></Label>

                 <Frame VerticalOptions="Fill" Grid.Column="0" Grid.Row="3" CornerRadius="4" Padding="0" Margin="10,5,10,5">
                    <Image x:Name="ImagemCapa" HorizontalOptions="FillAndExpand" Aspect="AspectFill" VerticalOptions="FillAndExpand" />
                 </Frame>

                 <controls:BotaoFrame Grid.Column="0" Grid.Row="4" BackgroundColor="#198B61" Margin="10,0,10,0" Padding="0" CornerRadius="4">
                     <controls:BotaoFrame.GestureRecognizers>
                         <TapGestureRecognizer Tapped="Button_Clicked" />
                     </controls:BotaoFrame.GestureRecognizers>
                     <Grid HorizontalOptions="CenterAndExpand">
                         <Grid.ColumnDefinitions>
                             <ColumnDefinition Width="auto"></ColumnDefinition>
                             <ColumnDefinition Width="*"></ColumnDefinition>
                         </Grid.ColumnDefinitions>
                         <Grid.RowDefinitions>
                             <RowDefinition Height="*"></RowDefinition>
                         </Grid.RowDefinitions>
                         <Label Grid.Column="0" Grid.Row="0" Text="&#xf086;" TextColor="White" FontSize="22" VerticalOptions="CenterAndExpand">
                         <Label.FontFamily>
                            <OnPlatform x:TypeArguments="x:String" Android="Font-Awesome-Free-Solid.otf#FontAwesome5Free-Solid" iOS="FontAwesome5Free-Solid" />
                        </Label.FontFamily>
                         </Label>
                         <Label Grid.Column="1" Grid.Row="0" Text="tire dúvidas e agende um atendimento" TextColor="White" FontSize="14" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" />                         
                     </Grid>
                 </controls:BotaoFrame>

                 <!-- ESPECIALIDADES -->
                <Grid Grid.Row="5" Grid.Column="0" VerticalOptions="StartAndExpand">
                 <FlexLayout x:Name="xEspecialidades" BindableLayout.ItemsSource="Binding especialidades" VerticalOptions="Fill" Margin="10,15,10,5" JustifyContent="Start" AlignContent="Start" AlignItems="Stretch" AlignSelf="Center" Wrap="Wrap" HorizontalOptions="FillAndExpand">
                    <BindableLayout.ItemTemplate>
                        <DataTemplate>
                            <Grid HeightRequest="20" Margin="0,0,4,6" HorizontalOptions="StartAndExpand">
                                <Frame BackgroundColor="#f1f1f1" CornerRadius="5" Padding="2" HorizontalOptions="StartAndExpand">
                                   <Label Text="Binding ." Grid.Column="1" Grid.Row="0" TextColor="DarkGray" FontSize="11" HorizontalOptions="Fill" />
                                </Frame>
                            </Grid>
                          </DataTemplate>
                    </BindableLayout.ItemTemplate>
                  </FlexLayout>
                </Grid>

                 <!-- DISTANCIA -->
                 <Grid x:Name="xGridDistancia" Grid.Column="0" Grid.Row="6" VerticalOptions="StartAndExpand" HorizontalOptions="CenterAndExpand">
                         <Grid.ColumnDefinitions>
                             <ColumnDefinition Width="auto"></ColumnDefinition>
                             <ColumnDefinition Width="auto"></ColumnDefinition>
                         </Grid.ColumnDefinitions>
                         <Grid.RowDefinitions>
                             <RowDefinition Height="40"></RowDefinition>
                         </Grid.RowDefinitions>

                         <Label Grid.Column="0" Grid.Row="0" Text="&#xf3c5;" TextColor="#ff4800" FontSize="22" VerticalOptions="CenterAndExpand">
                         <Label.FontFamily>
                            <OnPlatform x:TypeArguments="x:String" Android="Font-Awesome-Free-Solid.otf#FontAwesome5Free-Solid" iOS="FontAwesome5Free-Solid" />
                        </Label.FontFamily>
                     </Label>
                     <Label x:Name="xDistancia" Grid.Column="1" Grid.Row="0" TextType="Html" TextColor="#505050" FontSize="14" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" />
                 </Grid>

                 <!-- MAPA -->
                 <Frame x:Name="MapaFrame" Grid.Column="0" Grid.Row="7" Padding="0" Margin="0" HasShadow="False" HorizontalOptions="Fill" VerticalOptions="Fill">
                     <maps:Map x:Name="Mapa"
                               MapType="Street"
                               VerticalOptions="FillAndExpand"
                               HorizontalOptions="FillAndExpand" 
                               IsShowingUser="true">
                     </maps:Map>
                 </Frame>

                 <Label x:Name="xSobreTitulo" Grid.Row="8" Grid.Column="0" TextColor="#58C8A2" FontSize="Title" Margin="10,10,10,10" />
                 <Label x:Name="xSobreTexto" LineBreakMode="WordWrap" TextType="Html" Grid.Row="9" Grid.Column="0" TextColor="Black" Margin="10,10,10,10" />

                 <!-- SLIDE IMAGENS -->
                 <CollectionView HeightRequest="110" Grid.Row="10" Grid.Column="0" x:Name="ImagensCollection" x:FieldModifier="public static" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" VerticalScrollBarVisibility="Never" HorizontalScrollBarVisibility="Never">
                     <CollectionView.ItemsLayout>
                        <LinearItemsLayout Orientation="Horizontal" SnapPointsType="Mandatory" SnapPointsAlignment="Start" />
                     </CollectionView.ItemsLayout>

                     <CollectionView.ItemTemplate>
                        <DataTemplate>
                            <Frame Padding="5">
                                <Frame.GestureRecognizers>
                                    <TapGestureRecognizer Command="Binding ImageZoom" CommandParameter="Binding keyname" />
                                </Frame.GestureRecognizers>
                                <Frame HeightRequest="100" WidthRequest="100" BackgroundColor="Transparent" CornerRadius="4" Padding="0" Margin="0">
                                    <Image Source="Binding keyname, StringFormat='www.myapp/assets/libs/thumb.php?w=300&#x26;h=300&#x26;img=0'"  HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Aspect="AspectFill" />
                                </Frame>
                            </Frame>
                        </DataTemplate>
                    </CollectionView.ItemTemplate>
                </CollectionView>

                 <!-- CURRICULUM E PAGAMENTOS -->
                 <Grid Grid.Row="11" Grid.Column="0" VerticalOptions="StartAndExpand">
                 <FlexLayout x:Name="xCurriculum" BindableLayout.ItemsSource="Binding curriculum" VerticalOptions="Fill" Margin="10,15,10,5" JustifyContent="Start" Wrap="Wrap" HorizontalOptions="FillAndExpand">
                    <BindableLayout.ItemTemplate>
                        <DataTemplate>
                            <Grid HeightRequest="20" Margin="0,0,4,6" HorizontalOptions="StartAndExpand">
                                <Frame BackgroundColor="#f1f1f1" CornerRadius="5" Padding="2" HorizontalOptions="StartAndExpand">
                                    <Grid HeightRequest="20" Margin="0" Padding="0">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="auto" />
                                            <ColumnDefinition Width="auto" />
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions><RowDefinition Height="20" /></Grid.RowDefinitions>

                                        <Label VerticalOptions="CenterAndExpand" Grid.Column="0" Grid.Row="0" Text="&#xf559;" TextColor="DarkGray" FontSize="12">
                                             <Label.FontFamily>
                                                <OnPlatform x:TypeArguments="x:String" Android="Font-Awesome-Free-Solid.otf#FontAwesome5Free-Solid" iOS="FontAwesome5Free-Solid" />
                                            </Label.FontFamily>
                                         </Label>
                                        <Label VerticalOptions="CenterAndExpand" Text="Binding ." Grid.Column="1" Grid.Row="0" TextColor="DarkGray" FontSize="11" HorizontalOptions="Fill" />

                                    </Grid>
                                </Frame>
                            </Grid>
                          </DataTemplate>
                    </BindableLayout.ItemTemplate>
                  </FlexLayout>
                </Grid>

             </Grid>
         </ScrollView>
     </Grid>
  </ContentPage.Content>
</ContentPage>

controls:BotaoFrame 是一个简单的类,它实现了 Frame 但带有图案的视觉效果,我确信它没有什么问题

背后的代码:

using Xamarin.Forms;
using Xamarin.Forms.Maps;
using System.Collections.ObjectModel;
using System;
using MasterDetailPageNavigation.XAML;
using System.Threading.Tasks;

namespace MasterDetailPageNavigation

    public partial class VisualizarProfissional : ContentPage
    
        public static ProfissionalVer dados = null;
        public static ObservableCollection<string> EspecialidadesLista;
        public string IdProfGlobal;
        public VisualizarProfissional(string IdProf)
        
            InitializeComponent();
            NavigationPage.SetHasNavigationBar(this, false);
            NavigationPage.SetHasBackButton(this, false);
            IdProfGlobal = IdProf;
            Task.Run(()=>GetProfissionalData(IdProf));
        

        public async Task GetProfissionalData(string id)
        
            WebService client = new WebService();
            dados = await Task.Run(()=> client.GetJsonUnique<ProfissionalVer>("wwwmyapp.com/assets/libs/app/VisualizarProfissional.php?id=" + id));

            if (dados != null)
            
                xCategoria.Text = dados.contaTipo == 3 ? dados.estabelecimento : dados.profissao;
                xTitulo.Text = dados.titulo;
                xEspecialidades.BindingContext = dados;
                xCurriculum.BindingContext = dados;

                xEndereco.Text = dados.privLocal == 0 ? (
                    (dados.logradouro != null ? dados.logradouro : "") +
                    (dados.imovelN != null ? ", " + dados.imovelN : "") +
                    (dados.complemento != null ? " - " + dados.complemento : "") +
                    (dados.bairro != null ? ", " + dados.bairro : "") +
                    (dados.cidade != null ? ", " + dados.cidade : "") +
                    (dados.uf != null ? " " + dados.uf : "")
                    ) : dados.bairro + " - " + dados.cidade + " " + dados.uf;

                // Imagens
                if (dados.imagens.Count > 0)
                
                    ImagemCapa.Source = "wwwmyapp.com/assets/libs/thumb.php?w=300&h=300&img=" + dados.imagens[0].keyname;
                    if (dados.imagens.Count > 1)
                    
                        ImagensCollection.ItemsSource = dados.imagens;
                        ImagensCollection.IsVisible = true;
                    
                
                else
                
                    ImagemCapa.Source = "semimage.jpg";
                    ImagensCollection.IsVisible = false;
                

                //Mapa e distancia
                if (ContactsPage.PubCoords.Latitude != null && ContactsPage.PubCoords.Longitude != null
                    && dados.lat != null && dados.lng != null)
                
                    double lat1 = ContactsPage.PubCoords.Latitude;
                    double lon1 = ContactsPage.PubCoords.Longitude;
                    double lat2 = dados.lat;
                    double lon2 = dados.lng;

                    double rlat1 = Math.PI * lat1 / 180;
                    double rlat2 = Math.PI * lat2 / 180;
                    double theta = lon1 - lon2;
                    double rtheta = Math.PI * theta / 180;
                    double dist =
                        Math.Sin(rlat1) * Math.Sin(rlat2) + Math.Cos(rlat1) *
                        Math.Cos(rlat2) * Math.Cos(rtheta);
                    dist = Math.Acos(dist);
                    dist = dist * 180 / Math.PI;
                    dist = dist * 60 * 1.1515 * 1.609344;

                    string distShow;
                    if (dist < 1)
                    
                        dist = dist * 1000;
                        distShow = string.Format("0:0.0", dist);
                        if (distShow == "0.0")
                            distShow = "Parece que você chegou ao endereço!";
                        else
                            distShow = "Aproximadamente <strong>" + distShow + " metros</strong> de você";
                    
                    else
                    
                        distShow = "Aproximadamente <strong>" + string.Format("0:0.0", dist) + " km</strong> de você";
                    

                    xDistancia.Text = distShow;

                    if (dados.privLocal == 1)
                    
                        RowMap.Height = 0;
                        MapaFrame.IsVisible = false;
                    
                
                else
                
                    xGridDistancia.IsVisible = false;
                

                if (dados.lat != null && dados.lng != null && dados.privLocal == 0)
                
                    Mapa.MoveToRegion(MapSpan.FromCenterAndRadius(
                        new Position(dados.lat, dados.lng),
                        Distance.FromMiles(0.5)));

                    var pin = new Pin
                    
                        Type = PinType.Place,
                        Position = new Position(dados.lat, dados.lng),
                        Label = dados.titulo,
                        Address = dados.logradouro,
                    ;

                    Mapa.Pins.Add(pin);
                
                else if (dados.privLocal == 1)
                
                    MapaFrame.IsVisible = false;
                    Mapa.IsEnabled = false;
                    RowMap.Height = 0;
                

                // Sobre
                if (dados.sobre != null)
                
                    xSobreTitulo.Text = "Sobre - " + dados.titulo;
                    xSobreTexto.Text = "<p style ='text-align:justify;'>" + dados.sobre + "</p>";
                
                else
                
                    xSobreTitulo.IsVisible = false;
                    xSobreTexto.IsVisible = false;
                

            
            else
                GetProfissionalData(id);

        

        async void Button_Clicked(System.Object sender, System.EventArgs e)
        
            if (App.Current.MainPage is MasterDetailPage mdp)
            
                await mdp.Detail.Navigation.PushAsync(new SecondPage(IdProfGlobal));
                mdp.IsPresented = false;
            
        
    

所有页面似乎都有这个问题,这只是我想公开的一个示例页面,看看我是否做错了一切(笑)。 有人知道导致此问题的原因是什么吗?

【问题讨论】:

您是实际将其加载到手机上还是在 PC 上使用模拟器? 我正在我的设备上进行测试:galaxy s6 和 s9。尝试调试和发布版本。 注释掉页面的某些部分并搜索 xaml 块是罪魁祸首 @Mouse 我做到了。我在问题中提到了它。 【参考方案1】:

虽然它有所帮助,但主要问题不在于这个特定页面。主页是问题,它有

<StackLayout><ScrollView></ScrollView></StackLayout>

我只需要删除&lt;StackLayout&gt;&lt;/StackLayout&gt;,整个应用程序中的所有内容现在都运行顺利。这证明了构建干净的布局是多么重要。

【讨论】:

除此之外,看看 UI 代码,它仍然很复杂,并且包含太多不必要的布局。 感谢您的分享,请采纳您的回答,对有类似问题的其他人有帮助。 不幸的是,这对我们来说不是一个选项,因为 StackLayout 是必需的 - 布局已经很干净了!

以上是关于为啥滚动这个 xamarin 页面这么慢?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 jQuery 选择器这么慢?

为啥videoview这么慢?

升级到 Visual Studio 16.11.1 后,Xamarin Forms 破坏了 XANS 7028:System.IO.FileNotFoundException:无法加载程序集“Xama

为啥这个查询运行这么慢?

为啥这个 select 语句这么慢?

为啥这个计数查询这么慢?