add flutter

This commit is contained in:
Ariska
2026-03-11 15:29:37 +07:00
parent c253e1a370
commit 619d758027
9490 changed files with 135801 additions and 1353 deletions
+9
View File
@@ -0,0 +1,9 @@
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
/.idea
*iml
+23
View File
@@ -0,0 +1,23 @@
Copyright (c) 2015, DoAT Media Ltd.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+266
View File
@@ -0,0 +1,266 @@
> **Announcement**
>
> 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:
>
> ```diff
> -implementation 'me.everything:overscroll-decor-android:1.1.0'
> +implementation 'io.github.everythingme:overscroll-decor-android:1.1.1'
> ```
# Over-Scroll Support For Android's RecyclerView, ListView, GridView, ScrollView ...
The 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.
The 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.
![RecyclerView demo](recyclerview_demo.gif)
# Gradle Dependency
Add the following to your module's `build.gradle` file:
```groovy
dependencies {
// ...
implementation 'io.github.everythingme:overscroll-decor-android:1.1.1'
}
```
# Usage
### RecyclerView
Supports both linear and staggered-grid layout managers (i.e. all native Android layouts).
Can be easily adapted to support custom layout managers.
```java
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
// Horizontal
OverScrollDecoratorHelper.setUpOverScroll(recyclerView, OverScrollDecoratorHelper.ORIENTATION_HORIZONTAL);
// Vertical
OverScrollDecoratorHelper.setUpOverScroll(recyclerView, OverScrollDecoratorHelper.ORIENTATION_VERTICAL);
```
### RecyclerView with items swiping / dragging
See _Advanced Usage_.
### ListView
```java
ListView listView = (ListView) findViewById(R.id.list_view);
OverScrollDecoratorHelper.setUpOverScroll(listView);
```
### GridView
```java
GridView gridView = (GridView) findViewById(R.id.grid_view);
OverScrollDecoratorHelper.setUpOverScroll(gridView);
```
### ViewPager
```java
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
OverScrollDecoratorHelper.setUpOverScroll(viewPager);
```
### ScrollView, HorizontalScrollView
```java
ScrollView scrollView = (ScrollView) findViewById(R.id.scroll_view);
OverScrollDecoratorHelper.setUpOverScroll(scrollView);
HorizontalScrollView horizontalScrollView = (HorizontalScrollView) findViewById(R.id.horizontal_scroll_view);
OverScrollDecoratorHelper.setUpOverScroll(horizontalScrollView);
```
### Any View - Text, Image... (Always Over-Scroll Ready)
```java
View view = findViewById(R.id.demo_view);
// Horizontal
OverScrollDecoratorHelper.setUpStaticOverScroll(view, OverScrollDecoratorHelper.ORIENTATION_HORIZONTAL);
// Vertical
OverScrollDecoratorHelper.setUpStaticOverScroll(view, OverScrollDecoratorHelper.ORIENTATION_VERTICAL);
```
# Advanced Usage
```java
// Horizontal RecyclerView
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
new HorizontalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView));
// ListView (vertical)
ListView listView = (ListView) findViewById(R.id.list_view);
new VerticalOverScrollBounceEffectDecorator(new AbsListViewOverScrollDecorAdapter(listView));
// GridView (vertical)
GridView gridView = (GridView) findViewById(R.id.grid_view);
new VerticalOverScrollBounceEffectDecorator(new AbsListViewOverScrollDecorAdapter(gridView));
// ViewPager
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
new HorizontalOverScrollBounceEffectDecorator(new ViewPagerOverScrollDecorAdapter(viewPager));
// A simple TextView - horizontal
View textView = findViewById(R.id.title);
new HorizontalOverScrollBounceEffectDecorator(new StaticOverScrollDecorAdapter(view));
```
### RecyclerView with [ItemTouchHelper](http://developer.android.com/reference/android/support/v7/widget/helper/ItemTouchHelper.html) based swiping / dragging
As 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:
```java
// Normally you would attach an ItemTouchHelper & a callback to a RecyclerView, this way:
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
ItemTouchHelper.Callback myCallback = new ItemTouchHelper.Callback() {
...
};
ItemTouchHelper myHelper = new ItemTouchHelper(myCallback);
myHelper.attachToRecyclerView(recyclerView);
// INSTEAD of attaching the helper yourself, simply use the dedicated adapter c'tor, e.g.:
new VerticalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView, myCallback));
```
For more info on the swiping / dragging mechanism, try [this useful tutorial](https://medium.com/@ipaulpro/drag-and-swipe-with-recyclerview-b9456d2b1aaf).
### Over-Scroll Listeners
As 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.
#### State-Change Listener
The over-scroll manager dispatches events onto a state-change listener denoting transitions in the effect's state:
```java
// Note: over-scroll is set-up using the helper method.
IOverScrollDecor decor = OverScrollDecoratorHelper.setUpOverScroll(recyclerView, OverScrollDecoratorHelper.ORIENTATION_HORIZONTAL);
decor.setOverScrollStateListener(new IOverScrollStateListener() {
@Override
public void onOverScrollStateChange(IOverScrollDecor decor, int oldState, int newState) {
switch (newState) {
case STATE_IDLE:
// No over-scroll is in effect.
break;
case STATE_DRAG_START_SIDE:
// Dragging started at the left-end.
break;
case STATE_DRAG_END_SIDE:
// Dragging started at the right-end.
break;
case STATE_BOUNCE_BACK:
if (oldState == STATE_DRAG_START_SIDE) {
// Dragging stopped -- view is starting to bounce back from the *left-end* onto natural position.
} else { // i.e. (oldState == STATE_DRAG_END_SIDE)
// View is starting to bounce back from the *right-end*.
}
break;
}
}
}
```
#### Real-time Updates Listener
The 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').
```java
// 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.
VerticalOverScrollBounceEffectDecorator decor = new VerticalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView, itemTouchHelperCallback));
decor.setOverScrollUpdateListener(new IOverScrollUpdateListener() {
@Override
public void onOverScrollUpdate(IOverScrollDecor decor, int state, float offset) {
final View view = decor.getView();
if (offset > 0) {
// 'view' is currently being over-scrolled from the top.
} else if (offset < 0) {
// 'view' is currently being over-scrolled from the bottom.
} else {
// No over-scroll is in-effect.
// This is synonymous with having (state == STATE_IDLE).
}
}
});
```
The 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.
### Custom Views
```java
public class CustomView extends View {
// ...
}
final CustomView view = (CustomView) findViewById(R.id.custom_view);
new VerticalOverScrollBounceEffectDecorator(new IOverScrollDecoratorAdapter() {
@Override
public View getView() {
return view;
}
@Override
public boolean isInAbsoluteStart() {
// canScrollUp() is an example of a method you must implement
return !view.canScrollUp();
}
@Override
public boolean isInAbsoluteEnd() {
// canScrollDown() is an example of a method you must implement
return !view.canScrollDown();
}
});
```
### Effect Behavior Configuration
```java
/// Make over-scroll applied over a list-view feel more 'stiff'
new VerticalOverScrollBounceEffectDecorator(new AbsListViewOverScrollDecorAdapter(view),
5f, // Default is 3
VerticalOverScrollBounceEffectDecorator.DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK,
VerticalOverScrollBounceEffectDecorator.DEFAULT_DECELERATE_FACTOR);
// Make over-scroll applied over a list-view bounce-back more softly
new VerticalOverScrollBounceEffectDecorator(new AbsListViewOverScrollDecorAdapter(view),
VerticalOverScrollBounceEffectDecorator.DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD,
VerticalOverScrollBounceEffectDecorator.DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK,
-1f // Default is -2
);
```
### Dynamic Effect Disabling
As of version 1.0.4, the effect can be dynamically disabled (detached) and reenabled (attached) at runtime:
```java
IOverScrollDecor decor = OverScrollDecoratorHelper.setUpOverScroll(view);
// Detach. You are strongly encouraged to only call this when overscroll isn't
// in-effect: Either add getCurrentState()==STATE_IDLE as a precondition,
// or use a state-change listener.
decor.detach();
// Attach.
decor.attach();
```
`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).
## Credits
App icons by <a href="http://somerandomdude.com/work/iconic/">P.J. Onori</a>,
<a href="http://graphicriver.net/item/wirecons-vector-icons/4586710?ref=tmthymllr">Timothy Miller</a>,
<a href="http://icons4android.com">Icons4Android</a>,
<a href="http://icons8.com/android-icons">Icons8.com</a>
+1
View File
@@ -0,0 +1 @@
/build
+27
View File
@@ -0,0 +1,27 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
buildToolsVersion '29.0.3'
defaultConfig {
applicationId 'me.everything.overscrolldemo'
minSdkVersion 14
targetSdkVersion 30
versionCode 1
versionName '1.0'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation project(':liboverscroll')
// implementation 'io.github.everythingme:overscroll-decor-android:1.1.1'
}
+17
View File
@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/amit/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="me.everything.overscrolldemo" >
<application
android:allowBackup="true"
android:icon="@drawable/app_icon"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity
android:name=".OverScrollDemoActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,105 @@
package me.everything.overscrolldemo;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import com.google.android.material.navigation.NavigationView;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.MenuItem;
import me.everything.overscrolldemo.view.GridViewDemoFragment;
import me.everything.overscrolldemo.view.ListViewDemoFragment;
import me.everything.overscrolldemo.view.MiscViewsDemoFragment;
import me.everything.overscrolldemo.view.NestedScrollViewDemoFragment;
import me.everything.overscrolldemo.view.RecyclerViewDemoFragment;
import me.everything.overscrolldemo.view.RecyclerViewStaggeredGridDemoFragment;
import me.everything.overscrolldemo.view.ScrollViewDemoFragment;
import me.everything.overscrolldemo.view.ViewPagerDemoFragment;
public class OverScrollDemoActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_overscroll_demo);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle(R.string.recycler_view_demo_title);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.drawer_nav);
navigationView.setNavigationItemSelectedListener(this);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_placeholder, new RecyclerViewDemoFragment())
.commit();
}
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onNavigationItemSelected(MenuItem item) {
final int id = item.getItemId();
item.setChecked(true);
switch (id) {
case R.id.drawer_item_recyclerview_demo:
replaceMainFragment(new RecyclerViewDemoFragment(), R.string.recycler_view_demo_title);
break;
case R.id.drawer_item_gridview_demo:
replaceMainFragment(new GridViewDemoFragment(), R.string.grid_view_demo_title);
break;
case R.id.drawer_item_listview_demo:
replaceMainFragment(new ListViewDemoFragment(), R.string.list_view_demo_title);
break;
case R.id.drawer_item_recyclerview_staggered_grid_demo:
replaceMainFragment(new RecyclerViewStaggeredGridDemoFragment(), R.string.recycler_view_staggered_grid_demo_title);
break;
case R.id.drawer_item_scrollview_demo:
replaceMainFragment(new ScrollViewDemoFragment(), R.string.scroll_view_demo_title);
break;
case R.id.drawer_item_viewpager_demo:
replaceMainFragment(new ViewPagerDemoFragment(),R.string.viewpager_demo_title);
break;
case R.id.drawer_item_nested_scrollview_demo:
replaceMainFragment(new NestedScrollViewDemoFragment(), R.string.nested_scrollview_demo_title);
break;
case R.id.drawer_item_misc_demo:
replaceMainFragment(new MiscViewsDemoFragment(), R.string.misc_views_demo_title);
break;
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
private void replaceMainFragment(Fragment fragment, int titleResId) {
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(R.animator.fade_in_slow, R.animator.fade_out_quick)
.replace(R.id.fragment_placeholder, fragment)
.commit();
getSupportActionBar().setTitle(titleResId);
}
}
@@ -0,0 +1,52 @@
package me.everything.overscrolldemo.control;
import android.content.res.Resources;
import java.util.Arrays;
import java.util.List;
import me.everything.overscrolldemo.R;
public class DemoContentHelper {
private static List<DemoItem> sSpectrumItemsVioletToRed;
private static List<DemoItem> sSpectrumItemsRedToViolet;
public static List<DemoItem> getSpectrumItems(Resources res) {
if (sSpectrumItemsVioletToRed == null) {
sSpectrumItemsVioletToRed = Arrays.asList(
new DemoItem(res.getColor(android.R.color.holo_purple), "PURPLE"),
new DemoItem(res.getColor(android.R.color.holo_blue_dark), "BLUE"),
new DemoItem(res.getColor(android.R.color.holo_blue_light), "LIGHT BLUE"),
new DemoItem(res.getColor(R.color.spectrum_cyan), "CYAN"),
new DemoItem(res.getColor(android.R.color.holo_green_dark), "GREEN"),
new DemoItem(res.getColor(android.R.color.holo_green_light), "LIGHT GREEN"),
new DemoItem(res.getColor(R.color.spectrum_yellow), "YELLOW"),
new DemoItem(res.getColor(android.R.color.holo_orange_light), "LIGHT ORANGE"),
new DemoItem(res.getColor(android.R.color.holo_orange_dark), "ORANGE"),
new DemoItem(res.getColor(android.R.color.holo_red_light), "LIGHT RED"),
new DemoItem(res.getColor(android.R.color.holo_red_dark), "RED")
);
}
return sSpectrumItemsVioletToRed;
}
public static List<DemoItem> getReverseSpectrumItems(Resources res) {
if (sSpectrumItemsRedToViolet == null) {
sSpectrumItemsRedToViolet = Arrays.asList(
new DemoItem(res.getColor(android.R.color.holo_red_dark), "RED"),
new DemoItem(res.getColor(android.R.color.holo_red_light), "LIGHT RED"),
new DemoItem(res.getColor(android.R.color.holo_orange_dark), "ORANGE"),
new DemoItem(res.getColor(android.R.color.holo_orange_light), "LIGHT ORANGE"),
new DemoItem(res.getColor(R.color.spectrum_yellow), "YELLOW"),
new DemoItem(res.getColor(android.R.color.holo_green_light), "LIGHT GREEN"),
new DemoItem(res.getColor(android.R.color.holo_green_dark), "GREEN"),
new DemoItem(res.getColor(R.color.spectrum_cyan), "CYAN"),
new DemoItem(res.getColor(android.R.color.holo_blue_light), "LIGHT BLUE"),
new DemoItem(res.getColor(android.R.color.holo_blue_dark), "BLUE"),
new DemoItem(res.getColor(android.R.color.holo_purple), "PURPLE")
);
}
return sSpectrumItemsRedToViolet;
}
}
@@ -0,0 +1,32 @@
package me.everything.overscrolldemo.control;
public class DemoItem {
private int mColor;
private String mColorName;
public DemoItem() {
}
public DemoItem(int color, String colorName) {
mColorName = colorName;
mColor = color;
}
public int getColor() {
return mColor;
}
public void setColor(int color) {
mColor = color;
}
public String getColorName() {
return mColorName;
}
public void setColorName(String colorName) {
mColorName = colorName;
}
}
@@ -0,0 +1,25 @@
package me.everything.overscrolldemo.view;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import java.util.List;
import me.everything.overscrolldemo.R;
import me.everything.overscrolldemo.control.DemoItem;
public class DemoGridAdapter extends DemoListAdapterBase {
protected DemoGridAdapter(LayoutInflater inflater) {
super(inflater);
}
public DemoGridAdapter(LayoutInflater inflater, List<DemoItem> items) {
super(inflater, items);
}
@Override
protected DemoViewHolder createViewHolder(ViewGroup parent) {
return new DemoViewHolder(R.layout.grid_item, parent, mInflater);
}
}
@@ -0,0 +1,25 @@
package me.everything.overscrolldemo.view;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import java.util.List;
import me.everything.overscrolldemo.R;
import me.everything.overscrolldemo.control.DemoItem;
public class DemoListAdapter extends DemoListAdapterBase {
protected DemoListAdapter(LayoutInflater inflater) {
super(inflater);
}
public DemoListAdapter(LayoutInflater inflater, List<DemoItem> items) {
super(inflater, items);
}
@Override
protected DemoViewHolder createViewHolder(ViewGroup parent) {
return new DemoViewHolder(R.layout.vertical_list_item, parent, mInflater);
}
}
@@ -0,0 +1,104 @@
package me.everything.overscrolldemo.view;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import me.everything.overscrolldemo.control.DemoItem;
public abstract class DemoListAdapterBase extends BaseAdapter {
private static final int COLOR_VIEW_TYPE = 0;
public static class DemoViewHolder {
TextView mTextView;
public DemoViewHolder(int resId, ViewGroup parent, LayoutInflater inflater) {
mTextView = (TextView) inflater.inflate(resId, parent, false);
mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mTextView.getContext(), "Tapped on: "+mTextView.getText(), Toast.LENGTH_SHORT).show();
}
});
mTextView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Toast.makeText(mTextView.getContext(), "Long-tapped on: "+mTextView.getText(), Toast.LENGTH_SHORT).show();
return false;
}
});
}
public void init(DemoItem item) {
mTextView.setText(item.getColorName());
int color = item.getColor();
mTextView.setBackgroundColor(color);
}
public View getView() {
return mTextView;
}
}
protected final LayoutInflater mInflater;
protected List<DemoItem> mItems;
protected DemoListAdapterBase(LayoutInflater inflater) {
mInflater = inflater;
}
public DemoListAdapterBase(LayoutInflater inflater, List<DemoItem> items) {
mInflater = inflater;
mItems = items;
}
public void setItems(List items) {
mItems = items;
}
@Override
public int getCount() {
return mItems.size();
}
@Override
public Object getItem(int position) {
return mItems.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
DemoViewHolder holder;
if (convertView == null) {
holder = createViewHolder(parent);
holder.getView().setTag(holder);
} else {
holder = (DemoViewHolder) convertView.getTag();
}
holder.init((DemoItem) getItem(position));
return holder.getView();
}
protected abstract DemoViewHolder createViewHolder(ViewGroup parent);
@Override
public int getItemViewType(int position) {
return COLOR_VIEW_TYPE;
}
}
@@ -0,0 +1,85 @@
package me.everything.overscrolldemo.view;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import me.everything.overscrolldemo.control.DemoItem;
public abstract class DemoRecyclerAdapterBase extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int COLOR_VIEW_TYPE = 0;
public static class DemoViewHolder extends RecyclerView.ViewHolder {
public DemoViewHolder(int resId, ViewGroup parent, LayoutInflater inflater) {
super(inflater.inflate(resId, parent, false));
getTextView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getTextView().getContext(), "Tapped on: "+getTextView().getText(), Toast.LENGTH_SHORT).show();
}
});
getTextView().setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Toast.makeText(getTextView().getContext(), "Long-tapped on: "+getTextView().getText(), Toast.LENGTH_SHORT).show();
return false;
}
});
}
public void init(DemoItem item) {
TextView textView = getTextView();
textView.setText(item.getColorName());
int color = item.getColor();
textView.setBackgroundColor(color);
}
private TextView getTextView() {
return (TextView) itemView;
}
}
protected final LayoutInflater mInflater;
protected List<DemoItem> mItems;
protected DemoRecyclerAdapterBase(LayoutInflater inflater) {
mInflater = inflater;
}
public DemoRecyclerAdapterBase(LayoutInflater inflater, List<DemoItem> items) {
mInflater = inflater;
mItems = items;
}
public void setItems(List items) {
mItems = items;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
DemoItem item = mItems.get(position);
DemoViewHolder demoHolder = (DemoViewHolder) holder;
demoHolder.init(item);
}
@Override
public int getItemViewType(int position) {
return COLOR_VIEW_TYPE;
}
@Override
public int getItemCount() {
return mItems.size();
}
}
@@ -0,0 +1,28 @@
package me.everything.overscrolldemo.view;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import java.util.List;
import me.everything.overscrolldemo.R;
public class DemoRecyclerAdapterHorizontal extends DemoRecyclerAdapterBase {
public DemoRecyclerAdapterHorizontal(LayoutInflater inflater) {
super(inflater);
}
public DemoRecyclerAdapterHorizontal(List items, LayoutInflater inflater) {
super(inflater, items);
}
@Override
@NonNull
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new DemoViewHolder(R.layout.horizontal_list_item, parent, mInflater);
}
}
@@ -0,0 +1,27 @@
package me.everything.overscrolldemo.view;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import java.util.List;
import me.everything.overscrolldemo.R;
public class DemoRecyclerAdapterVertical extends DemoRecyclerAdapterBase {
public DemoRecyclerAdapterVertical(LayoutInflater inflater) {
super(inflater);
}
public DemoRecyclerAdapterVertical(List items, LayoutInflater inflater) {
super(inflater, items);
}
@Override
@NonNull
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new DemoViewHolder(R.layout.vertical_list_item, parent, mInflater);
}
}
@@ -0,0 +1,34 @@
package me.everything.overscrolldemo.view;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import android.widget.ListAdapter;
import java.util.List;
import me.everything.android.ui.overscroll.OverScrollDecoratorHelper;
import me.everything.overscrolldemo.R;
import me.everything.overscrolldemo.control.DemoContentHelper;
import me.everything.overscrolldemo.control.DemoItem;
public class GridViewDemoFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.gridview_overscroll_demo, null, false);
initVerticalGridView(DemoContentHelper.getSpectrumItems(getResources()), (GridView) fragmentView.findViewById(R.id.grid_view));
return fragmentView;
}
private void initVerticalGridView(List<DemoItem> content, GridView gridView) {
LayoutInflater appInflater = LayoutInflater.from(getActivity().getApplicationContext());
ListAdapter adapter = new DemoGridAdapter(appInflater, content);
gridView.setAdapter(adapter);
OverScrollDecoratorHelper.setUpOverScroll(gridView);
}
}
@@ -0,0 +1,36 @@
package me.everything.overscrolldemo.view;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import androidx.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.ListView;
import java.util.List;
import me.everything.android.ui.overscroll.OverScrollDecoratorHelper;
import me.everything.overscrolldemo.R;
import me.everything.overscrolldemo.control.DemoContentHelper;
import me.everything.overscrolldemo.control.DemoItem;
public class ListViewDemoFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.listview_overscroll_demo, null, false);
initVerticalListView(DemoContentHelper.getSpectrumItems(getResources()), (ListView) fragmentView.findViewById(R.id.list_view));
return fragmentView;
}
private void initVerticalListView(List<DemoItem> content, ListView listView) {
LayoutInflater appInflater = LayoutInflater.from(getActivity().getApplicationContext());
ListAdapter adapter = new DemoListAdapter(appInflater, content);
listView.setAdapter(adapter);
OverScrollDecoratorHelper.setUpOverScroll(listView);
}
}
@@ -0,0 +1,45 @@
package me.everything.overscrolldemo.view;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Chronometer;
import me.everything.android.ui.overscroll.OverScrollDecoratorHelper;
import me.everything.overscrolldemo.R;
public class MiscViewsDemoFragment extends Fragment {
private static final String CHRONO_TIME_SAVE_ID = "chronoTime";
private Chronometer mChrono;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.misc_overscroll_demo, null, false);
View textView = fragmentView.findViewById(R.id.demo_text);
OverScrollDecoratorHelper.setUpStaticOverScroll(textView, OverScrollDecoratorHelper.ORIENTATION_HORIZONTAL);
View imageView = fragmentView.findViewById(R.id.demo_image);
OverScrollDecoratorHelper.setUpStaticOverScroll(imageView, OverScrollDecoratorHelper.ORIENTATION_VERTICAL);
mChrono = (Chronometer) fragmentView.findViewById(R.id.demo_chronometer);
if (savedInstanceState != null) {
mChrono.setBase(savedInstanceState.getLong(CHRONO_TIME_SAVE_ID));
}
OverScrollDecoratorHelper.setUpStaticOverScroll(mChrono, OverScrollDecoratorHelper.ORIENTATION_HORIZONTAL);
mChrono.start();
return fragmentView;
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putLong(CHRONO_TIME_SAVE_ID, mChrono.getBase());
super.onSaveInstanceState(outState);
}
}
@@ -0,0 +1,21 @@
package me.everything.overscrolldemo.view;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ScrollView;
import me.everything.android.ui.overscroll.OverScrollDecoratorHelper;
import me.everything.overscrolldemo.R;
public class NestedScrollViewDemoFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final ScrollView rootView = (ScrollView) inflater.inflate(R.layout.nested_scrollview_demo, null, false);
OverScrollDecoratorHelper.setUpOverScroll(rootView);
return rootView;
}
}
@@ -0,0 +1,190 @@
package me.everything.overscrolldemo.view;
import android.app.AlertDialog;
import androidx.fragment.app.Fragment;
import android.content.DialogInterface;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import me.everything.android.ui.overscroll.IOverScrollDecor;
import me.everything.android.ui.overscroll.IOverScrollStateListener;
import me.everything.android.ui.overscroll.IOverScrollUpdateListener;
import me.everything.android.ui.overscroll.OverScrollDecoratorHelper;
import me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator;
import me.everything.android.ui.overscroll.adapters.RecyclerViewOverScrollDecorAdapter;
import me.everything.overscrolldemo.R;
import me.everything.overscrolldemo.control.DemoContentHelper;
import static me.everything.android.ui.overscroll.IOverScrollState.*;
public class RecyclerViewDemoFragment extends Fragment {
private TextView mHorizScrollMeasure;
private TextView mVertScrollMeasure;
private IOverScrollDecor mHorizOverScrollEffect;
private IOverScrollDecor mVertOverScrollEffect;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View fragmentView = inflater.inflate(R.layout.recyclerview_overscroll_demo, null, false);
mHorizScrollMeasure = (TextView) fragmentView.findViewById(R.id.horizontal_scroll_measure);
mVertScrollMeasure = (TextView) fragmentView.findViewById(R.id.vertical_scroll_measure);
initHorizontalRecyclerView((RecyclerView) fragmentView.findViewById(R.id.horizontal_recycler_view));
initVerticalRecyclerView((RecyclerView) fragmentView.findViewById(R.id.vertical_recycler_view));
return fragmentView;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
final MenuItem detachMenuItem = menu.add("Detach over-scroll").setVisible(true);
final MenuItem attachMenuItem = menu.add("Attach over-scroll").setVisible(false);
detachMenuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
detachMenuItem.setVisible(false);
attachMenuItem.setVisible(true);
mHorizOverScrollEffect.detach();
mVertOverScrollEffect.detach();
return true;
}
});
attachMenuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
detachMenuItem.setVisible(true);
attachMenuItem.setVisible(false);
initHorizontalRecyclerView((RecyclerView) getView().findViewById(R.id.horizontal_recycler_view));
initVerticalRecyclerView((RecyclerView) getView().findViewById(R.id.vertical_recycler_view));
return true;
}
});
super.onCreateOptionsMenu(menu, inflater);
}
private void initHorizontalRecyclerView(RecyclerView recyclerView) {
LayoutInflater appInflater = LayoutInflater.from(getActivity().getApplicationContext());
RecyclerView.Adapter adapter = new DemoRecyclerAdapterHorizontal(DemoContentHelper.getSpectrumItems(getResources()), appInflater);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false));
// Apply over-scroll in 'standard form' - i.e. using the helper.
mHorizOverScrollEffect = OverScrollDecoratorHelper.setUpOverScroll(recyclerView, OverScrollDecoratorHelper.ORIENTATION_HORIZONTAL);
// Over-scroll listeners can be applied in standard form as well.
mHorizOverScrollEffect.setOverScrollUpdateListener(new IOverScrollUpdateListener() {
@Override
public void onOverScrollUpdate(IOverScrollDecor decor, int state, float offset) {
mHorizScrollMeasure.setText(String.valueOf((int) offset));
}
});
mHorizOverScrollEffect.setOverScrollStateListener(new IOverScrollStateListener() {
private final int mDragColorLeft = getResources().getColor(android.R.color.holo_purple);
private final int mBounceBackColorLeft = getResources().getColor(android.R.color.holo_blue_light);
private final int mDragColorRight = getResources().getColor(android.R.color.holo_red_light);
private final int mBounceBackColorRight = getResources().getColor(android.R.color.holo_orange_dark);
private final int mClearColor = mHorizScrollMeasure.getCurrentTextColor();
@Override
public void onOverScrollStateChange(IOverScrollDecor decor, int oldState, int newState) {
if (newState == STATE_DRAG_START_SIDE) {
mHorizScrollMeasure.setTextColor(mDragColorLeft);
} else if (newState == STATE_DRAG_END_SIDE) {
mHorizScrollMeasure.setTextColor(mDragColorRight);
} else if (newState == STATE_BOUNCE_BACK) {
mHorizScrollMeasure.setTextColor((oldState == STATE_DRAG_START_SIDE) ? mBounceBackColorLeft : mBounceBackColorRight);
} else {
mHorizScrollMeasure.setTextColor(mClearColor);
}
}
});
}
private void initVerticalRecyclerView(RecyclerView recyclerView) {
LayoutInflater appInflater = LayoutInflater.from(getActivity().getApplicationContext());
final DemoRecyclerAdapterBase adapter = new DemoRecyclerAdapterVertical(new ArrayList<>(DemoContentHelper.getReverseSpectrumItems(getResources())), appInflater);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
// Set-up of recycler-view's native item swiping.
ItemTouchHelper.Callback itemTouchHelperCallback = new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
return makeMovementFlags(0, ItemTouchHelper.RIGHT);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) {
AlertDialog dialog = new AlertDialog.Builder(getActivity())
.setTitle("Item swiping is supported!")
.setMessage("Recycler-view's native item swiping and the over-scrolling effect can co-exist! But, to get them to work WELL -- please apply the effect using the dedicated helper method!")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
adapter.notifyDataSetChanged();
}
})
.create();
dialog.show();
}
};
// Apply over-scroll in 'advanced form' - i.e. create an instance manually.
mVertOverScrollEffect = new VerticalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView, itemTouchHelperCallback));
// Over-scroll listeners are applied here via the mVertOverScrollEffect explicitly.
mVertOverScrollEffect.setOverScrollUpdateListener(new IOverScrollUpdateListener() {
@Override
public void onOverScrollUpdate(IOverScrollDecor decor, int state, float offset) {
mVertScrollMeasure.setText(String.valueOf((int) offset));
}
});
mVertOverScrollEffect.setOverScrollStateListener(new IOverScrollStateListener() {
private final int mDragColorTop = getResources().getColor(android.R.color.holo_red_light);
private final int mBounceBackColorTop = getResources().getColor(android.R.color.holo_orange_dark);
private final int mDragColorBottom = getResources().getColor(android.R.color.holo_purple);
private final int mBounceBackColorBottom = getResources().getColor(android.R.color.holo_blue_light);
private final int mClearColor = mHorizScrollMeasure.getCurrentTextColor();
@Override
public void onOverScrollStateChange(IOverScrollDecor decor, int oldState, int newState) {
if (newState == STATE_DRAG_START_SIDE) {
mVertScrollMeasure.setTextColor(mDragColorTop);
} else if (newState == STATE_DRAG_END_SIDE) {
mVertScrollMeasure.setTextColor(mDragColorBottom);
} else if (newState == STATE_BOUNCE_BACK) {
mVertScrollMeasure.setTextColor(oldState == STATE_DRAG_START_SIDE ? mBounceBackColorTop : mBounceBackColorBottom);
} else {
mVertScrollMeasure.setTextColor(mClearColor);
}
}
});
}
}
@@ -0,0 +1,39 @@
package me.everything.overscrolldemo.view;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import me.everything.android.ui.overscroll.OverScrollDecoratorHelper;
import me.everything.overscrolldemo.R;
import me.everything.overscrolldemo.control.DemoContentHelper;
public class RecyclerViewStaggeredGridDemoFragment extends Fragment {
private static final int GRID_SPAN_COUNT = 2;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.recyclerview_stgrid_overscroll_demo, null, false);
initVerticalRecyclerView((RecyclerView) fragmentView.findViewById(R.id.vertical_recycler_view));
return fragmentView;
}
private void initVerticalRecyclerView(RecyclerView recyclerView) {
LayoutInflater appInflater = LayoutInflater.from(getActivity().getApplicationContext());
final DemoRecyclerAdapterBase adapter = new DemoRecyclerAdapterVertical(new ArrayList<>(DemoContentHelper.getReverseSpectrumItems(getResources())), appInflater);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(GRID_SPAN_COUNT, StaggeredGridLayoutManager.VERTICAL));
OverScrollDecoratorHelper.setUpOverScroll(recyclerView, OverScrollDecoratorHelper.ORIENTATION_VERTICAL);
}
}
@@ -0,0 +1,34 @@
package me.everything.overscrolldemo.view;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import androidx.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;
import me.everything.android.ui.overscroll.OverScrollDecoratorHelper;
import me.everything.overscrolldemo.R;
public class ScrollViewDemoFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.scrollview_overscroll_demo, null, false);
initHorizontalScrollView((HorizontalScrollView) fragmentView.findViewById(R.id.horizontal_scroll_view));
initVerticalScrollView((ScrollView) fragmentView.findViewById(R.id.vertical_scroll_view));
return fragmentView;
}
private void initHorizontalScrollView(HorizontalScrollView scrollView) {
OverScrollDecoratorHelper.setUpOverScroll(scrollView);
}
private void initVerticalScrollView(ScrollView scrollView) {
OverScrollDecoratorHelper.setUpOverScroll(scrollView);
}
}
@@ -0,0 +1,78 @@
package me.everything.overscrolldemo.view;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
import me.everything.android.ui.overscroll.OverScrollDecoratorHelper;
import me.everything.overscrolldemo.R;
import me.everything.overscrolldemo.control.DemoContentHelper;
import me.everything.overscrolldemo.control.DemoItem;
public class ViewPagerDemoFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.viewpager_overscroll_demo,null,false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initHorizontalViewPager(DemoContentHelper.getSpectrumItems(getResources()), ((ViewPager) view.findViewById(R.id.view_pager)));
}
private void initHorizontalViewPager(List<DemoItem> items, ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(items);
viewPager.setAdapter(adapter);
OverScrollDecoratorHelper.setUpOverScroll(viewPager);
}
public static class ViewPagerAdapter extends PagerAdapter{
private List<DemoItem> items;
public ViewPagerAdapter(List<DemoItem> items){
this.items = items;
}
@Override
public int getCount() {
return items.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
@NonNull
public Object instantiateItem(ViewGroup container, int position) {
TextView textView = new TextView(container.getContext());
textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
textView.setText(items.get(position).getColorName());
textView.setBackgroundColor(items.get(position).getColor());
textView.setGravity(Gravity.CENTER);
container.addView(textView);
return textView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
}
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/linear"
android:valueFrom="0.0"
android:valueTo="1.0"
android:propertyName="alpha"
android:duration="500"
/>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/linear"
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:duration="80"
/>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:color="@android:color/white"
android:state_checked="true"
/>
<item android:color="@android:color/darker_gray"/>
</selector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 620 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 809 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 965 B

@@ -0,0 +1,10 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<gradient
android:startColor="@android:color/holo_red_dark"
android:centerColor="@android:color/holo_green_light"
android:endColor="@android:color/holo_blue_dark"
android:type="linear"
android:angle="135"
/>
</shape>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@android:color/darker_gray"
android:state_checked="true"
/>
</selector>
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
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:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start"
>
<include layout="@layout/activity_overscroll_demo_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<com.google.android.material.navigation.NavigationView
android:id="@+id/drawer_nav"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/drawer_header_overscroll_demo"
app:menu="@menu/activity_overscroll_demo_drawer_items"
app:itemBackground="@drawable/drawer_items_bkg"
/>
</androidx.drawerlayout.widget.DrawerLayout>
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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=".OverscrollDemo"
>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="@style/AppTheme.AppBarOverlay"
>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:id="@+id/fragment_placeholder"
android:layout_below="@id/app_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
/>
</RelativeLayout>
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:background="@color/colorPrimary"
android:padding="16dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:orientation="horizontal"
android:gravity="fill_horizontal"
>
<ImageView
android:layout_height="64dp"
android:layout_width="64dp"
android:src="@drawable/app_icon"
android:layout_gravity="center_vertical"
/>
<LinearLayout
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center_vertical"
android:paddingLeft="16dp"
>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/drawer_title"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:textSize="18dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/drawer_subtitle"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
/>
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/color_name"
android:layout_width="match_parent"
android:layout_height="200dp"
android:textSize="30dp"
android:textColor="@android:color/black"
android:gravity="center"
/>
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="@dimen/default_label_size"
android:text="@string/vert_drag_label"
android:lines="1"
/>
<!--
When over-scrolling is applied over views that don't stretch over the entire vertical region,
an artificial parent must be introduced so that bounds are clipped while over-scrolling is
in effect.
-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingTop="@dimen/activity_vertical_margin"
android:layout_weight="1"
>
<GridView
android:id="@+id/grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:gravity="center"
/>
</FrameLayout>
</LinearLayout>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/color_name"
android:layout_height="match_parent"
android:layout_width="100dp"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:textSize="18dp"
android:textColor="@android:color/black"
android:gravity="center"
/>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/color_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:textSize="40dp"
android:gravity="center"
android:clickable="true"
android:background="@android:color/black"
/>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="@dimen/default_label_size"
android:text="@string/vert_drag_label"
android:lines="1"
/>
<!--
When over-scrolling is applied over views that don't stretch over the entire vertical region,
an artificial parent must be introduced so that bounds are clipped while over-scrolling is
in effect.
-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingTop="@dimen/activity_vertical_margin"
android:layout_weight="1"
>
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
</LinearLayout>
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
>
<TextView
android:id="@+id/demo_text"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:clickable="true"
android:text="Practically any clickable widget can be over-scrolled.\nTry it!"
android:textSize="30sp"
android:layout_gravity="center"
android:gravity="center"
/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
<ImageView
android:id="@+id/demo_image"
android:layout_width="128dp"
android:layout_height="128dp"
android:layout_gravity="center"
android:clickable="true"
android:background="@drawable/app_icon"
/>
</FrameLayout>
<Chronometer
android:id="@+id/demo_chronometer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:layout_gravity="center"
android:clickable="true"
android:textSize="30sp"
/>
</LinearLayout>
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
>
<androidx.core.widget.NestedScrollView
android:id="@+id/nested_scrollview_root"
android:layout_width="match_parent"
android:layout_height="180dp"
android:padding="14dp"
android:paddingTop="0dp"
>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/nested_scrollview_text"
android:textSize="19sp"
android:textStyle="bold"
/>
</androidx.core.widget.NestedScrollView>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
</LinearLayout>
</ScrollView>
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:id="@+id/horizontal_recycler_view_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left"
android:textSize="@dimen/default_label_size"
android:text="@string/horiz_drag_label"
android:lines="1"
/>
<TextView
android:id="@+id/horizontal_scroll_measure"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:textSize="@dimen/default_subtitle_size"
android:text="0"
android:textStyle="bold"
/>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/horizontal_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:layout_weight="3"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:id="@+id/vertical_recycler_view_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left"
android:textSize="@dimen/default_label_size"
android:text="@string/vert_drag_label"
android:lines="1"
/>
<TextView
android:id="@+id/vertical_scroll_measure"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:textSize="@dimen/default_subtitle_size"
android:text="0"
android:textStyle="bold"
/>
</LinearLayout>
<!--
When over-scrolling is applied over views that don't stretch though the full vertical region,
an artificial parent must be introduced so that bounds are clipped while over-scrolling is
in effect.
-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingTop="10dp"
android:layout_weight="7"
>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/vertical_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
</LinearLayout>
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/vertical_recycler_view_header"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:textSize="@dimen/default_label_size"
android:text="@string/vert_drag_label"
android:lines="1"
/>
</LinearLayout>
<!--
When over-scrolling is applied over views that don't stretch though the full vertical region,
an artificial parent must be introduced so that bounds are clipped while over-scrolling is
in effect.
-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="10dp"
>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/vertical_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
</LinearLayout>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginRight="20dp"
>
<ImageView
android:layout_height="64dp"
android:layout_width="64dp"
android:src="@drawable/app_icon"
android:layout_gravity="center"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="EverythingMe"
/>
</LinearLayout>
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="@dimen/default_label_size"
android:text="@string/horiz_drag_label"
android:lines="1"
/>
<HorizontalScrollView
android:id="@+id/horizontal_scroll_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingTop="10dp"
android:layout_weight="3"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<include layout="@layout/scrollview_horizontal_item"/>
<include layout="@layout/scrollview_horizontal_item"/>
<include layout="@layout/scrollview_horizontal_item"/>
<include layout="@layout/scrollview_horizontal_item"/>
<include layout="@layout/scrollview_horizontal_item"/>
<include layout="@layout/scrollview_horizontal_item"/>
<include layout="@layout/scrollview_horizontal_item"/>
<include layout="@layout/scrollview_horizontal_item"/>
<include layout="@layout/scrollview_horizontal_item"/>
<include layout="@layout/scrollview_horizontal_item"/>
</LinearLayout>
</HorizontalScrollView>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="@dimen/default_label_size"
android:text="@string/vert_drag_label"
android:lines="1"
/>
<!--
When over-scrolling is applied over views that don't stretch over the full vertical region,
an artificial parent must be introduced so that bounds are clipped while over-scrolling is
in effect.
-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingTop="10dp"
android:layout_weight="7"
>
<ScrollView
android:id="@+id/vertical_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
<include layout="@layout/scrollview_vertical_item"/>
</LinearLayout>
</ScrollView>
</FrameLayout>
</LinearLayout>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="10dp"
>
<ImageView
android:layout_height="64dp"
android:layout_width="64dp"
android:src="@drawable/app_icon"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="EverythingMe"
android:textSize="21dp"
android:gravity="left|center_vertical"
android:layout_gravity="center"
/>
</LinearLayout>
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/app_bar_overscroll_demo"
tools:context=".OverscrollDemo"
>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</androidx.recyclerview.widget.RecyclerView>
</RelativeLayout>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/color_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:textSize="40dp"
android:textColor="@android:color/black"
android:gravity="center"
/>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
>
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group
android:checkableBehavior="single">
<item
android:id="@+id/drawer_item_recyclerview_demo"
android:icon="@drawable/ic_recycler"
android:title="RecyclerView Demo"
android:checked="true"
/>
<item
android:id="@+id/drawer_item_recyclerview_staggered_grid_demo"
android:icon="@drawable/ic_recycler"
android:title="RecyclerView - St.Grid Demo"
/>
<item
android:id="@+id/drawer_item_gridview_demo"
android:icon="@drawable/ic_grid"
android:title="GridView Demo"
/>
<item
android:id="@+id/drawer_item_listview_demo"
android:icon="@drawable/ic_list"
android:title="ListView Demo"
/>
<item
android:id="@+id/drawer_item_scrollview_demo"
android:icon="@drawable/ic_scroller"
android:title="ScrollView Demo"
/>
<item
android:id="@+id/drawer_item_viewpager_demo"
android:icon="@drawable/ic_view_pager"
android:title="ViewPager Demo"
/>
<item
android:id="@+id/drawer_item_nested_scrollview_demo"
android:title="NestedScrollView Demo"
/>
<item
android:id="@+id/drawer_item_misc_demo"
android:icon="@drawable/ic_misc"
android:title="Misc-Views Demo"
/>
</group>
</menu>
@@ -0,0 +1,8 @@
<resources>>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
@@ -0,0 +1,6 @@
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">@android:color/holo_orange_light</color>
<color name="colorPrimaryDark">@android:color/holo_orange_dark</color>
<color name="colorAccent">#FF4081</color>
<color name="spectrum_cyan">#00e0e0</color>
<color name="spectrum_yellow">#f0e000</color>
</resources>
@@ -0,0 +1,9 @@
<resources>
<dimen name="nav_header_vertical_spacing">16dp</dimen>
<dimen name="nav_header_height">140dp</dimen>
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="default_label_size">26sp</dimen>
<dimen name="default_subtitle_size">22sp</dimen>
</resources>
@@ -0,0 +1,23 @@
<resources>
<string name="app_name">OverscrollDemo</string>
<string name="drawer_title">Over-Scroll Demo App</string>
<string name="drawer_subtitle">EverythingMe</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="grid_view_demo_title">GridView Over-Scroll Demo</string>
<string name="list_view_demo_title">ListView Over-Scroll Demo</string>
<string name="recycler_view_demo_title">RecyclerView Over-Scroll Demo</string>
<string name="recycler_view_staggered_grid_demo_title">RecyclerView St.Grid Over-Scroll Demo</string>
<string name="scroll_view_demo_title">ScrollView Over-Scroll Demo</string>
<string name="viewpager_demo_title">ViewPager Over-Scroll Demo</string>
<string name="nested_scrollview_demo_title">NestedScrollView Over-Scroll Demo</string>
<string name="misc_views_demo_title">Misc. Over-Scroll Demo</string>
<string name="nested_scrollview_text">This text box is scrollable thanks to being situated inside a nested scroll view. That makes it scrollable regardless of the scrolling of the content of the entire screen, which can be scrolled independently.\nThe point here is to demonstrate how the over-scroll effect can work in the presence of nested scroll-views, provided it is applied over the parent (root) view, regardless of having inner nested scroll-views as children.\nIn this demo, the root view is merely a ScrollView, and therefore applying the effect over it is straightforward (i.e. using the OverScrollHelper).</string>
<string name="horiz_drag_label">⇔ Drag Horizontally</string>
<string name="vert_drag_label">⇳ Drag Vertically</string>
</resources>
@@ -0,0 +1,17 @@
<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>
+26
View File
@@ -0,0 +1,26 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
_isOverscrollDecor = true
}
repositories {
mavenCentral()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.2'
}
}
allprojects {
repositories {
mavenCentral()
google()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
+20
View File
@@ -0,0 +1,20 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.enableJetifier=true
android.useAndroidX=true
@@ -0,0 +1,6 @@
#Mon Mar 02 14:56:48 WIB 2026
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+164
View File
@@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
@@ -0,0 +1 @@
/build
@@ -0,0 +1,33 @@
apply plugin: 'com.android.library'
android {
namespace 'me.everything.android.ui.overscroll'
compileSdk 33
defaultConfig {
minSdkVersion 21
targetSdkVersion 33
versionCode 1
versionName '1.0'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'androidx.viewpager:viewpager:1.0.0'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-core:3.1.0'
testImplementation 'org.robolectric:robolectric:4.3.1'
}
// Enable publishing
if (rootProject.hasProperty('_isOverscrollDecor')) {
apply from: './publishing.gradle'
}
@@ -0,0 +1,39 @@
// Based on https://stackoverflow.com/a/42160584/453052
project.ext.buildPomXmlDependencies = { pom, configurations ->
pom.withXml {
final rootNode = asNode().appendNode('dependencies')
addConfigurationDependencies(rootNode, configurations.api, 'compile')
addConfigurationDependencies(rootNode, configurations.compile, 'compile')
addConfigurationDependencies(rootNode, configurations.implementation, 'runtime')
}
}
private static def addConfigurationDependencies(rootNode, Configuration configuration, String scope) {
configuration.dependencies.each { dep -> addChildDependency(rootNode, dep, scope) }
}
private static def addChildDependency(rootNode, Dependency dep, String scope) {
if (dep.group == null || dep.version == null || dep.name == null || dep.name == "unspecified")
return
final childNode = rootNode.appendNode('dependency')
childNode.appendNode('groupId', dep.group)
childNode.appendNode('artifactId', dep.name)
childNode.appendNode('version', dep.version)
childNode.appendNode('scope', scope)
if (!dep.transitive) {
// If this dependency is transitive, we should force exclude all its dependencies them from the POM
final exclusionNode = childNode.appendNode('exclusions').appendNode('exclusion')
exclusionNode.appendNode('groupId', '*')
exclusionNode.appendNode('artifactId', '*')
} else if (!dep.properties.excludeRules.empty) {
// Otherwise add specified exclude rules
final exclusionNode = childNode.appendNode('exclusions').appendNode('exclusion')
dep.properties.excludeRules.each { ExcludeRule rule ->
exclusionNode.appendNode('groupId', rule.group ?: '*')
exclusionNode.appendNode('artifactId', rule.module ?: '*')
}
}
}
@@ -0,0 +1,205 @@
apply plugin: 'maven-publish'
apply plugin: 'signing'
apply from: './publish-pom.gradle'
String TARGET_MAVEN_CENTRAL_URL = 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/'
List DEVELOPERS = [
[name: 'd4vidi', email: 'amit.d4vidi@gmail.com'],
]
String _sonatypeUsername = 'd4vidi'
String _sonatypePassword = System.getProperty('sonatypePassword')
String _versionName = System.getProperty('version')
String _mavenRepoUrl = TARGET_MAVEN_CENTRAL_URL
Map _mavenCredentials = [
username: _sonatypeUsername,
password: _sonatypePassword,
]
def _selectedVariant = null
def onPrePublish = {
assertDefined(_versionName, "Publishing: Version not specified (run 'gradle publish' with a -Dversion=1.2.3 argument)")
assertDefined(_sonatypePassword, "Publishing: Please specify the password to use for sonatype (run 'gradle publish' with a -DsonatypePassword=<pw> argument)")
logger.lifecycle("Publishing is now in session! 📣\n Version: $_versionName\n Target URL: ${_mavenRepoUrl}\n Build-variant: '${_selectedVariant.name}'")
}
def declareArchive = { target ->
project.artifacts {
archives target
}
}
// Running from Gradle tab in IDE would create liboverscroll/build/libs/liboverscroll-sources.jar
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
task javadoc(type: Javadoc) {
failOnError false
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}
// Running from Gradle tab in IDE would create liboverscroll/build/libs/liboverscroll-javadoc.jar
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
/*
* Signing configuration
* https://docs.gradle.org/current/userguide/signing_plugin.html
*/
// Tell signing task to sign everything current and future we set as a project archive...
signing {
sign configurations.archives
}
/*
* Plumbing work for actually having the publishing task work properly, if executed
*/
project.afterEvaluate {
project.tasks.all { Task task ->
android.libraryVariants.all { variant ->
String variantName = variant.name.capitalize()
if (task.name == "publishMaven${variantName}AarPublicationToMavenRepository") {
task.dependsOn "assemble${variantName}"
task.dependsOn project.tasks.signArchives
task.doFirst {
onPrePublish()
}
}
}
}
}
/*
* Publishing configuration
*/
publishing {
repositories {
maven {
url _mavenRepoUrl
if (_mavenCredentials != null) {
credentials {
username _mavenCredentials.username
password _mavenCredentials.password
}
}
}
}
publications {
android.libraryVariants.all { variant ->
if (isReleaseVariant(variant)) {
_selectedVariant = variant
String variantNameCapitalized = variant.name.capitalize()
"maven${variantNameCapitalized}Aar"(MavenPublication) {
groupId 'io.github.everythingme'
artifactId 'overscroll-decor-android'
version "$_versionName"
// Register built .aar as published artifact (as a file, explicitly)
variant.outputs.forEach { output ->
artifact output.outputFile
// Also register as an archive-artifact, for signing (via equivalent task's output)
declareArchive project.tasks["bundle${variantNameCapitalized}Aar"]
}
// Register sources, javadoc as published artifacts (via equivalent tasks' output)
artifact sourcesJar
artifact javadocJar
// Also register source, javadoc as archive-artifacts, for signing
declareArchive sourcesJar
declareArchive javadocJar
// Add package metadata to the .pom
pom {
name = 'Overscroll-Decor'
description = 'iOS-like over-scrolling effect for Android'
url = 'https://github.com/EverythingMe/overscroll-decor'
packaging 'aar' // Oh so important - or apps would ignore our code!!!!!
scm {
connection = 'scm:git:git://github.com/EverythingMe/overscroll-decor'
developerConnection = 'scm:git:git@github.com/EverythingMe/overscroll-decor.git'
url = 'https://github.com/EverythingMe/overscroll-decor'
}
licenses {
license {
name = 'BSD-2'
url = 'https://github.com/EverythingMe/overscroll-decor/blob/master/LICENSE'
}
}
developers {
DEVELOPERS.each { d ->
developer {
name = d.name
email = d.email
}
}
}
}
// Add dependencies to the .pom
buildPomXmlDependencies(pom, configurations)
// Register pom.xml's signature file (pom.xml.asc) as published artifact
// Note: this is done manually, instead of registering the pom as an archived artifact
pom.withXml {
def pomFile = file("${project.buildDir}/generated-pom.xml")
writeTo(pomFile) // Need to force-write so as to have the signature generated over the finalized content
def pomAscFile = signing.sign(pomFile).signatureFiles[0]
artifact(pomAscFile) {
classifier = null
extension = 'pom.asc'
}
}
// Register all artifacts we've previously registered as archives (i.e. .jar.asc's, .aar.asc's) as published artifacts.
// Note: this relies on preregistering the equivalent generator-tasks as archive artifacts
// inside a project.artifacts { ... } clause.
project.tasks.signArchives.signatureFiles.each {
artifact(it) {
def matcherSrcDocs = (it.file =~ /-(sources|javadoc)\.jar\.asc$/)
def matcherAAR = (it.file =~ /\.aar\.asc$/)
if (matcherSrcDocs.find()) {
classifier = matcherSrcDocs.group(1)
extension = 'jar.asc'
} else if (matcherAAR.find()) {
classifier = null
extension = 'aar.asc'
} else {
classifier = null
extension = null
}
}
}
}
}
}
}
}
/*
* Utils
*/
private static def isReleaseVariant(variant) {
return variant.buildType.name == 'release'
}
private static def assertDefined(target, message) {
if (target == null) {
throw new IllegalArgumentException(message)
}
}
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
@@ -0,0 +1,97 @@
package me.everything.android.ui.overscroll;
import android.view.MotionEvent;
import android.view.View;
import me.everything.android.ui.overscroll.adapters.IOverScrollDecoratorAdapter;
/**
* A concrete implementation of {@link OverScrollBounceEffectDecoratorBase} for a horizontal orientation.
*/
public class HorizontalOverScrollBounceEffectDecorator extends OverScrollBounceEffectDecoratorBase {
protected static class MotionAttributesHorizontal extends MotionAttributes {
public boolean init(View view, MotionEvent event) {
// We must have history available to calc the dx. Normally it's there - if it isn't temporarily,
// we declare the event 'invalid' and expect it in consequent events.
if (event.getHistorySize() == 0) {
return false;
}
// Allow for counter-orientation-direction operations (e.g. item swiping) to run fluently.
final float dy = event.getY(0) - event.getHistoricalY(0, 0);
final float dx = event.getX(0) - event.getHistoricalX(0, 0);
if (Math.abs(dx) < Math.abs(dy)) {
return false;
}
mAbsOffset = view.getTranslationX();
mDeltaOffset = dx;
mDir = mDeltaOffset > 0;
return true;
}
}
protected static class AnimationAttributesHorizontal extends AnimationAttributes {
public AnimationAttributesHorizontal() {
mProperty = View.TRANSLATION_X;
}
@Override
protected void init(View view) {
mAbsOffset = view.getTranslationX();
mMaxOffset = view.getWidth();
}
}
/**
* C'tor, creating the effect with default arguments:
* <br/>Touch-drag ratio in 'forward' direction will be set to DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD.
* <br/>Touch-drag ratio in 'backwards' direction will be set to DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK.
* <br/>Deceleration factor (for the bounce-back effect) will be set to DEFAULT_DECELERATE_FACTOR.
*
* @param viewAdapter The view's encapsulation.
*/
public HorizontalOverScrollBounceEffectDecorator(IOverScrollDecoratorAdapter viewAdapter) {
this(viewAdapter, DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD, DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK, DEFAULT_DECELERATE_FACTOR);
}
/**
* C'tor, creating the effect with explicit arguments.
* @param viewAdapter The view's encapsulation.
* @param touchDragRatioFwd Ratio of touch distance to actual drag distance when in 'forward' direction.
* @param touchDragRatioBck Ratio of touch distance to actual drag distance when in 'backward'
* direction (opposite to initial one).
* @param decelerateFactor Deceleration factor used when decelerating the motion to create the
* bounce-back effect.
*/
public HorizontalOverScrollBounceEffectDecorator(IOverScrollDecoratorAdapter viewAdapter,
float touchDragRatioFwd, float touchDragRatioBck, float decelerateFactor) {
super(viewAdapter, decelerateFactor, touchDragRatioFwd, touchDragRatioBck);
}
@Override
protected MotionAttributes createMotionAttributes() {
return new MotionAttributesHorizontal();
}
@Override
protected AnimationAttributes createAnimationAttributes() {
return new AnimationAttributesHorizontal();
}
@Override
protected void translateView(View view, float offset) {
view.setTranslationX(offset);
}
@Override
protected void translateViewAndEvent(View view, float offset, MotionEvent event) {
view.setTranslationX(offset);
event.offsetLocation(offset - event.getX(0), 0f);
}
}
@@ -0,0 +1,30 @@
package me.everything.android.ui.overscroll;
import android.view.View;
public interface IOverScrollDecor {
View getView();
void setOverScrollStateListener(IOverScrollStateListener listener);
void setOverScrollUpdateListener(IOverScrollUpdateListener listener);
/**
* Get the current decorator's runtime state, i.e. one of the values specified by {@link IOverScrollState}.
* @return The state.
*/
int getCurrentState();
/**
* Detach the decorator from its associated view, thus disabling it entirely.
*
* <p>It is best to call this only when over-scroll isn't currently in-effect - i.e. verify that
* <code>getCurrentState()==IOverScrollState.STATE_IDLE</code> as a precondition, or otherwise
* use a state listener previously installed using
* {@link #setOverScrollStateListener(IOverScrollStateListener)}.</p>
*
* <p>Note: Upon detachment completion, the view in question will return to the default
* Android over-scroll configuration (i.e. {@link View.OVER_SCROLL_ALWAYS} mode). This can be
* overridden by calling <code>View.setOverScrollMode(mode)</code> immediately thereafter.</p>
*/
void detach();
}

Some files were not shown because too many files have changed in this diff Show More