Как обновить прогрессбар из customwebview рендерера в формах xamarin для Android? - PullRequest
0 голосов
/ 31 августа 2018

В настоящее время я разрабатываю приложение в Xamarin Forms с фоном Android, поэтому сначала мне нужно было создать приложение для Android, а затем приложение для iOS.

Я новичок в Xamarin Forms, и я борюсь за то, как обновить ProgressBar из WebView, используя специальный рендерер для WebView.

В Android вы можете сделать что-то подобное с ProgressBar и WebView, которые находятся в main_layout.xml

public class MainActivity extends Activity {

    private ProgressBar progressBar;
    private WebView webView;    

    @Override
    protected void onCreate(Bundle savedInstanceState) {     
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);

        progressBar = (ProgressBar) findViewById(R.id.progress);
        webView = (AdvancedWebView) findViewById(R.id.webView);
        // webview initialisation
        webView.setWebChromeClient(new WebChromeClient(){
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                // update progressbar progress
                progressBar.setProgress(newProgress);
           }
       });
        webView.setWebViewClient(new WebViewClient(this) {
            @Override
            public void onPageFinished(WebView view, String url) {
                // hide progressbar when it's done
                progressBar.setVisibility(View.GONE);
            }
        });
    }
}

В формах Xamarin у меня есть этот макет в MainPage.xaml в общем проекте

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
NavigationPage.HasNavigationBar="False">

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <ProgressBar
        x:Name="progress"
        Grid.Row="3"
        HorizontalOptions="FillAndExpand"
        Progress="0"
        VerticalOptions="Center" />

    <WebView
        x:Name="webview"
        Grid.Row="0"
        Grid.RowSpan="4"
        Grid.Column="0"
        HorizontalOptions="FillAndExpand"
        IsVisible="False"
        Source="https://google.com"
        VerticalOptions="FillAndExpand" />

</Grid>

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

        MainPage = new MainPage(); 
    }
}

И этот пользовательский рендер WebView для Android в проекте Android

[assembly: ExportRenderer(typeof(WebView), typeof(CustomWebviewRenderer))]
namespace MyApp.Droid
{
    public class CustomWebviewRenderer: WebViewRenderer
    {
        private readonly Context context;

        public CustomWebviewRenderer(Context context) : base(context)
        {
            this.context = context;
        }

        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);
            var formsWebView = e.NewElement as Xamarin.Forms.WebView;

            if (formsWebView != null)
            {
                var webView = Control as Android.Webkit.WebView;
                webView.SetWebViewClient(new CustomWebViewClient()); 
                webView.SetWebChromeClient(new CustomWebChromeClient());     
                webView.Settings.LoadWithOverviewMode = true;
                webView.Settings.UseWideViewPort = true;
                SetNativeControl(webView);
            }
        }

        private class ScoritoWebChromeClient : WebChromeClient
        {
            public override void OnProgressChanged(Android.Webkit.WebView view, int newProgress)
            {
                // how to update progressbar progress?
                base.OnProgressChanged(view, newProgress);               
            }
        }

        private class CustomWebViewClient : WebViewClient
        {
            public override void OnPageFinished(Android.Webkit.WebView view, string url)
            {
                // how to hide progressbar?
                base.OnPageFinished(view, url);
            }

            public override void OnPageStarted(Android.Webkit.WebView view, string url, Bitmap favicon)
            {
                base.OnPageStarted(view, url, favicon);
            }

            public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request)
            {
                return base.ShouldOverrideUrlLoading(view, request);
            }
        }
    }
}

Как я могу обновить ProgressBar, который есть в моем MainPage.xaml, с OnPageFinished в CustomWebviewRenderer классе, чтобы показать, что веб-страница закончила загрузку? Должен ли я использовать MainActivity.cs в проекте Android?

Может кто-нибудь указать мне правильное направление, как решить эту проблему?

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Итак, через 10 дней Я наконец нашел решение этой проблемы с помощью bindableproperties ...

Итак, я добавил CustomWebView в PCL

public class CustomWebView : WebView
{
    public static readonly BindableProperty PageProgressProperty = BindableProperty.Create(
        nameof(PageProgress),
        typeof(int),
        typeof(CustomWebView),
        default(int));

    public int PageProgress
    {
        get => (int)GetValue(PageProgressProperty);
        set => SetValue(PageProgressProperty, value);
    }      
}

Также CustomProgressBar в PCL

public class CustomProgressBar : ProgressBar
{
    public CustomProgressBar()
    {
    }

    public static readonly BindableProperty CurrentProgressProperty =
    BindableProperty.Create(
        nameof(CurrentProgress),
        typeof(int),
        typeof(CustomProgressBar),
        default(int),
        propertyChanged: CustomProgressPropertyChanged);

    private static void CustomProgressPropertyChanged(BindableObject sender, object oldValue, object newValue)
    {
        CustomProgressBar thisProgressBar = (CustomProgressBar)sender;
        double percent = Convert.ToDouble(newValue) / 100;
        thisProgressBar.ProgressTo(percent, 100, Easing.Linear);
    }

    public int CurrentProgress
    {
        get => (int)GetValue(CurrentProgressProperty);
        set => SetValue(CurrentProgressProperty, value);
    }
}

А теперь я могу обновить прогресс из моего CustomWebviewRenderer следующим образом

public class CustomWebviewRenderer : WebViewRenderer
{
    private readonly Context context;

    public CustomWebviewRenderer(Context context) : base(context)
    {
        this.context = context;
    }

    protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
    {
        base.OnElementChanged(e);
        var formsWebView = e.NewElement as WebView;

        if (e.OldElement == null)
        {
            var x = Control;
            var webView = Control as Android.Webkit.WebView;
            webView.SetWebViewClient(new CustomWebViewClient(Element));
            webView.SetWebChromeClient(new CustomWebChromeClient(Element));
            webView.Settings.LoadWithOverviewMode = true;
            SetNativeControl(webView);
        }
    }

    private class CustomWebViewClient : WebViewClient
    {
        private readonly WebView formsWebView;

        public CustomWebViewClient(WebView webView)
        {
            formsWebView = webView;
        }

        public override void OnReceivedError(Android.Webkit.WebView view, IWebResourceRequest request, WebResourceError error)
        {
            base.OnReceivedError(view, request, error);
        }

        public override void OnPageFinished(Android.Webkit.WebView view, string url)
        {
            base.OnPageFinished(view, url);
        }

        public override void OnPageStarted(Android.Webkit.WebView view, string url, Bitmap favicon)
        {
            base.OnPageStarted(view, url, favicon);
        }

        public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request)
        {
            return base.ShouldOverrideUrlLoading(view, request);
        }
    }

    private class CustomWebChromeClient : WebChromeClient
    {
        private WebView element;

        public CustomWebChromeClient(WebView element)
        {
            this.element = element;
        }

        public override void OnProgressChanged(Android.Webkit.WebView view, int newProgress)
        {
            base.OnProgressChanged(view, newProgress);
            element.SetValueFromRenderer(CustomWebView.PageProgressProperty, newProgress);
        }          
    }
}

И, наконец, в .xaml просматриваются следующие свойства: BindingContext и CurrentProgress. BindingContext установлен на веб-просмотр, а CurrentProgress - это пользовательское свойство, связанное с PageProgress, которое находится в CustomWebView

    <local:CustomProgressBar
        x:Name="progress"
        Grid.Row="3"
        BindingContext="{x:Reference webview}"
        CurrentProgress="{Binding Path=PageProgress}"
        HorizontalOptions="FillAndExpand"
        ProgressColor="#FFB800"
        VerticalOptions="Center" />

    <local:CustomWebView
        x:Name="webview"
        Grid.Row="0"
        Grid.RowSpan="4"
        Grid.Column="0"
        HorizontalOptions="FillAndExpand"
        IsVisible="False"
        VerticalOptions="FillAndExpand" />

Так что да, потребовалось время, чтобы понять это ...

0 голосов
/ 06 сентября 2018

Обновление:

Создайте собственный класс WebView на вашем PCL:

 public class CustomWebView: WebView
 {   
    public static readonly BindableProperty ActionProperty = BindableProperty.Create(propertyName: nameof(Action), returnType: typeof(Action),
        declaringType: typeof(CustomWebView),
        defaultValue: null,
        defaultBindingMode: BindingMode.OneWay);

    public void InvokeAction()
    {
        if (Action == null || data == null)
        {
            return;
        }
        Action.Invoke();
    }

    public Action Action
    {
        get { return (Action)GetValue(ActionProperty); }
        set { SetValue(ActionProperty, value); }
    }

 }

Используйте этот CustomWebView с его пространством имен следующим образом:

<namespace:CustomWebView  x:Name="webview"
    Grid.Row="0"
    Grid.RowSpan="4"
    Grid.Column="0"
    HorizontalOptions="FillAndExpand"
    IsVisible="False"
    Source="https://google.com"
    VerticalOptions="FillAndExpand"/>  

Но если вы все еще настаиваете на использовании средства визуализации, вы можете обновить индикатор выполнения с помощью свойства элемента и получить обратный вызов или изменить свойство, как показано ниже:

[assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebviewRenderer))]
 namespace MyApp.Droid
{
public class CustomWebviewRenderer: WebViewRenderer
{
    private readonly Context context;  

    public CustomWebviewRenderer(Context context) : base(context)
    {
        this.context = context;
    }

    protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
    {
        base.OnElementChanged(e);
        var formsWebView = e.NewElement as Xamarin.Forms.WebView;

        if (formsWebView != null)
        {
            var webView = Control as Android.Webkit.WebView;
            webView.SetWebViewClient(new CustomWebViewClient()); 
            webView.SetWebChromeClient(new CustomWebChromeClient());     
            webView.Settings.LoadWithOverviewMode = true;
            webView.Settings.UseWideViewPort = true;
            SetNativeControl(webView);
        }
    }

    private class ScoritoWebChromeClient : WebChromeClient
    {
        public override void OnProgressChanged(Android.Webkit.WebView view, int newProgress)
        {
            // how to update progressbar progress?
            base.OnProgressChanged(view, newProgress);               
        }
    }

    private class CustomWebViewClient : WebViewClient
    {
        private _webView;
        public CustomWebViewClient (Xamarin.Forms.WebView webView) 
        {
          _webView=webView;
        }
        public override void OnPageFinished(Android.Webkit.WebView view, string url)
        {
            // how to hide progressbar?
            _webView.InvokeAction();
            base.OnPageFinished(view, url);
        }

        public override void OnPageStarted(Android.Webkit.WebView view, string url, Bitmap favicon)
        {
            base.OnPageStarted(view, url, favicon);
        }

        public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request)
        {
            return base.ShouldOverrideUrlLoading(view, request);
        }
    }
  }
}   

Обратите внимание, что это всего лишь пример, и его можно изменить в соответствии с вашими требованиями.

Если это не сработает или у вас возникнут запросы, вернитесь!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...