package com.marshalchen.common.uimodule.listbuddies.views;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ListView;
/**
* ListView that notify the through a listener about the Y distance that was scrolled.
*/
public class ObservableListView extends ListView {
private static final String TAG = ObservableListView.class.getSimpleName();
/**
* Delegate for the callback to the fragment/activity that the ListView is in
*/
private ListViewObserverDelegate mObserver;
private View mTrackedChild;
private int mTrackedChildPrevPosition;
private int mTrackedChildPrevTop;
public ObservableListView(Context context) {
super(context);
}
public ObservableListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ObservableListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public static interface ListViewObserverDelegate {
public void onListScroll(View view, float deltaY);
}
private View getChildInTheMiddle() {
return getChildAt(getChildCount() / 2);
}
public void setObserver(ListViewObserverDelegate observer) {
mObserver = observer;
}
/**
* Calculate the scroll distance comparing the distance with the top of the list of the current
* child and the last one tracked
*
* @param l - Current horizontal scroll origin.
* @param t - Current vertical scroll origin.
* @param oldl - Previous horizontal scroll origin.
* @param oldt - Previous vertical scroll origin.
*/
private float OldDeltaY;
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (mTrackedChild == null) {
//We want to continue scrolling the list when we don't find a valid child
// so we use the last value of deltaY
mObserver.onListScroll(this, OldDeltaY);
if (getChildCount() > 0) {
mTrackedChild = getChildInTheMiddle();
mTrackedChildPrevTop = mTrackedChild.getTop();
mTrackedChildPrevPosition = getPositionForView(mTrackedChild);
}
} else {
boolean childIsSafeToTrack = mTrackedChild.getParent() == this && getPositionForView(mTrackedChild) == mTrackedChildPrevPosition;
if (childIsSafeToTrack) {
int top = mTrackedChild.getTop();
if (mObserver != null) {
float deltaY = top - mTrackedChildPrevTop;
if (deltaY == 0) {
//When we scroll so fast the list this value becomes 0 all the time
// so we don't want the other list stop, and we give it the last
//no 0 value we have
deltaY = OldDeltaY;
} else {
OldDeltaY = deltaY;
}
mObserver.onListScroll(this, deltaY);
}
mTrackedChildPrevTop = top;
} else {
mTrackedChild = null;
}
}
}
}