Xamarin - замораживание страницы вместо отображения индикатора активности - PullRequest
0 голосов
/ 19 марта 2020

У меня есть страница, построенная следующим образом:

<StackLayout>
    <CollectionView ItemsSource="{Binding Galleries}" x:Name="myCollection" SelectionMode="Single" SelectionChanged="CollectionView_SelectionChanged">
        <CollectionView.ItemsLayout>
            <GridItemsLayout Orientation="Vertical"
                    Span="2" />
        </CollectionView.ItemsLayout>
        <CollectionView.ItemTemplate>
            <DataTemplate>

                <Image Source="{Binding ThumbUrl}"
                   Aspect="AspectFit" />

            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
    <ActivityIndicator BindingContext="{x:Reference myCollection}" IsRunning="{Binding IsLoading}"/>

</StackLayout>

Источник привязки возвращает множество URL-адресов к изображениям, которые затем отображаются в виде галереи. Поскольку загрузка страницы занимает несколько секунд, я хотел бы показать индикатор активности. У меня есть еще одна страница, которая ссылается на различные галереи. Вот как страница загружает страницу галереи:

   private void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e.CurrentSelection.Count > 0)
        { 
            var item = (GalleryListEntry)e.CurrentSelection.FirstOrDefault();
            ((CollectionView)sender).SelectedItem = null;
            Navigation.PushModalAsync(new Gallery(item.PCode, item.GCode));
        }
    }

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

Что я делаю не так?

РЕДАКТИРОВАТЬ: по запросу, код для страницы галереи:

Gallery.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:vm="clr-namespace:GalShare.ViewModel"
         xmlns:d="http://xamarin.com/schemas/2014/forms/design"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         mc:Ignorable="d"
         x:Class="GalShare.Views.Gallery">

<StackLayout>
    <CollectionView ItemsSource="{Binding Galleries}" x:Name="myCollection" SelectionMode="Single" SelectionChanged="CollectionView_SelectionChanged">
        <CollectionView.ItemsLayout>
            <GridItemsLayout Orientation="Vertical"
                    Span="2" />
        </CollectionView.ItemsLayout>
        <CollectionView.ItemTemplate>
            <DataTemplate>

                <Image Source="{Binding ThumbUrl}"
                   Aspect="AspectFit" />

            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
    <ActivityIndicator BindingContext="{x:Reference myCollection}" IsRunning="{Binding IsLoading}"/>

</StackLayout>

gallery.xaml.cs

using GalShare.Model;
using GalShare.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace GalShare.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]

public partial class Gallery : ContentPage
{
    public Gallery(string photographerCode, string galleryCode)
    {
        InitializeComponent();
        BindingContext = new GalleryViewModel(photographerCode, galleryCode);
    }
}

}

GalleryViewModel.cs

using GalShare.Model;
using GalShare.Service;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;

namespace GalShare.ViewModel
{
    class GalleryViewModel
    {
        public string pCode { get; set; }
        public string gCode { get; set; }
        public ObservableCollection<picdata> Galleries { get; set; }          
        public GalleryViewModel(string pCode, string gCode)
        {
            this.pCode = pCode;
            this.gCode = gCode;

            Galleries = new GalleryService().GetImageList(pCode,gCode);

    }
    }
}

GalleryService.cs

using GalShare.Model;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net;
using System.Text;

namespace GalShare.Service
{
public class JsonGalListTxt
{
    public string Galurl { get; set; }
}

public class JsonTxt
{
    public Settings Settings { get; set; }
    public IList<File> Files { get; set; }
}

public class Settings
{
    public string Path { get; set; }
}

public class File
{
    public string file { get; set; }
}

public class galURL
{
    public string galurl { get; set; }
}

class GalleryService
 {

  //  public string pCode { get; set; }
  //  public string gCode { get; set; }

    public ObservableCollection<picdata> Images { get; set; }
    public ObservableCollection<picdata> GetImageList(string pCode, string gCode)
    {

        WebClient client = new WebClient();
        string GalUrl = client.DownloadString("https://www.mypage.it/getUrl.php?pid=" + pCode + "&galid=" + gCode);
        var deserializedUrl = JsonConvert.DeserializeObject<galURL>(GalUrl);

        Images = new ObservableCollection<picdata>();

            string downloadString = client.DownloadString(deserializedUrl.galurl);
            var deserialized = JsonConvert.DeserializeObject<JsonTxt>(downloadString);


            foreach (File img in deserialized.Files)
            {

               Images.Add(new picdata()
               {
                    ImageName = img.file,
                    BaseUrl = deserialized.Settings.Path.ToString(),
                    ThumbUrl = deserialized.Settings.Path.ToString() + "/thumbs" + img.file
               });
            }

        return Images;



    }
}
}

1 Ответ

0 голосов
/ 19 марта 2020

когда вы создаете виртуальную машину из конструктора, она загружает ВСЕ образы в основном потоке, блокируя фактическое появление страницы до тех пор, пока она не завершит

public Gallery(string photographerCode, string galleryCode)
{
    InitializeComponent();
    BindingContext = new GalleryViewModel(photographerCode, galleryCode);
}

как минимум, я бы переместил это на OnAppearing, чтобы сначала отображалась страница, а затем загружались изображения.

Вы также можете переместить запросы на изображения в другой поток, чтобы он не блокировал пользовательский интерфейс. Вы также можете использовать библиотеку типа FFImageLoading , которая поможет вам справиться с этим

...