{"id":15025381,"url":"https://github.com/everythingme/overscroll-decor","last_synced_at":"2025-05-14T13:08:08.404Z","repository":{"id":40669211,"uuid":"46658160","full_name":"EverythingMe/overscroll-decor","owner":"EverythingMe","description":"Android: iOS-like over-scrolling effect applicable over almost all scrollable Android views.","archived":false,"fork":false,"pushed_at":"2021-04-22T14:49:22.000Z","size":3380,"stargazers_count":2882,"open_issues_count":45,"forks_count":401,"subscribers_count":75,"default_branch":"master","last_synced_at":"2025-04-20T20:35:52.939Z","etag":null,"topics":["android","fling","gridview","ios","listview","overscroll","recyclerview","scrollview","viewpager"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EverythingMe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-11-22T11:44:06.000Z","updated_at":"2025-04-14T12:38:46.000Z","dependencies_parsed_at":"2022-07-08T02:16:36.070Z","dependency_job_id":null,"html_url":"https://github.com/EverythingMe/overscroll-decor","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EverythingMe%2Foverscroll-decor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EverythingMe%2Foverscroll-decor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EverythingMe%2Foverscroll-decor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EverythingMe%2Foverscroll-decor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EverythingMe","download_url":"https://codeload.github.com/EverythingMe/overscroll-decor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254149960,"owners_count":22022851,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","fling","gridview","ios","listview","overscroll","recyclerview","scrollview","viewpager"],"created_at":"2024-09-24T20:02:14.291Z","updated_at":"2025-05-14T13:08:03.393Z","avatar_url":"https://github.com/EverythingMe.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003e **Announcement**\n\u003e\n\u003e An update regarding Bintray's shutdown: The library has been successfuly republished onto maven central, but with a different Group ID; Please update your Gradle dependencies as follows:\n\u003e\n\u003e ```diff\n\u003e -implementation 'me.everything:overscroll-decor-android:1.1.0'\n\u003e +implementation 'io.github.everythingme:overscroll-decor-android:1.1.1'\n\u003e ```\n\n# Over-Scroll Support For Android's RecyclerView, ListView, GridView, ScrollView ...\n\nThe library provides an iOS-like over-scrolling effect applicable over almost all Android native scrollable views. It is also built to allow for very easy adaptation to support custom views.\n\nThe core effect classes are loose-[decorators](https://en.wikipedia.org/wiki/Decorator_pattern) of Android views, and are thus decoupled from the actual view classes' implementations. That allows developers to apply the effect over views while keeping them as untampered 'black-boxes'. Namely, it allows for keeping important optimizations such as view-recycling intact.\n\n![RecyclerView demo](recyclerview_demo.gif)\n\n# Gradle Dependency\n\nAdd the following to your module's `build.gradle` file:\n\n```groovy\ndependencies {\n    // ...\n    \n    implementation 'io.github.everythingme:overscroll-decor-android:1.1.1'\n}\n```\n\n# Usage\n\n### RecyclerView\n\nSupports both linear and staggered-grid layout managers (i.e. all native Android layouts).\nCan be easily adapted to support custom layout managers.\n\n```java\nRecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);\n    \n// Horizontal\nOverScrollDecoratorHelper.setUpOverScroll(recyclerView, OverScrollDecoratorHelper.ORIENTATION_HORIZONTAL);\n// Vertical\nOverScrollDecoratorHelper.setUpOverScroll(recyclerView, OverScrollDecoratorHelper.ORIENTATION_VERTICAL);\n```\n\n### RecyclerView with items swiping / dragging\nSee _Advanced Usage_.\n\n\n### ListView\n\n```java\nListView listView = (ListView) findViewById(R.id.list_view);\nOverScrollDecoratorHelper.setUpOverScroll(listView);\n```\n\n### GridView\n\n```java\nGridView gridView = (GridView) findViewById(R.id.grid_view);\nOverScrollDecoratorHelper.setUpOverScroll(gridView);\n```\n\n### ViewPager\n\n```java\nViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);\nOverScrollDecoratorHelper.setUpOverScroll(viewPager);\n```\n\n### ScrollView, HorizontalScrollView\n\n```java\nScrollView scrollView = (ScrollView) findViewById(R.id.scroll_view);\nOverScrollDecoratorHelper.setUpOverScroll(scrollView);\n    \nHorizontalScrollView horizontalScrollView = (HorizontalScrollView) findViewById(R.id.horizontal_scroll_view);\nOverScrollDecoratorHelper.setUpOverScroll(horizontalScrollView);\n```\n\n### Any View - Text, Image... (Always Over-Scroll Ready)\n\n```java\nView view = findViewById(R.id.demo_view);\n    \n// Horizontal\nOverScrollDecoratorHelper.setUpStaticOverScroll(view, OverScrollDecoratorHelper.ORIENTATION_HORIZONTAL);\n// Vertical\nOverScrollDecoratorHelper.setUpStaticOverScroll(view, OverScrollDecoratorHelper.ORIENTATION_VERTICAL);\n```\n\n# Advanced Usage\n\n```java\n// Horizontal RecyclerView\nRecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);\nnew HorizontalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView));\n\n// ListView (vertical)\nListView listView = (ListView) findViewById(R.id.list_view);\nnew VerticalOverScrollBounceEffectDecorator(new AbsListViewOverScrollDecorAdapter(listView));\n\n// GridView (vertical)\nGridView gridView = (GridView) findViewById(R.id.grid_view);\nnew VerticalOverScrollBounceEffectDecorator(new AbsListViewOverScrollDecorAdapter(gridView));\n\n// ViewPager\nViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);\nnew HorizontalOverScrollBounceEffectDecorator(new ViewPagerOverScrollDecorAdapter(viewPager));\n\n// A simple TextView - horizontal\nView textView = findViewById(R.id.title);\nnew HorizontalOverScrollBounceEffectDecorator(new StaticOverScrollDecorAdapter(view));\n```\n\n### RecyclerView with [ItemTouchHelper](http://developer.android.com/reference/android/support/v7/widget/helper/ItemTouchHelper.html) based swiping / dragging\nAs of version 1.0.1, the effect can work smoothly with the RecyclerView's built-in mechanism for items swiping and dragging (based on [ItemTouchHelper](http://developer.android.com/reference/android/support/v7/widget/helper/ItemTouchHelper.html)). BUT, it requires some (very little) explicit configuration work:\n\n```java\n// Normally you would attach an ItemTouchHelper \u0026 a callback to a RecyclerView, this way:\nRecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);\nItemTouchHelper.Callback myCallback = new ItemTouchHelper.Callback() {\n\t...\n};\nItemTouchHelper myHelper = new ItemTouchHelper(myCallback);\nmyHelper.attachToRecyclerView(recyclerView);\n\n// INSTEAD of attaching the helper yourself, simply use the dedicated adapter c'tor, e.g.:\nnew VerticalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView, myCallback));\n\n```\n\nFor more info on the swiping / dragging mechanism, try [this useful tutorial](https://medium.com/@ipaulpro/drag-and-swipe-with-recyclerview-b9456d2b1aaf).\n\n### Over-Scroll Listeners\nAs of version 1.0.2, the effect provides a means for registering listeners of over-scroll related events. There are two types of listeners, as follows.\n\n#### State-Change Listener\nThe over-scroll manager dispatches events onto a state-change listener denoting transitions in the effect's state:\n\n```java\n\n// Note: over-scroll is set-up using the helper method.\nIOverScrollDecor decor = OverScrollDecoratorHelper.setUpOverScroll(recyclerView, OverScrollDecoratorHelper.ORIENTATION_HORIZONTAL);\n\ndecor.setOverScrollStateListener(new IOverScrollStateListener() {\n    @Override\n\tpublic void onOverScrollStateChange(IOverScrollDecor decor, int oldState, int newState) {\n\t    switch (newState) {\n\t        case STATE_IDLE:\n\t            // No over-scroll is in effect.\n\t            break;\n\t        case STATE_DRAG_START_SIDE:\n\t            // Dragging started at the left-end.\n\t            break;\n\t        case STATE_DRAG_END_SIDE:\n\t            // Dragging started at the right-end.\n\t            break;\n\t        case STATE_BOUNCE_BACK:\n\t            if (oldState == STATE_DRAG_START_SIDE) {\n\t                // Dragging stopped -- view is starting to bounce back from the *left-end* onto natural position.\n\t            } else { // i.e. (oldState == STATE_DRAG_END_SIDE)\n\t                // View is starting to bounce back from the *right-end*.\n\t            }\n\t            break;\n\t    }\n\t}\n}\n```\n\n#### Real-time Updates Listener\nThe over-scroll manager can also dispatch *real-time*, as-it-happens over-scroll events denoting the current offset resulting due to an over-scroll being in-effect (the offset thus denotes the current 'intensity').\n\n```java\n// Note: over-scroll is set-up by explicity instantiating a decorator rather than using the helper; The two methods can be used interchangeably for registering listeners.\nVerticalOverScrollBounceEffectDecorator decor = new VerticalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView, itemTouchHelperCallback));\n\ndecor.setOverScrollUpdateListener(new IOverScrollUpdateListener() {\n    @Override\n    public void onOverScrollUpdate(IOverScrollDecor decor, int state, float offset) {\n    \tfinal View view = decor.getView();\n    \tif (offset \u003e 0) {\n    \t\t// 'view' is currently being over-scrolled from the top.\n    \t} else if (offset \u003c 0) {\n    \t\t// 'view' is currently being over-scrolled from the bottom.\n    \t} else {\n    \t\t// No over-scroll is in-effect.\n    \t\t// This is synonymous with having (state == STATE_IDLE).\n    \t}\n    }\n});\n\n```\n\n\nThe two type of listeners can be used either separately or in conjunction, depending on your needs. Refer to the demo project's RecyclerView-demo section for actual concrete usage.\n    \n### Custom Views\n\n```java\npublic class CustomView extends View {\n    // ...\n}\n    \nfinal CustomView view = (CustomView) findViewById(R.id.custom_view);\nnew VerticalOverScrollBounceEffectDecorator(new IOverScrollDecoratorAdapter() {\n\n    @Override\n    public View getView() {\n        return view;\n    }\n\n    @Override\n    public boolean isInAbsoluteStart() {\n\t    // canScrollUp() is an example of a method you must implement\n        return !view.canScrollUp();\n    }\n\n    @Override\n    public boolean isInAbsoluteEnd() {\n\t     // canScrollDown() is an example of a method you must implement\n        return !view.canScrollDown();\n    }\n});\n```\n\n### Effect Behavior Configuration\n\n```java\n/// Make over-scroll applied over a list-view feel more 'stiff'\nnew VerticalOverScrollBounceEffectDecorator(new AbsListViewOverScrollDecorAdapter(view),\n        5f, // Default is 3\n        VerticalOverScrollBounceEffectDecorator.DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK,\n        VerticalOverScrollBounceEffectDecorator.DEFAULT_DECELERATE_FACTOR);\n                \n// Make over-scroll applied over a list-view bounce-back more softly\nnew VerticalOverScrollBounceEffectDecorator(new AbsListViewOverScrollDecorAdapter(view),\n        VerticalOverScrollBounceEffectDecorator.DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD,\n        VerticalOverScrollBounceEffectDecorator.DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK,\n        -1f // Default is -2\n        );\n```\n\n### Dynamic Effect Disabling\n\nAs of version 1.0.4, the effect can be dynamically disabled (detached) and reenabled (attached) at runtime:\n\n```java\nIOverScrollDecor decor = OverScrollDecoratorHelper.setUpOverScroll(view);\n\n// Detach. You are strongly encouraged to only call this when overscroll isn't\n// in-effect: Either add getCurrentState()==STATE_IDLE as a precondition,\n// or use a state-change listener.\ndecor.detach();\n// Attach.\ndecor.attach();\n```\n\n`attach()` and `detach()` can be used repeatedly - as necessary, as can be seen in the demo project (refer to action-bar menu in recycler-view demo).\n\n## Credits\n\nApp icons by \u003ca href=\"http://somerandomdude.com/work/iconic/\"\u003eP.J. Onori\u003c/a\u003e,\n\u003ca href=\"http://graphicriver.net/item/wirecons-vector-icons/4586710?ref=tmthymllr\"\u003eTimothy Miller\u003c/a\u003e,\n\u003ca href=\"http://icons4android.com\"\u003eIcons4Android\u003c/a\u003e, \n\u003ca href=\"http://icons8.com/android-icons\"\u003eIcons8.com\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feverythingme%2Foverscroll-decor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feverythingme%2Foverscroll-decor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feverythingme%2Foverscroll-decor/lists"}