Created
November 12, 2015 11:40
-
-
Save oianmol/cb6849c94f11a3a4e749 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.support.v4.view.ViewCompat; | |
import android.support.v7.widget.RecyclerView; | |
import android.support.v7.widget.RecyclerView.OnScrollListener; | |
import android.util.AttributeSet; | |
import android.util.Log; | |
import android.view.MotionEvent; | |
import android.view.View; | |
import android.widget.AbsListView; | |
import android.widget.ListView; | |
import android.widget.TextView; | |
public class CircleListView extends RecyclerView { | |
private static final String TAG = CircleListView.class.getSimpleName(); | |
private static final boolean DEBUG = BuildConfig.DEBUG && false; | |
private static final int DEFAULT_SCROLL_DURATION = 200; | |
public static final int DEFAULT_SELECTION = Integer.MAX_VALUE / 2; | |
private boolean mIsForceCentering; | |
private ViewModifier mViewModifier; | |
private final CenterRunnable mCenterRunnable = new CenterRunnable(); | |
private int mScrollDuration = DEFAULT_SCROLL_DURATION; | |
private OnItemCenteredListener mOnItemCenteredListener; | |
public CircleListView(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
setOnScrollListener(new OnScrollListener() { | |
@Override | |
public void onScrollStateChanged(RecyclerView recyclerView, int newState) { | |
super.onScrollStateChanged(recyclerView, newState); | |
if (newState == RecyclerView.SCROLL_STATE_IDLE) { | |
if (!mIsForceCentering) { | |
// Start centering the view | |
mIsForceCentering = true; | |
final View childView = findViewAtCenter(); | |
if (childView != null) { | |
if (DEBUG) { | |
} | |
if (mOnItemCenteredListener != null) { | |
mOnItemCenteredListener.onItemCentered(childView); | |
} | |
mCenterRunnable.setView(childView); | |
ViewCompat.postOnAnimation(CircleListView.this, mCenterRunnable); | |
} | |
} | |
} | |
} | |
@Override | |
public void onScrolled(RecyclerView recyclerView, int dx, int dy) { | |
super.onScrolled(recyclerView, dx, dy); | |
if (mViewModifier != null) { | |
final int count = getChildCount(); | |
for (int i = 0; i < count; ++i) { | |
View v = getChildAt(i); | |
mViewModifier.applyToView(v, CircleListView.this); | |
} | |
} | |
} | |
}); | |
setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER); | |
} | |
@Override | |
protected void onLayout(boolean changed, int l, int t, int r, int b) { | |
super.onLayout(changed, l, t, r, b); | |
this.smoothScrollToPosition(DEFAULT_SELECTION); | |
} | |
/** | |
* Sets the current {@link ViewModifier} for this list. | |
* | |
* @param modifier implementation of the {@link ViewModifier} class | |
* @see ViewModifier | |
*/ | |
public void setViewModifier(ViewModifier modifier) { | |
mViewModifier = modifier; | |
} | |
/** | |
* Sets the smooth scroll duration. | |
* | |
* @param duration the number of milliseconds the scrolling animation will take | |
*/ | |
public void setScrollDuration(int duration) { | |
mScrollDuration = duration; | |
} | |
/** | |
* Sets the listener object that will be notified when the list centers on an item. | |
* | |
* @param listener the {@link OnItemCenteredListener} implementation | |
*/ | |
public void setOnItemCenteredListener(OnItemCenteredListener listener) { | |
mOnItemCenteredListener = listener; | |
} | |
public void smoothScrollToView(View v) { | |
final float y = v.getY() + v.getHeight() * 0.5f; | |
final float halfHeight = getHeight() * 0.5f; | |
final int distance = (int) (y - halfHeight); | |
smoothScrollBy(distance, mScrollDuration); | |
} | |
@Override | |
public boolean onTouchEvent(MotionEvent ev) { | |
removeCallbacks(mCenterRunnable); | |
mIsForceCentering = false; | |
return super.onTouchEvent(ev); | |
} | |
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { | |
} | |
/** | |
* Finds a View located at the specified point. | |
* | |
* @param x x-coordinate of the point | |
* @param y y-coordinate of the point | |
* @return {@link View} located at (x, y) or <code>null</code> if not found | |
*/ | |
public View findViewAt(int x, int y) { | |
final int count = getChildCount(); | |
for (int i = 0; i < count; ++i) { | |
final View v = getChildAt(i); | |
final int x0 = v.getLeft(); | |
final int y0 = v.getTop(); | |
final int x1 = v.getWidth() - x0; | |
final int y1 = v.getHeight() + y0; | |
if (x >= x0 && x <= x1 && y >= y0 && y <= y1) { | |
return v; | |
} | |
} | |
return null; | |
} | |
/** | |
* Finds a {@link View} located in the center of the {@link CircleListView}. | |
* | |
* @return the {@link View} at the center of the {@link CircleListView} | |
*/ | |
public View findViewAtCenter() { | |
return findViewAt(0, getHeight() / 2); | |
} | |
public class CenterRunnable implements Runnable { | |
private View mView; | |
public void setView(View v) { | |
mView = v; | |
} | |
public void run() { | |
smoothScrollToView(mView); | |
mIsForceCentering = true; | |
} | |
} | |
/** | |
* Handles the event occurring when the list centers on an item. | |
* | |
* @see CircleListView#setOnItemCenteredListener(OnItemCenteredListener) | |
*/ | |
public interface OnItemCenteredListener { | |
public void onItemCentered(View v); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment