How to Hide ActionBar/Toolbar While Scrolling Down in Webview

26,872

Solution 1

You can do this without any Java code using the design library's CoordinatorLayout and NestedScrollView, with app:layout_scrollFlags set on Toolbar. Here's how you do it.

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
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/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|enterAlways"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.AppBarLayout>

<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="fill_vertical"
   android:fillViewport="true"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

You can play around with with different layout_scrollFlags and fitsSystemWindows behaviour once you get the hang of it.

Solution 2

Well I have implemented by CustomWebView and GestureDetector:

CustomWebView.java:

public class CustomWebView extends WebView {
    private GestureDetector gestureDetector;
    public CustomWebView(Context context) {
        super(context);
    }
    public CustomWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public CustomWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return gestureDetector.onTouchEvent(ev) || super.onTouchEvent(ev);
    }

    public void setGestureDetector(GestureDetector gestureDetector) {
        this.gestureDetector = gestureDetector;
    }
}

web_fragment.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent"
    android:orientation="vertical">

   <com.customview.CustomWebView
            android:id="@+id/customWebView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:focusable="true" />

</LinearLayout>

CustomeGestureDetector clss for Gesture Detection (I have added in Fragment):

private class CustomeGestureDetector extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            if(e1 == null || e2 == null) return false;
            if(e1.getPointerCount() > 1 || e2.getPointerCount() > 1) return false;
            else {
                try {
                    if(e1.getY() - e2.getY() > 20 ) {
                            // Hide Actionbar
                        getSupportActionBar().hide();
                        customWebView.invalidate();
                       return false;
                    }
                    else if (e2.getY() - e1.getY() > 20 ) {
                            // Show Actionbar
                        getSupportActionBar().show();
                        customWebView.invalidate();
                       return false;
                    }

                } catch (Exception e) {
                    customWebView.invalidate();
                }
                return false;
            }


        }
    }

WebFragment.java:

private CustomWebView customWebView;

customWebView= (CustomWebView) view.findViewById(R.id.customWebView);

customWebView.setGestureDetector(new GestureDetector(new CustomeGestureDetector()));

It works fine for me, hope it would help you.

Solution 3

enter image description here

package com.keshav.hideactionbarandfooterexample;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageButton;

import java.util.ArrayList;
import java.util.List;

import adapters.RecyclerAdapter;
import listners.HidingScrollListener;

public class MainActivity extends AppCompatActivity {

    private Toolbar mToolbar;
    private Toolbar toolbar_bottom;
    private ImageButton mFabButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(R.style.AppThemeRed);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.e("keshav", "MainActivity called");

        initToolbar();
        mFabButton = (ImageButton) findViewById(R.id.fabButton);
        initRecyclerView();
    }

    private void initToolbar() {
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar_bottom = (Toolbar) findViewById(R.id.toolbar_bottom);
        setSupportActionBar(mToolbar);
        setSupportActionBar(toolbar_bottom);
        setTitle(getString(R.string.app_name));
        mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
        toolbar_bottom.setTitleTextColor(getResources().getColor(android.R.color.white));


        toolbar_bottom.setVisibility(View.GONE);
    }

    private void initRecyclerView() {
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList());
        recyclerView.setAdapter(recyclerAdapter);

        recyclerView.addOnScrollListener(new HidingScrollListener() {
            @Override
            public void onHide() {
                hideViews();
            }

            @Override
            public void onShow() {
                showViews();
            }
        });
    }

    private void hideViews() {
        // TODO (-mToolbar)  plus means  2 view above ho jaye or not visible to user
        mToolbar.animate().translationY(-mToolbar.getHeight()).setInterpolator(new AccelerateInterpolator(2));

        // TODO uncomment this Hide Footer in android when Scrolling
        // TODO (+mToolbar)  plus means  2 view forward ho jaye or not visible to user
        toolbar_bottom.animate().translationY(+toolbar_bottom.getHeight()).setInterpolator(new AccelerateInterpolator(2));

        // TODO keshav Hide Also Floatng Button In Android
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mFabButton.getLayoutParams();
        int fabBottomMargin = lp.bottomMargin;
        mFabButton.animate().translationY(mFabButton.getHeight() + fabBottomMargin).setInterpolator(new AccelerateInterpolator(2)).start();
        // TODO keshav Hide Also Floatng Button In Android
    }

    private void showViews() {
        mToolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));

        // TODO uncomment this Hide Footer in android when Scrolling
        toolbar_bottom.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));
        mFabButton.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start();
    }

    private List<String> createItemList() {
        List<String> itemList = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            itemList.add("Item " + i);
        }
        return itemList;
    }
}

=============================================
             RecyclerAdapter
=============================================
package adapters;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.keshav.hideactionbarandfooterexample.R;

import java.util.List;

/*
* RecyclerView Adapter that allows to add a header view.
* */
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final int TYPE_HEADER = 2;
    private static final int TYPE_ITEM = 1;
    private List<String> mItemList;

    public RecyclerAdapter(List<String> itemList) {
        mItemList = itemList;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        if (viewType == TYPE_ITEM) {
            final View view = LayoutInflater.from(context).inflate(R.layout.recycler_item, parent, false);
            return RecyclerItemViewHolder.newInstance(view);
        } else if (viewType == TYPE_HEADER) {
            final View view = LayoutInflater.from(context).inflate(R.layout.recycler_header, parent, false);
            return new RecyclerHeaderViewHolder(view);
        }
        throw new RuntimeException("There is no type that matches the type " + viewType + " + make sure your using types correctly");
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
        if (!isPositionHeader(position)) {
            RecyclerItemViewHolder holder = (RecyclerItemViewHolder) viewHolder;
            String itemText = mItemList.get(position - 1); // header
            holder.setItemText(itemText);
        }
    }

    public int getBasicItemCount() {
        return mItemList == null ? 0 : mItemList.size();
    }


    @Override
    public int getItemViewType(int position) {
        if (isPositionHeader(position)) {
            return TYPE_HEADER;
        }

        return TYPE_ITEM;
    }

    @Override
    public int getItemCount() {
        return getBasicItemCount() + 1; // header
    }

    private boolean isPositionHeader(int position) {
        return position == 0;
    }

}

=====================================================
         RecyclerHeaderViewHolder
=====================================================
package adapters;

import android.support.v7.widget.RecyclerView;
import android.view.View;

public class RecyclerHeaderViewHolder extends RecyclerView.ViewHolder {
    public RecyclerHeaderViewHolder(View itemView) {
        super(itemView);
    }
}

=====================================================
              RecyclerItemViewHolder
=====================================================

package adapters;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;

import com.keshav.hideactionbarandfooterexample.R;


public class RecyclerItemViewHolder extends RecyclerView.ViewHolder {

    private final TextView mItemTextView;

    public RecyclerItemViewHolder(final View parent, TextView itemTextView) {
        super(parent);
        mItemTextView = itemTextView;
    }

    public static RecyclerItemViewHolder newInstance(View parent) {
        TextView itemTextView = (TextView) parent.findViewById(R.id.itemTextView);
        return new RecyclerItemViewHolder(parent, itemTextView);
    }

    public void setItemText(CharSequence text) {
        mItemTextView.setText(text);
    }

}

===================================================
            activity_main.xml
===================================================

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"/>

    <ImageButton
            android:id="@+id/fabButton"
            android:layout_width="56dp"
            android:layout_height="56dp"
            android:layout_gravity="bottom|right"
            android:layout_marginBottom="16dp"
            android:layout_marginRight="16dp"
            android:background="@drawable/fab_bcg"
            android:src="@drawable/ic_favorite_outline_white_24dp"
            android:contentDescription="@string/fab_description"/>


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar_bottom"
        android:layout_width="match_parent"
        android:layout_alignParentBottom="true"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"/>

    </RelativeLayout>

</FrameLayout>


==================================================
    recycle_header.xml in layout folder
==================================================

<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"/>

==================================================
    recycle_item.xml in layout folder
==================================================
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_margin="8dp"
    card_view:cardCornerRadius="4dp">
    <TextView
        android:id="@+id/itemTextView"
        android:layout_width="match_parent"
        android:layout_height="?attr/listPreferredItemHeight"
        android:gravity="center_vertical"
        android:padding="8dp"
        style="@style/Base.TextAppearance.AppCompat.Body2"/>
</android.support.v7.widget.CardView>


=================================================
                      styles.xml
=================================================
<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    </style>

    <style name="AppThemeRed" parent="AppTheme">
        <item name="colorPrimary">@color/color_primary_red</item>
        <item name="colorPrimaryDark">@color/color_primary_red_dark</item>
    </style>

    <style name="AppThemeGreen" parent="AppTheme">
        <item name="colorPrimary">@color/color_primary_green</item>
        <item name="colorPrimaryDark">@color/color_primary_green_dark</item>
    </style>

    <style name="AppThemeBlue" parent="AppTheme">
        <item name="colorPrimary">@color/color_primary_blue</item>
        <item name="colorPrimaryDark">@color/color_primary_blue_dark</item>
        <item name="colorAccent">@color/color_accent_pink</item>
    </style>

</resources>

build.gradle Dependency

  compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support:recyclerview-v7:25.3.1'
    compile 'com.android.support:cardview-v7:25.3.1'
    compile 'com.android.support:design:25.3.1'
Share:
26,872

Related videos on Youtube

Sathish Kumar
Author by

Sathish Kumar

I'm a Full-stack developer in mobile &amp; web applications.

Updated on June 05, 2020

Comments

  • Sathish Kumar
    Sathish Kumar almost 4 years

    In Google chrome and play store. the app can hide the actionbar while scrolling and allows the user to Browse conveniently. Please Help me to do like this.

    I've used onTouchListener for webview it doesn't works.

    mWebView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            getSupportActionBar().show();
                                break;
                        case MotionEvent.ACTION_UP:
                            getSupportActionBar().hide();
                                break;
                        default: break;
                    }
                    return false;
                }
            });
    

    Thanks in Advance

    • Radheshyam Singh
      Radheshyam Singh about 9 years
      Example for hiding action bar is here
    • Sathish Kumar
      Sathish Kumar about 9 years
      This Example shows for Linear Layout. how to implement this in webview
    • Radheshyam Singh
      Radheshyam Singh about 9 years
      There is an example here [stackoverflow.com/questions/14752523/…
  • LarsH
    LarsH almost 7 years
    Thanks for this, it's very helpful! However I would change the name of your CustomGestureDetector class to CustomGestureDetectorListener or something, because it's not a GestureDetector. As it is, it's confusing.
  • Keshav Gera
    Keshav Gera almost 7 years
  • Gabriel Gómez
    Gabriel Gómez over 6 years
    This works great, but you loose the "zoom" by gesture. Is there a way to get it again in this solution? Thanks
  • Alexei Fando
    Alexei Fando about 6 years
    Some may find it necessary to add android:fillViewport="true" to NestedScrollView to make it take up the full available height of its container. Strangely, android:layout_gravity="fill_vertical", was not enough to achieve that in all cases.
  • Sudarshan
    Sudarshan almost 6 years
    It's working as expected with this error "java.lang.IllegalStateException: Unable to create layer for WebView, size 1200x17076 exceeds max size 16384". Is there any solution?
  • Ioane Sharvadze
    Ioane Sharvadze almost 6 years
    Adding new layout will decrease performance. This is not correct solution. As for your issue @Sudarshan, it is happening, because it will create full size webview (same as a webpage) and try to render it. Because of that, you will loose webview optimisations, where only part of a page is rendered. I would not suggest to use this solution.
  • Developer Vicky
    Developer Vicky almost 6 years
    Bad practice to use Webview in ScrollView, Jump link will not work.
  • willcwf
    willcwf over 5 years
    This does not work correctly for pages where the DOM is populated by javascript after the page load. The height is incorrect: issuetracker.google.com/issues/37077954#makechanges and thus the scrolling does not work.
  • Bartłomiej Uliasz
    Bartłomiej Uliasz about 5 years
    Changing android:layout_height="match_parent" to android:layout_height="wrap_content" in WebView prevents misbehaviour on change of text size and other content modification of WebView. For example decreasing font size with webView.settings.textZoom (Kotlin) will make unnecessary blank space at the end of the WebView content with current code.