Hiding/Showing the toolbar when fragment in the tabs is scrolled

38,026

Solution 1

Try this.

main.xml

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinatorLayout"
    android:layout_height="match_parent"
    android:layout_width="match_parent"   
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbarsdfs"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"/>

        <android.support.design.widget.TabLayout
            android:id="@+id/tabLayout"
            android:scrollbars="horizontal"
            android:layout_below="@+id/toolbarsdfs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            app:tabTextColor="@android:color/white"
            app:tabSelectedTextColor="@android:color/white"
            app:tabIndicatorColor="@android:color/white"
            app:tabIndicatorHeight="3dp" />

    </android.support.design.widget.AppBarLayout>
    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_below="@+id/tablayout"/>
    </android.support.design.widget.CoordinatorLayout>

fragmentfeeds.xml

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v4.widget.NestedScrollView
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:isScrollContainer="false"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="fill_vertical"
            android:clipToPadding="false"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

    <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <android.support.v4.widget.SwipeRefreshLayout
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/swipe"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="#FFFFFF">     

    <WebView
             android:id="@+id/webviewtool"
             android:layout_width="match_parent"
             android:layout_height="fill_parent"
             android:numColumns="1"
             android:focusableInTouchMode="false"
             android:focusable="false"
             android:background="#FFFFFF" />
</android.support.v4.widget.SwipeRefreshLayout>
             </LinearLayout>
    </android.support.v4.widget.NestedScrollView>

Solution 2

Firstly, You should move your webview into NestedScrollView and set 'android:isScrollContainer' property to 'false' value. https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html

Secondly, You should move your ViewPager outside the AppBarLayout. So, your main.xml should be like this:

<?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"
android:id="@+id/main_content"
android:background="#FFF"
android:clickable="true"
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">

    <!-- your app bar stuff here -->
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="240dp"
        app:layout_scrollFlags="scroll|enterAlways">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:id="@+id/image_header"/>

        <include layout="@layout/header"/>

    </FrameLayout>

    <android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        android:background="#FFF"
        app:tabTextColor="#a3a3a3"
        app:tabSelectedTextColor="#a3a3a3"
        app:tabIndicatorColor="#0042ab"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

</android.support.design.widget.AppBarLayout>

<android.support.v4.view.ViewPager
    android:id="@+id/viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="gone"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    android:background="#eaeaea"/>

AppBarLayout childern will hide only if they have flag app:layout_scrollFlags

Read more about implementing support design library here:
https://android-developers.googleblog.com/2015/05/android-design-support-library.html

Solution 3

Have a look at

Solution 4

You should move your ViewPager outside the AppBarLayout and add behavior to ViewPager app:layout_behavior="@string/appbar_scrolling_view_behavior"

I wrote a full example! https://github.com/erikcaffrey/AndroidDesignSupportLibrary

I hope it help you!

Solution 5

im sorry about my english.

I'll show you how i've made that for my app (min sdk: 14, target sdk: 22). I dont use fragments, i only have a single webview in my activity, but the handler is the same. The probles is when you make scroll inside a webview, Android doesn't handle that like a scroll event, the webview handles his own events.

First i define the styles.xml in res folder. I use a transparent and overlayed ActionBar, thats better when you want to hide and show that:

res/styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="@android:style/Theme.Holo">
        <!-- Customize your theme here. -->
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:actionBarStyle">@style/MyActionBar</item>

    </style>

    <!-- ACTION BAR STYLES -->
    <style name="MyActionBar" parent="@android:style/Widget.Holo.ActionBar">
        <item name="android:background">@color/actionbar_background</item>

    </style>

</resources>

then at the manifest, i define the styles for the app and the ActionBar in the application section:

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

finally in the MainActivity, you must control the gestures in the webview. You must implements the View.OnTouchListener, and the Handler.Callback. When you touch on the webview, you must compare the start event and the end event:

MainActivity.Java

public class MainActivity extends Activity implements View.OnTouchListener, Handler.Callback {

    private float x1,x2,y1,y2; //x1, y1 is the start of the event, x2, y2 is the end.
    static final int MIN_DISTANCE = 150; //min distance for a scroll up event

    private static final int CLICK_ON_WEBVIEW = 1;
    private static final int CLICK_ON_URL = 2;
    private static final int UP_ON_WEBVIEW = 3;


    private final Handler handler = new Handler(this);

    public WebView webView;
    private WebViewClient client;
    private WebAppInterface webAppInt = new WebAppInterface(this);


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = (WebView)findViewById(R.id.myWebView);
        webView.setOnTouchListener(this);

        client = new WebViewClient();
        webView.setWebViewClient(client);        
        webView.loadDataWithBaseURL("file:///android_asset/", "myweb.html", "text/html", "UTF-8", "");

    }

//HERE START THE IMPORTANT PART
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (v.getId() == R.id.myWebView && event.getAction() == MotionEvent.ACTION_DOWN){
            x1 = event.getX();
            y1 = event.getY();
            handler.sendEmptyMessageDelayed(CLICK_ON_WEBVIEW, 200);
        } else if (v.getId() == R.id.myWebView && event.getAction() == MotionEvent.ACTION_UP){
            x2 = event.getX();
            y2 = event.getY();

            handler.sendEmptyMessageDelayed(UP_ON_WEBVIEW, 200);
        }

        return false;
    }

    @Override
    public boolean handleMessage(Message msg) {
        if (msg.what == CLICK_ON_URL){ //if you clic a link in the webview, thats not a scroll
            handler.removeMessages(CLICK_ON_WEBVIEW);
            handler.removeMessages(UP_ON_WEBVIEW);
            return true;
        }
        if (msg.what == CLICK_ON_WEBVIEW){

            Toast.makeText(this, "WebView clicked", Toast.LENGTH_SHORT).show();
            return true;
        }
        if (msg.what == UP_ON_WEBVIEW){
            float deltaX = x2 - x1; //horizontal move distance
            float deltaY = y2 - y1; //vertical move distance
            if ((Math.abs(deltaX) > MIN_DISTANCE) && (Math.abs(deltaX) > Math.abs(deltaY)))
            {
                // Left to Right swipe action
                if (x2 > x1)
                {
                    Toast.makeText(this, "Left to Right swipe [Next]", Toast.LENGTH_SHORT).show ();
                }

                // Right to left swipe action
                else
                {
                    Toast.makeText(this, "Right to Left swipe [Previous]", Toast.LENGTH_SHORT).show ();
                }

            }
            else if ((Math.abs(deltaY) > MIN_DISTANCE) && (Math.abs(deltaY) > Math.abs(deltaX)))
            {
                // Top to Bottom swipe action -- i SWOW MY ACTIONBAR ON SCROLLDOWN
                if (y2 > y1)
                {
                    getActionBar().show();
                    Toast.makeText(this, "Top to Bottom swipe [Show Bar]", Toast.LENGTH_SHORT).show ();
                }

                // Bottom to top swipe action -- I HIDE MY ACTIONBAR ON SCROLLUP
                else
                {
                    getActionBar().hide();
                    Toast.makeText(this, "Bottom to Top swipe [Hide Bar]", Toast.LENGTH_SHORT).show ();
                }
            }
            return true;
        }
        return false;
    }
}

I hope thats helps you.

Share:
38,026

Related videos on Youtube

Faiyaz
Author by

Faiyaz

My name is Faiyaz Ansari and i am from India. I am doing Computer science.

Updated on March 29, 2020

Comments

  • Faiyaz
    Faiyaz about 4 years

    I added the new Toolbar, Tablayout and Viewpager in my android app. I provided Fragments for my 3 Tabs and its working fine. But the problem is that when i scroll up my Toolbar does not hide. I want that when i scroll my fragment it should hide. And one more thing, i am using Webview in the fragment. My codes are given below.

    MainActivity.Java

    public class MainActivity extends AppCompatActivity {
        TabLayout tabLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
            setupToolbar();
            setupTablayout();
        }
    
    private void setupToolbar() {
        // TODO Auto-generated method stub
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbarsdfs);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);}
    }
    
    private void setupTablayout() {
        // TODO Auto-generated method stub
        tabLayout = (TabLayout) findViewById(R.id.tabLayout);
        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
        tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
        tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
        final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
        final PagerAdapter adapter = new PagerAdapter
                (getSupportFragmentManager(), tabLayout.getTabCount());
        viewPager.setAdapter(adapter);
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                viewPager.setCurrentItem(tab.getPosition());
            }
    
            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
    
            }
    
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
    
            }
        });
    }
    }
    

    main.xml

    <android.support.design.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/coordinatorLayout"
        android:layout_height="match_parent"
        android:layout_width="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/toolbarsdfs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimaryDark"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
        app:layout_scrollFlags="scroll|enterAlways"/>
    
    <android.support.design.widget.TabLayout
                android:id="@+id/tabLayout"
                android:scrollbars="horizontal"
                android:layout_below="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="?attr/colorPrimary" />
    
    <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="fill_parent"
            android:layout_below="@+id/tablayout"/>
    
    </android.support.design.widget.AppBarLayout>
    </android.support.design.widget.CoordinatorLayout>
    

    PagerAdapter.Java

    public class PagerAdapter extends FragmentStatePagerAdapter {
        int mNumOfTabs;
    
        public PagerAdapter(FragmentManager fm, int NumOfTabs) {
            super(fm);
            this.mNumOfTabs = NumOfTabs;
        }
    
        @Override
        public Fragment getItem(int position) {
    
            switch (position) {
                case 0:
                    Fragment_Feeds tab1 = new Fragment_Feeds();
                    return tab1;
                case 1:
                    Fragment_Facts tab2 = new Fragment_Facts();
                    return tab2;
                default:
                    return null;
            }
        }
    
        @Override
        public int getCount() {
            return mNumOfTabs;
        }
    }
    

    Fragment_Feeds.java

    public class Fragment_Feeds extends Fragment {
        SwipeRefreshLayout swipeView;
        WebView myWebView;
        ProgressBar progressBar;
        final static String myBlogAddr = "http://myblog.com";
        String myUrl;
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragmentfeeds, container, false);
            swipeView = (SwipeRefreshLayout) view.findViewById(R.id.swipe);
    
            myWebView = (WebView) view.findViewById(R.id.webview);
            progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
            myWebView.setWebViewClient(new MyWebViewClient()); 
            WebSettings webSettings = myWebView.getSettings();
            webSettings.setJavaScriptEnabled(true);
            myWebView.setOverScrollMode(View.OVER_SCROLL_NEVER);
            myWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
            myWebView.setHorizontalScrollBarEnabled(false);
            myWebView.loadUrl("http://myblog.com");
            swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener()    
            {
                @Override
                public void onRefresh() 
                {
                      myWebView.loadUrl("http://myblog.com");
    
                }});
            return view;
        }
        private class MyWebViewClient extends WebViewClient {
            @Override
            public void onPageFinished(WebView view, String url) {
                swipeView.setRefreshing(false);
            }
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
             myUrl = url;
                view.loadUrl(url);
                return true;
            }
            @Override
            public void onReceivedError(WebView view, int errorCod,String description, String failingUrl) {
                myWebView.loadUrl("file:///android_asset/error_page.html");
            }
        }
        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            inflater.inflate(R.menu.main, menu);
            super.onCreateOptionsMenu(menu, inflater);
        }
    }
    

    fragmentfeeds.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#FFFFFF" >
        <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
        <android.support.v4.widget.SwipeRefreshLayout
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/swipe"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="#FFFFFF">s
    
        <WebView
          android:id="@+id/webview"
          android:layout_width="match_parent"
          android:layout_height="fill_parent"
          android:numColumns="1"
          android:scrollbars="none"
          android:focusableInTouchMode="false"
          android:focusable="false"
          android:background="#FFFFFF" />
       </android.support.v4.widget.SwipeRefreshLayout>
    
    </LinearLayout>
    

    What i want?

    What i want is that when i scroll the webview upwards, the toolbar should also scroll upwards and hides and when i scroll back down the toolbar should come back as soon as possible.

    • Pankaj Arora
      Pankaj Arora over 8 years
    • Ashish Dwivedi
      Ashish Dwivedi over 8 years
      Add app:layout_scrollFlags="scroll|enterAlways" in toolbar
    • Vikash Kumar Verma
      Vikash Kumar Verma over 7 years
      if you are using gridview in fragment then add android:nestedScrollingEnabled="true" in gridview
  • Faiyaz
    Faiyaz over 8 years
    I cannot use <include layout="@layout/header> because i am using tablayout.
  • Andrew
    Andrew over 8 years
    It's just an example. I edit your xml gist.github.com/devindi/e46b0206aa84228831b4
  • Faiyaz
    Faiyaz over 8 years
    I think you didn't understood my question. Actually i am using fragments for the tab.
  • Andrew
    Andrew over 8 years
    I write same app few weeks ago. So I understood you. I has big scrollable header, tab layout and view pager with 3 fragments. Right?
  • Faiyaz
    Faiyaz over 8 years
    No my app don't have big scrollable header. It has a toolbar, Tablayout, and viewpager. And i dont want to hide tablayout on scroll , i just want to hide toolbar on scroll.
  • Faiyaz
    Faiyaz over 8 years
    and yead view pager have 2 fragments.
  • Andrew
    Andrew over 8 years
    So, you need smth like that dropbox.com/s/1apmu35aie2cp0p/output.gif?dl=0
  • Faiyaz
    Faiyaz over 8 years
    Yes i want something like that
  • Faiyaz
    Faiyaz over 8 years
    If i take the viewpager out of AppBar it fill the whole screen