2

I am trying to implement 2 way databinding for WebView and Progressbar.

Initially ProgressBar will continue to appear and as soon as webview finishes loading , progress bar should be GONE.

But I am not able to create that binding

I have created Binding adapter for webview to load url and also set WebViewClient to check page loading is finished but cannot update the visibility of progressbar

////////////// Post

@BindingAdapter({"app:webUrl"})
    public void configureWebView(WebView iWebView, String iUrl) {

        iWebView.getSettings().setJavaScriptEnabled(true);
        iWebView.setWebViewClient(new WebViewClient() {

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                // code to set visibility of progress bar
            }
        });

        iWebView.loadUrl(iUrl);
    }

//////////////////// Layout

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <import type="android.view.View" />

        <variable
            name="newsUrl"
            type="com.example.bindingdemo.data.model.Post" />
    </data>


    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <WebView
            android:id="@+id/news_web_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:webUrl="@{newsUrl.url}" />

        <ProgressBar
            android:id="@+id/news_prog_bar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="@{**<WhatConditionToWrite>** ? View.GONE: View.Visible}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.constraint.ConstraintLayout>
</layout>
Napolean
  • 5,303
  • 2
  • 29
  • 35

1 Answers1

10

In your BindingAdapter

@BindingAdapter({ "setWebViewClient" })
public static void setWebViewClient(WebView view, WebViewClient client) {
    view.setWebViewClient(client);
}

@BindingAdapter({ "loadUrl" })
public static void loadUrl(WebView view, String url) {
    view.loadUrl(url);
}

In your ViewModel

public class YourObjectModel extends BaseObservable {

    private class Client extends WebViewClient {
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request,
            WebResourceError error) {
            super.onReceivedError(view, request, error);
            setHideProgress(true);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            setHideProgress(true);
        }
    }

    public WebViewClient getWebViewClient() {
        return new Client();
    }

    @Bindable
    public boolean isHideProgress() {
        return hideProgress;
    }

    private void setHideProgress(boolean hideProgress) {
        this.hideProgress = hideProgress;
        notifyPropertyChanged(BR.hideProgress);
    }
}

XML

<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="viewModel"
            type="YourObjectModel"
            />
    </data>
    <WebView 
            ... 
            app:loadUrl="@{viewModel.url}"  
            app:setWebViewClient="@{viewModel.webViewClient}" />
    <ProgressBar 
            ... 
            android:visibility="@{viewModel.hideProgress ? View.GONE : View.VISIBLE}" />

</layout>
Linh
  • 57,942
  • 23
  • 262
  • 279
  • I am not using any ViewModel. Just the Model class holding data and simple data binding. Can we do that ? – Napolean Jun 01 '17 at 08:29
  • @Napolean this Model is the ViewModel ^^ – Linh Jun 01 '17 at 08:30
  • Thanks Phan. It worked. I just changed hideProgress to be as following with accessors and mutators public ObservableBoolean hideProgress = new ObservableBoolean(); – Napolean Jun 01 '17 at 08:51
  • 1
    We can merge the multipe binding adapters @BindingAdapter({"loadUrl", "setWebViewClient"}) public static void loadUrl(WebView view, String url, WebViewClient client) { view.setWebViewClient(client) view.loadUrl(url); } – Napolean Jun 01 '17 at 09:27