DiscreteScrollView
The library is a RecyclerView-based implementation of a scrollable list, where current item is centered and can be changed using swipes.
It is similar to a ViewPager, but you can quickly and painlessly create layout, where views adjacent to the currently selected view are partially or fully visible on the screen.
Gradle
Add this into your dependencies block.
compile 'com.yarolegovich:discrete-scrollview:1.5.1'
Reporting an issue
If you are going to report an issue, I will greatly appreciate you including some code which I can run to see the issue. By doing so you maximize the chance that I will fix the problem.
By the way, before reporting a problem, try replacing DiscreteScrollView with a RecyclerView. If the problem is still present, it's likely somewhere in your code.
Sample
Please see the sample app for examples of library usage.
Wiki
General
The library uses a custom LayoutManager to adjust items' positions on the screen and handle scroll, however it is not exposed to the client
code. All public API is accessible through DiscreteScrollView class, which is a simple descendant of RecyclerView.
If you have ever used RecyclerView - you already know how to use this library. One thing to note - you should NOT set LayoutManager.
Usage:
- Add DiscreteScrollView to your layout either using xml or code:
- Create your implementation of RecyclerView.Adapter. Refer to the sample for an example, if you don't know how to do it.
- Set the adapter.
- You are done!
<com.yarolegovich.discretescrollview.DiscreteScrollView
android:id="@+id/picker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:dsv_orientation="horizontal|vertical" />
DiscreteScrollView scrollView = findViewById(R.id.picker);
scrollView.setAdapter(new YourAdapterImplementation());
API
General
scrollView.setOrientation(DSVOrientation o);
scrollView.setOffscreenItems(count);
scrollView.setOverScrollEnabled(enabled);
Related to the current item:
scrollView.getCurrentItem();
scrollView.scrollToPosition(int position);
scrollView.smoothScrollToPosition(int position);
scrollView.setItemTransitionTimeMillis(int millis);
Transformations
One useful feature of ViewPager is page transformations. It allows you, for example, to create carousel effect. DiscreteScrollView also supports
page transformations.
scrollView.setItemTransformer(transformer);
public interface DiscreteScrollItemTransformer {
void transformItem(View item, float position);
}
In the above example view1Position == (currentlySelectedViewPosition - n)
and view2Position == (currentlySelectedViewPosition + n)
, where n
defaults to 1 and can be changed using the following API:
scrollView.setClampTransformProgressAfter(n);
Because scale transformation is the most common, I included a helper class - ScaleTransformer, here is how to use it:
cityPicker.setItemTransformer(new ScaleTransformer.Builder()
.setMaxScale(1.05f)
.setMinScale(0.8f)
.setPivotX(Pivot.X.CENTER)
.setPivotY(Pivot.Y.BOTTOM)
.build());
You may see how it works on GIFs.
Slide through multiple items
To allow slide through multiple items call:
scrollView.setSlideOnFling(true);
The default threshold is set to 2100. Lower the threshold, more fluid the animation. You can adjust the threshold by calling:
scrollView.setSlideOnFlingThreshold(value);
Infinite scroll
Infinite scroll is implemented on the adapter level:
InfiniteScrollAdapter wrapper = InfiniteScrollAdapter.wrap(yourAdapter);
scrollView.setAdapter(wrapper);
An instance of InfiniteScrollAdapter
has the following useful methods:
int getRealItemCount();
int getRealCurrentPosition();
int getRealPosition(int position);
int getClosestPosition(int position);
Currently InfiniteScrollAdapter
handles data set changes inefficiently, so your contributions are welcome.
Disabling scroll
It's possible to forbid user scroll in any or specific direction using:
scrollView.setScrollConfig(config);
Where config
is an instance of DSVScrollConfig
enum. The default value enables scroll in any direction.
Callbacks
scrollView.addScrollStateChangeListener(listener);
scrollView.removeScrollStateChangeListener(listener);
public interface ScrollStateChangeListener<T extends ViewHolder> {
void onScrollStart(T currentItemHolder, int adapterPosition);
void onScrollEnd(T currentItemHolder, int adapterPosition);
void onScroll(float scrollPosition, int currentIndex, int newIndex, @Nullable T currentHolder, @Nullable T newCurrentHolder);
}
scrollView.addScrollListener(listener);
scrollView.removeScrollListener(listener);
public interface ScrollListener<T extends ViewHolder> {
void onScroll(float scrollPosition, int currentIndex, int newIndex, @Nullable T currentHolder, @Nullable T newCurrentHolder);
}
- Current selection changes:
scrollView.addOnItemChangedListener(listener);
scrollView.removeOnItemChangedListener(listener);
public interface OnItemChangedListener<T extends ViewHolder> {
void onCurrentItemChanged(@Nullable T viewHolder, int adapterPosition);
}
Special thanks
Thanks to Tayisiya Yurkiv for sample app design and beautiful GIFs.
License
Copyright 2017 Yaroslav Shevchuk
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.