The NestedScrollView
provided with the support library doesn't work properly with the WebView
(related bug report). Because of this I have set out to implement NestedScrollingChild
for a WebView
and it appears to work fine for the first scroll, collapsing and expanding the AppBarLayout
but any subsequent scrolls fail to collapse it.
My WebView
:
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.support.v4.view.NestedScrollingChild;
import android.support.v4.view.NestedScrollingChildHelper;
import android.util.AttributeSet;
import android.view.View;
import android.webkit.WebView;
/**
* Created by carlos on 2/19/16.
*/
public class MyWebView extends WebView implements NestedScrollingChild {
private static final String TAG = MyWebView.class.getSimpleName();
private NestedScrollingChildHelper helper = new NestedScrollingChildHelper(this);
public MyWebView(Context context) {
super(context);
}
public MyWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public MyWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public MyWebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
super(context, attrs, defStyleAttr, privateBrowsing);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
int dx = l - oldl;
int dy = t - oldt;
if (dy != 0) helper.startNestedScroll(View.SCROLL_AXIS_VERTICAL);
helper.dispatchNestedPreScroll(dx, dy, null, null);
if (dy != 0) helper.stopNestedScroll();
super.onScrollChanged(l, t, oldl, oldt);
}
@Override
public boolean isNestedScrollingEnabled() {
return helper.isNestedScrollingEnabled();
}
@Override
public void setNestedScrollingEnabled(boolean enabled) {
helper.setNestedScrollingEnabled(enabled);
}
@Override
public boolean startNestedScroll(int axes) {
return helper.startNestedScroll(axes);
}
@Override
public void stopNestedScroll() {
helper.stopNestedScroll();
}
@Override
public boolean hasNestedScrollingParent() {
return helper.hasNestedScrollingParent();
}
@Override
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
return helper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
}
@Override
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
return helper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
}
@Override
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
return helper.dispatchNestedFling(velocityX, velocityY, consumed);
}
@Override
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
return helper.dispatchNestedPreFling(velocityX, velocityY);
}
}
My activity:
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebViewClient;
public class ScrollingActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scrolling);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
MyWebView view = (MyWebView) findViewById(R.id.webview);
view.setNestedScrollingEnabled(true);
view.setWebViewClient(new WebViewClient());
WebSettings settings = view.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAllowContentAccess(true);
settings.setAppCacheEnabled(true);
settings.setDatabaseEnabled(true);
settings.setDomStorageEnabled(true);
settings.setRenderPriority(WebSettings.RenderPriority.HIGH);
settings.setJavaScriptEnabled(true);
settings.setSupportZoom(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setBuiltInZoomControls(true);
settings.setAppCacheEnabled(true);
settings.setAppCachePath(getCacheDir().getAbsolutePath());
settings.setDatabaseEnabled(true);
settings.setSupportMultipleWindows(true);
settings.setLoadWithOverviewMode(true);
settings.setUseWideViewPort(true);
settings.setDomStorageEnabled(true);
settings.setAllowContentAccess(true);
settings.setAllowFileAccess(true);
settings.setSaveFormData(true);
// findViewById(R.id.nested).setLayerType(View.LAYER_TYPE_HARDWARE, null);
// view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
view.loadUrl("http://vimeo.com");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_scrolling, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
My styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
</resources>
My dimensions file:
<resources>
<dimen name="app_bar_height">180dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="text_margin">16dp</dimen>
</resources>
My activity layout (activity_scrolling.xml
):
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.childscrollview.ScrollingActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|snap|enterAlways">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<com.childscrollview.MyWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
></com.childscrollview.MyWebView>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email"
app:layout_anchor="@id/app_bar"
app:layout_anchorGravity="bottom|end"/>
</android.support.design.widget.CoordinatorLayout>
So what is wrong with my implementation or is this a bug?
Thanks.
EDIT: Google now says the WebView isn't supported like this.
I had tested many WebView
, which implements NestedScrollingChild
.
However, the only correct implementation, is found at https://github.com/takahirom/webview-in-coordinatorlayout/blob/master/app/src/main/java/com/github/takahirom/webview_in_coodinator_layout/NestedWebView.java
You can use NestedWebView
without any modification. It works very smoothly.
I would also like to share my XML files.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/coordinator_layout"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="4dp"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" >
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar_layout"
app:layout_scrollFlags="scroll|enterAlways|snap"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary">
<!-- Toolbar -->
<include layout="@layout/toolbar"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<!-- http://stackoverflow.com/questions/14171471/remove-vertical-padding-from-horizontal-progressbar -->
<!-- http://stackoverflow.com/questions/32464749/horizontal-progress-bar-is-not-visible-if-placed-above-toolbar-for-android-5 -->
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="8dp"
android:id="@+id/progress_bar"
android:layout_gravity="top"
android:layout_marginBottom="0dp"
android:layout_marginTop="-4dp"
android:elevation="4dp"
android:max="100" />
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="?attr/headerShadow"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
A fragment, contains ViewAnimator
(Multiple WebView
is added into ViewAnimator
and a bottom navigation bar.
The fragment is added into content
FragmeLayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/web_view_linear_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal" >
<ViewAnimator
android:id="@+id/web_view_view_animator"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
<LinearLayout
android:id="@+id/navigation_linear_layout"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="?attr/colorPrimary"
android:orientation="horizontal" >
<LinearLayout
android:id="@+id/left_linear_layout"
android:layout_width="0dp"
android:width="0dp"
android:layout_weight="0.5"
android:layout_height="match_parent"
android:gravity="left"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:theme="@style/Base.ThemeOverlay.AppCompat.Dark" >
<ImageView
android:id="@+id/left_image_view"
android:scaleType="center"
android:src="@drawable/ic_chevron_left_white_24dp"
android:layout_width="48dp"
android:layout_height="match_parent" />
</LinearLayout>
<LinearLayout
android:id="@+id/right_linear_layout"
android:layout_width="0dp"
android:width="0dp"
android:layout_weight="0.5"
android:layout_height="match_parent"
android:gravity="right"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:theme="@style/Base.ThemeOverlay.AppCompat.Dark"
android:orientation="horizontal">
<TextView
android:id="@+id/next_text_view"
android:layout_width="0dp"
android:width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center_vertical|right"
android:ellipsize="end"
android:textSize="12sp"
android:maxLines = "2"
android:minLines = "1"
android:lineSpacingMultiplier="1.2"/>
<ImageView
android:id="@+id/right_image_view"
android:scaleType="center"
android:src="@drawable/ic_chevron_right_white_24dp"
android:layout_width="48dp"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
Here's the outcome
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With