This commit is contained in:
2026-03-03 16:30:57 +07:00
parent a13304e40e
commit c253e1a370
7569 changed files with 1324841 additions and 0 deletions

1
lib/overscroll-decor/app/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

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'
}

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 *;
#}

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
});
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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"
/>

View File

@@ -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"
/>

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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"
/>

View File

@@ -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>

View File

@@ -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"
/>

View File

@@ -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"
/>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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"
/>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>