├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── pl │ │ └── michalz │ │ └── hideonscrollexample │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── pl │ │ └── michalz │ │ └── hideonscrollexample │ │ ├── ScrollingFABBehavior.java │ │ ├── Utils.java │ │ ├── activity │ │ ├── MainActivity.java │ │ ├── partone │ │ │ └── PartOneActivity.java │ │ ├── partthree │ │ │ └── PartThreeActivity.java │ │ └── parttwo │ │ │ └── PartTwoActivity.java │ │ ├── adapter │ │ ├── partone │ │ │ ├── RecyclerAdapter.java │ │ │ └── viewholder │ │ │ │ ├── RecyclerHeaderViewHolder.java │ │ │ │ └── RecyclerItemViewHolder.java │ │ └── parttwo │ │ │ ├── RecyclerAdapter.java │ │ │ └── viewholder │ │ │ └── RecyclerItemViewHolder.java │ │ ├── fragment │ │ └── PartThreeFragment.java │ │ └── listener │ │ ├── partone │ │ └── HidingScrollListener.java │ │ └── parttwo │ │ └── HidingScrollListener.java │ └── res │ ├── drawable-hdpi │ └── ic_favorite_outline_white_24dp.png │ ├── drawable-mdpi │ └── ic_favorite_outline_white_24dp.png │ ├── drawable-xhdpi │ └── ic_favorite_outline_white_24dp.png │ ├── drawable-xxhdpi │ └── ic_favorite_outline_white_24dp.png │ ├── drawable │ └── fab_bcg.xml │ ├── layout │ ├── activity_main.xml │ ├── activity_part_one.xml │ ├── activity_part_three.xml │ ├── activity_part_two.xml │ ├── fragment_part_three.xml │ ├── recycler_header.xml │ ├── recycler_item.xml │ └── tabs.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-v21 │ └── dimen.xml │ └── values │ ├── color.xml │ ├── dimen.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | Application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | 25 | # Log Files 26 | *.log 27 | 28 | # Intellij project files 29 | *.iml 30 | *.ipr 31 | *.iws 32 | .idea/ 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | HideOnScrollExample 2 | ============= 3 | 4 | This example shows how to show/hide views (i.e. Toolbar or FAB) when a list is scrolled up/down. 5 | 6 | There is a blog post explaining the code: 7 | 8 | [part 1 - outdated](http://mzgreen.github.io/2015/02/15/How-to-hideshow-Toolbar-when-list-is-scroling%28part1%29/) 9 | 10 | [part 2 - outdated](http://mzgreen.github.io/2015/02/28/How-to-hideshow-Toolbar-when-list-is-scrolling%28part2%29/) 11 | 12 | [part 3](https://mzgreen.github.io/2015/06/23/How-to-hideshow-Toolbar-when-list-is-scrolling%28part3%29/) 13 | 14 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | applicationId "pl.michalz.hideonscrollexample" 9 | minSdkVersion 14 10 | targetSdkVersion 22 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:appcompat-v7:22.2.0' 25 | compile 'com.android.support:recyclerview-v7:22.2.0' 26 | compile 'com.android.support:cardview-v7:22.2.0' 27 | compile 'com.android.support:design:22.2.0' 28 | } 29 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Android SDK\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/pl/michalz/hideonscrollexample/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 23 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/ScrollingFABBehavior.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample; 2 | 3 | import android.content.Context; 4 | import android.support.design.widget.AppBarLayout; 5 | import android.support.design.widget.CoordinatorLayout; 6 | import android.support.design.widget.FloatingActionButton; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | 10 | public class ScrollingFABBehavior extends FloatingActionButton.Behavior { 11 | private int toolbarHeight; 12 | 13 | public ScrollingFABBehavior(Context context, AttributeSet attrs) { 14 | super(); 15 | this.toolbarHeight = Utils.getToolbarHeight(context); 16 | } 17 | 18 | @Override 19 | public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton fab, View dependency) { 20 | return super.layoutDependsOn(parent, fab, dependency) || (dependency instanceof AppBarLayout); 21 | } 22 | 23 | @Override 24 | public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton fab, View dependency) { 25 | boolean returnValue = super.onDependentViewChanged(parent, fab, dependency); 26 | if (dependency instanceof AppBarLayout) { 27 | CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) fab.getLayoutParams(); 28 | int fabBottomMargin = lp.bottomMargin; 29 | int distanceToScroll = fab.getHeight() + fabBottomMargin; 30 | float ratio = (float)dependency.getY()/(float)toolbarHeight; 31 | fab.setTranslationY(-distanceToScroll * ratio); 32 | } 33 | return returnValue; 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/Utils.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | 6 | public class Utils { 7 | 8 | public static int getToolbarHeight(Context context) { 9 | final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes( 10 | new int[]{R.attr.actionBarSize}); 11 | int toolbarHeight = (int) styledAttributes.getDimension(0, 0); 12 | styledAttributes.recycle(); 13 | 14 | return toolbarHeight; 15 | } 16 | 17 | public static int getTabsHeight(Context context) { 18 | return (int) context.getResources().getDimension(R.dimen.tabsHeight); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample.activity; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.support.v7.widget.Toolbar; 7 | import android.view.View; 8 | import android.widget.Button; 9 | import pl.michalz.hideonscrollexample.R; 10 | import pl.michalz.hideonscrollexample.activity.partone.PartOneActivity; 11 | import pl.michalz.hideonscrollexample.activity.partthree.PartThreeActivity; 12 | import pl.michalz.hideonscrollexample.activity.parttwo.PartTwoActivity; 13 | 14 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 15 | 16 | private Button partOneButton; 17 | private Button partTwoButton; 18 | private Button partThreeButton; 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_main); 24 | 25 | initToolbar(); 26 | 27 | partOneButton = (Button) findViewById(R.id.partOneButton); 28 | partTwoButton = (Button) findViewById(R.id.partTwoButton); 29 | partThreeButton = (Button) findViewById(R.id.partThreeButton); 30 | 31 | partOneButton.setOnClickListener(this); 32 | partTwoButton.setOnClickListener(this); 33 | partThreeButton.setOnClickListener(this); 34 | } 35 | 36 | private void initToolbar() { 37 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 38 | setSupportActionBar(toolbar); 39 | setTitle(getString(R.string.app_name)); 40 | } 41 | 42 | @Override 43 | public void onClick(View v) { 44 | if(v.equals(partOneButton)) { 45 | startActivity(PartOneActivity.class); 46 | } else if(v.equals(partTwoButton)) { 47 | startActivity(PartTwoActivity.class); 48 | } else { 49 | startActivity(PartThreeActivity.class); 50 | } 51 | } 52 | 53 | private void startActivity(Class activityClass) { 54 | Intent myIntent = new Intent(this, activityClass); 55 | startActivity(myIntent); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/activity/partone/PartOneActivity.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample.activity.partone; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.support.v7.widget.LinearLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.support.v7.widget.Toolbar; 8 | import android.view.animation.AccelerateInterpolator; 9 | import android.view.animation.DecelerateInterpolator; 10 | import android.widget.FrameLayout; 11 | import android.widget.ImageButton; 12 | import pl.michalz.hideonscrollexample.R; 13 | import pl.michalz.hideonscrollexample.adapter.partone.RecyclerAdapter; 14 | import pl.michalz.hideonscrollexample.listener.partone.HidingScrollListener; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | public class PartOneActivity extends AppCompatActivity { 20 | 21 | private Toolbar mToolbar; 22 | private ImageButton mFabButton; 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | setTheme(R.style.AppThemeRed); 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_part_one); 29 | 30 | initToolbar(); 31 | mFabButton = (ImageButton) findViewById(R.id.fabButton); 32 | initRecyclerView(); 33 | } 34 | 35 | private void initToolbar() { 36 | mToolbar = (Toolbar) findViewById(R.id.toolbar); 37 | setSupportActionBar(mToolbar); 38 | setTitle(getString(R.string.app_name)); 39 | mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white)); 40 | } 41 | 42 | private void initRecyclerView() { 43 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView); 44 | recyclerView.setLayoutManager(new LinearLayoutManager(this)); 45 | RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList()); 46 | recyclerView.setAdapter(recyclerAdapter); 47 | 48 | recyclerView.addOnScrollListener(new HidingScrollListener() { 49 | @Override 50 | public void onHide() { 51 | hideViews(); 52 | } 53 | 54 | @Override 55 | public void onShow() { 56 | showViews(); 57 | } 58 | }); 59 | } 60 | 61 | private void hideViews() { 62 | mToolbar.animate().translationY(-mToolbar.getHeight()).setInterpolator(new AccelerateInterpolator(2)); 63 | 64 | FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mFabButton.getLayoutParams(); 65 | int fabBottomMargin = lp.bottomMargin; 66 | mFabButton.animate().translationY(mFabButton.getHeight()+fabBottomMargin).setInterpolator(new AccelerateInterpolator(2)).start(); 67 | } 68 | 69 | private void showViews() { 70 | mToolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)); 71 | mFabButton.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start(); 72 | } 73 | 74 | private List createItemList() { 75 | List itemList = new ArrayList<>(); 76 | for(int i=0;i<20;i++) { 77 | itemList.add("Item "+i); 78 | } 79 | return itemList; 80 | } 81 | } -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/activity/partthree/PartThreeActivity.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample.activity.partthree; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.TabLayout; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v4.app.FragmentManager; 7 | import android.support.v4.app.FragmentPagerAdapter; 8 | import android.support.v4.view.ViewPager; 9 | import android.support.v7.app.AppCompatActivity; 10 | import android.support.v7.widget.Toolbar; 11 | import pl.michalz.hideonscrollexample.R; 12 | import pl.michalz.hideonscrollexample.fragment.PartThreeFragment; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | public class PartThreeActivity extends AppCompatActivity { 18 | 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | setTheme(R.style.AppThemeBlue); 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_part_three); 25 | 26 | initToolbar(); 27 | initViewPagerAndTabs(); 28 | } 29 | 30 | private void initToolbar() { 31 | Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar); 32 | setSupportActionBar(mToolbar); 33 | setTitle(getString(R.string.app_name)); 34 | mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white)); 35 | } 36 | 37 | private void initViewPagerAndTabs() { 38 | ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager); 39 | PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager()); 40 | pagerAdapter.addFragment(PartThreeFragment.createInstance(20), getString(R.string.tab_1)); 41 | pagerAdapter.addFragment(PartThreeFragment.createInstance(4), getString(R.string.tab_2)); 42 | viewPager.setAdapter(pagerAdapter); 43 | TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout); 44 | tabLayout.setupWithViewPager(viewPager); 45 | } 46 | 47 | static class PagerAdapter extends FragmentPagerAdapter { 48 | 49 | private final List fragmentList = new ArrayList<>(); 50 | private final List fragmentTitleList = new ArrayList<>(); 51 | 52 | public PagerAdapter(FragmentManager fragmentManager) { 53 | super(fragmentManager); 54 | } 55 | 56 | public void addFragment(Fragment fragment, String title) { 57 | fragmentList.add(fragment); 58 | fragmentTitleList.add(title); 59 | } 60 | 61 | @Override 62 | public Fragment getItem(int position) { 63 | return fragmentList.get(position); 64 | } 65 | 66 | @Override 67 | public int getCount() { 68 | return fragmentList.size(); 69 | } 70 | @Override 71 | public CharSequence getPageTitle(int position) { 72 | return fragmentTitleList.get(position); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/activity/parttwo/PartTwoActivity.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample.activity.parttwo; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.support.v7.widget.LinearLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.support.v7.widget.Toolbar; 8 | import android.view.animation.AccelerateInterpolator; 9 | import android.view.animation.DecelerateInterpolator; 10 | import android.widget.LinearLayout; 11 | import pl.michalz.hideonscrollexample.R; 12 | import pl.michalz.hideonscrollexample.Utils; 13 | import pl.michalz.hideonscrollexample.adapter.parttwo.RecyclerAdapter; 14 | import pl.michalz.hideonscrollexample.listener.parttwo.HidingScrollListener; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | public class PartTwoActivity extends AppCompatActivity { 20 | 21 | private LinearLayout mToolbarContainer; 22 | private int mToolbarHeight; 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | setTheme(R.style.AppThemeGreen); 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_part_two); 29 | 30 | mToolbarContainer = (LinearLayout) findViewById(R.id.toolbarContainer); 31 | initToolbar(); 32 | initRecyclerView(); 33 | } 34 | 35 | private void initToolbar() { 36 | Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar); 37 | setSupportActionBar(mToolbar); 38 | setTitle(getString(R.string.app_name)); 39 | mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white)); 40 | mToolbarHeight = Utils.getToolbarHeight(this); 41 | } 42 | 43 | private void initRecyclerView() { 44 | final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView); 45 | 46 | int paddingTop = Utils.getToolbarHeight(PartTwoActivity.this) + Utils.getTabsHeight(PartTwoActivity.this); 47 | recyclerView.setPadding(recyclerView.getPaddingLeft(), paddingTop, recyclerView.getPaddingRight(), recyclerView.getPaddingBottom()); 48 | 49 | recyclerView.setLayoutManager(new LinearLayoutManager(this)); 50 | RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList()); 51 | recyclerView.setAdapter(recyclerAdapter); 52 | 53 | recyclerView.addOnScrollListener(new HidingScrollListener(this) { 54 | 55 | @Override 56 | public void onMoved(int distance) { 57 | mToolbarContainer.setTranslationY(-distance); 58 | } 59 | 60 | @Override 61 | public void onShow() { 62 | mToolbarContainer.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start(); 63 | } 64 | 65 | @Override 66 | public void onHide() { 67 | mToolbarContainer.animate().translationY(-mToolbarHeight).setInterpolator(new AccelerateInterpolator(2)).start(); 68 | } 69 | 70 | }); 71 | } 72 | 73 | private List createItemList() { 74 | List itemList = new ArrayList<>(); 75 | for(int i=0;i<20;i++) { 76 | itemList.add("Item "+i); 77 | } 78 | return itemList; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/adapter/partone/RecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample.adapter.partone; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import pl.michalz.hideonscrollexample.R; 9 | import pl.michalz.hideonscrollexample.adapter.partone.viewholder.RecyclerHeaderViewHolder; 10 | import pl.michalz.hideonscrollexample.adapter.partone.viewholder.RecyclerItemViewHolder; 11 | 12 | import java.util.List; 13 | 14 | /* 15 | * RecyclerView Adapter that allows to add a header view. 16 | * */ 17 | public class RecyclerAdapter extends RecyclerView.Adapter { 18 | 19 | private static final int TYPE_HEADER = 2; 20 | private static final int TYPE_ITEM = 1; 21 | private List mItemList; 22 | 23 | public RecyclerAdapter(List itemList) { 24 | mItemList = itemList; 25 | } 26 | 27 | @Override 28 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 29 | Context context = parent.getContext(); 30 | if (viewType == TYPE_ITEM) { 31 | final View view = LayoutInflater.from(context).inflate(R.layout.recycler_item, parent, false); 32 | return RecyclerItemViewHolder.newInstance(view); 33 | } else if (viewType == TYPE_HEADER) { 34 | final View view = LayoutInflater.from(context).inflate(R.layout.recycler_header, parent, false); 35 | return new RecyclerHeaderViewHolder(view); 36 | } 37 | throw new RuntimeException("There is no type that matches the type " + viewType + " + make sure your using types correctly"); 38 | } 39 | 40 | @Override 41 | public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { 42 | if (!isPositionHeader(position)) { 43 | RecyclerItemViewHolder holder = (RecyclerItemViewHolder) viewHolder; 44 | String itemText = mItemList.get(position - 1); // header 45 | holder.setItemText(itemText); 46 | } 47 | } 48 | 49 | public int getBasicItemCount() { 50 | return mItemList == null ? 0 : mItemList.size(); 51 | } 52 | 53 | 54 | @Override 55 | public int getItemViewType(int position) { 56 | if (isPositionHeader(position)) { 57 | return TYPE_HEADER; 58 | } 59 | 60 | return TYPE_ITEM; 61 | } 62 | 63 | @Override 64 | public int getItemCount() { 65 | return getBasicItemCount() + 1; // header 66 | } 67 | 68 | private boolean isPositionHeader(int position) { 69 | return position == 0; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/adapter/partone/viewholder/RecyclerHeaderViewHolder.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample.adapter.partone.viewholder; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | 6 | public class RecyclerHeaderViewHolder extends RecyclerView.ViewHolder { 7 | public RecyclerHeaderViewHolder(View itemView) { 8 | super(itemView); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/adapter/partone/viewholder/RecyclerItemViewHolder.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample.adapter.partone.viewholder; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | import pl.michalz.hideonscrollexample.R; 7 | 8 | public class RecyclerItemViewHolder extends RecyclerView.ViewHolder { 9 | 10 | private final TextView mItemTextView; 11 | 12 | public RecyclerItemViewHolder(final View parent, TextView itemTextView) { 13 | super(parent); 14 | mItemTextView = itemTextView; 15 | } 16 | 17 | public static RecyclerItemViewHolder newInstance(View parent) { 18 | TextView itemTextView = (TextView) parent.findViewById(R.id.itemTextView); 19 | return new RecyclerItemViewHolder(parent, itemTextView); 20 | } 21 | 22 | public void setItemText(CharSequence text) { 23 | mItemTextView.setText(text); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/adapter/parttwo/RecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample.adapter.parttwo; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import pl.michalz.hideonscrollexample.R; 9 | import pl.michalz.hideonscrollexample.adapter.parttwo.viewholder.RecyclerItemViewHolder; 10 | 11 | import java.util.List; 12 | 13 | public class RecyclerAdapter extends RecyclerView.Adapter { 14 | 15 | private List mItemList; 16 | 17 | public RecyclerAdapter(List itemList) { 18 | mItemList = itemList; 19 | } 20 | 21 | @Override 22 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 23 | Context context = parent.getContext(); 24 | View view = LayoutInflater.from(context).inflate(R.layout.recycler_item, parent, false); 25 | return RecyclerItemViewHolder.newInstance(view); 26 | } 27 | 28 | @Override 29 | public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { 30 | RecyclerItemViewHolder holder = (RecyclerItemViewHolder) viewHolder; 31 | String itemText = mItemList.get(position); 32 | holder.setItemText(itemText); 33 | } 34 | 35 | @Override 36 | public int getItemCount() { 37 | return mItemList == null ? 0 : mItemList.size(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/adapter/parttwo/viewholder/RecyclerItemViewHolder.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample.adapter.parttwo.viewholder; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | import pl.michalz.hideonscrollexample.R; 7 | 8 | public class RecyclerItemViewHolder extends RecyclerView.ViewHolder { 9 | 10 | private final TextView mItemTextView; 11 | 12 | public RecyclerItemViewHolder(final View parent, TextView itemTextView) { 13 | super(parent); 14 | mItemTextView = itemTextView; 15 | } 16 | 17 | public static RecyclerItemViewHolder newInstance(View parent) { 18 | TextView itemTextView = (TextView) parent.findViewById(R.id.itemTextView); 19 | return new RecyclerItemViewHolder(parent, itemTextView); 20 | } 21 | 22 | public void setItemText(CharSequence text) { 23 | mItemTextView.setText(text); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/fragment/PartThreeFragment.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import pl.michalz.hideonscrollexample.R; 12 | import pl.michalz.hideonscrollexample.adapter.parttwo.RecyclerAdapter; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | public class PartThreeFragment extends Fragment { 18 | 19 | public final static String ITEMS_COUNT_KEY = "PartThreeFragment$ItemsCount"; 20 | 21 | public static PartThreeFragment createInstance(int itemsCount) { 22 | PartThreeFragment partThreeFragment = new PartThreeFragment(); 23 | Bundle bundle = new Bundle(); 24 | bundle.putInt(ITEMS_COUNT_KEY, itemsCount); 25 | partThreeFragment.setArguments(bundle); 26 | return partThreeFragment; 27 | } 28 | 29 | @Nullable 30 | @Override 31 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 32 | RecyclerView recyclerView = (RecyclerView) inflater.inflate( 33 | R.layout.fragment_part_three, container, false); 34 | setupRecyclerView(recyclerView); 35 | return recyclerView; 36 | } 37 | 38 | private void setupRecyclerView(RecyclerView recyclerView) { 39 | recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); 40 | RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList()); 41 | recyclerView.setAdapter(recyclerAdapter); 42 | } 43 | 44 | private List createItemList() { 45 | List itemList = new ArrayList<>(); 46 | Bundle bundle = getArguments(); 47 | if(bundle!=null) { 48 | int itemsCount = bundle.getInt(ITEMS_COUNT_KEY); 49 | for (int i = 0; i < itemsCount; i++) { 50 | itemList.add("Item " + i); 51 | } 52 | } 53 | return itemList; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/listener/partone/HidingScrollListener.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample.listener.partone; 2 | 3 | import android.support.v7.widget.LinearLayoutManager; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | /* 7 | * This class is a ScrollListener for RecyclerView that allows to show/hide 8 | * views when list is scrolled. It assumes that you have added a header 9 | * to your list. @see pl.michalz.hideonscrollexample.adapter.partone.RecyclerAdapter 10 | * */ 11 | public abstract class HidingScrollListener extends RecyclerView.OnScrollListener { 12 | 13 | private static final int HIDE_THRESHOLD = 20; 14 | 15 | private int mScrolledDistance = 0; 16 | private boolean mControlsVisible = true; 17 | 18 | 19 | @Override 20 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 21 | super.onScrolled(recyclerView, dx, dy); 22 | 23 | int firstVisibleItem = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition(); 24 | 25 | if (firstVisibleItem == 0) { 26 | if(!mControlsVisible) { 27 | onShow(); 28 | mControlsVisible = true; 29 | } 30 | } else { 31 | if (mScrolledDistance > HIDE_THRESHOLD && mControlsVisible) { 32 | onHide(); 33 | mControlsVisible = false; 34 | mScrolledDistance = 0; 35 | } else if (mScrolledDistance < -HIDE_THRESHOLD && !mControlsVisible) { 36 | onShow(); 37 | mControlsVisible = true; 38 | mScrolledDistance = 0; 39 | } 40 | } 41 | if((mControlsVisible && dy>0) || (!mControlsVisible && dy<0)) { 42 | mScrolledDistance += dy; 43 | } 44 | } 45 | 46 | public abstract void onHide(); 47 | public abstract void onShow(); 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/pl/michalz/hideonscrollexample/listener/parttwo/HidingScrollListener.java: -------------------------------------------------------------------------------- 1 | package pl.michalz.hideonscrollexample.listener.parttwo; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import pl.michalz.hideonscrollexample.Utils; 6 | 7 | /* 8 | * This class is a ScrollListener for RecyclerView that allows to show/hide 9 | * views when list is scrolled. 10 | * */ 11 | public abstract class HidingScrollListener extends RecyclerView.OnScrollListener { 12 | 13 | private static final float HIDE_THRESHOLD = 10; 14 | private static final float SHOW_THRESHOLD = 70; 15 | 16 | private int mToolbarOffset = 0; 17 | private boolean mControlsVisible = true; 18 | private int mToolbarHeight; 19 | private int mTotalScrolledDistance; 20 | 21 | public HidingScrollListener(Context context) { 22 | mToolbarHeight = Utils.getToolbarHeight(context); 23 | } 24 | 25 | @Override 26 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 27 | super.onScrollStateChanged(recyclerView, newState); 28 | 29 | if(newState == RecyclerView.SCROLL_STATE_IDLE) { 30 | if(mTotalScrolledDistance < mToolbarHeight) { 31 | setVisible(); 32 | } else { 33 | if (mControlsVisible) { 34 | if (mToolbarOffset > HIDE_THRESHOLD) { 35 | setInvisible(); 36 | } else { 37 | setVisible(); 38 | } 39 | } else { 40 | if ((mToolbarHeight - mToolbarOffset) > SHOW_THRESHOLD) { 41 | setVisible(); 42 | } else { 43 | setInvisible(); 44 | } 45 | } 46 | } 47 | } 48 | 49 | } 50 | 51 | @Override 52 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 53 | super.onScrolled(recyclerView, dx, dy); 54 | 55 | clipToolbarOffset(); 56 | onMoved(mToolbarOffset); 57 | 58 | if((mToolbarOffset 0) || (mToolbarOffset >0 && dy<0)) { 59 | mToolbarOffset += dy; 60 | } 61 | if (mTotalScrolledDistance < 0) { 62 | mTotalScrolledDistance = 0; 63 | } else { 64 | mTotalScrolledDistance += dy; 65 | } 66 | } 67 | 68 | private void clipToolbarOffset() { 69 | if(mToolbarOffset > mToolbarHeight) { 70 | mToolbarOffset = mToolbarHeight; 71 | } else if(mToolbarOffset < 0) { 72 | mToolbarOffset = 0; 73 | } 74 | } 75 | 76 | private void setVisible() { 77 | if(mToolbarOffset > 0) { 78 | onShow(); 79 | mToolbarOffset = 0; 80 | } 81 | mControlsVisible = true; 82 | } 83 | 84 | private void setInvisible() { 85 | if(mToolbarOffset < mToolbarHeight) { 86 | onHide(); 87 | mToolbarOffset = mToolbarHeight; 88 | } 89 | mControlsVisible = false; 90 | } 91 | 92 | public abstract void onMoved(int distance); 93 | public abstract void onShow(); 94 | public abstract void onHide(); 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_favorite_outline_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzgreen/HideOnScrollExample/5f932818c775464589681dc53fa8d719af2426fb/app/src/main/res/drawable-hdpi/ic_favorite_outline_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_favorite_outline_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzgreen/HideOnScrollExample/5f932818c775464589681dc53fa8d719af2426fb/app/src/main/res/drawable-mdpi/ic_favorite_outline_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_favorite_outline_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzgreen/HideOnScrollExample/5f932818c775464589681dc53fa8d719af2426fb/app/src/main/res/drawable-xhdpi/ic_favorite_outline_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_favorite_outline_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzgreen/HideOnScrollExample/5f932818c775464589681dc53fa8d719af2426fb/app/src/main/res/drawable-xxhdpi/ic_favorite_outline_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/fab_bcg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 |