package hk.hku.cs.srli.widget; import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.ListView; import hk.hku.cs.srli.widget.HoverScrollView.ScrollState; import hk.hku.cs.srli.widget.util.EdgeEffectHelper; import hk.hku.cs.srli.widget.util.HoverHandler; // almost identical to GridView public class HoverListView extends ListView { private HoverHandler hover; private EdgeEffectHelper edge; // to change this, use changeState(newState) private ScrollState state; public HoverListView(Context context) { super(context); init(null, 0); } public HoverListView(Context context, AttributeSet attrs) { super(context, attrs); init(attrs, 0); } public HoverListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(attrs, defStyle); } private void init(AttributeSet attrs, int defStyle) { hover = new HoverHandler(this); edge = new EdgeEffectHelper(this); hover.setOnHoverMoveListener(edge); state = ScrollState.NOT_SCROLLABLE; edge.setEdgeGlow(false, false, false, false); setWillNotDraw(false); } @Override public void onHoverChanged(boolean hovered) { super.onHoverChanged(hovered); edge.onHoverChanged(hovered); } @Override public boolean onInterceptHoverEvent(MotionEvent event) { // get all hover events from here hover.onHoverEvent(event); // don't interference with children return false; } @Override public boolean onHoverEvent(MotionEvent event) { // already handled above return false; } @Override public void draw(Canvas canvas) { super.draw(canvas); edge.draw(canvas); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); updateScrollState(); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); updateScrollState(); } private void updateScrollState() { if (getChildCount() <= 0) { changeState(ScrollState.NOT_SCROLLABLE); return; } float top = getChildAt(0).getTop(); float bottom = getChildAt(getChildCount() - 1).getBottom(); boolean reachedTop = getFirstVisiblePosition() == 0 && top >= 0; boolean reachedBottom = getLastVisiblePosition() == getAdapter().getCount() - 1 && bottom <= getHeight(); if (reachedTop && reachedBottom) changeState(ScrollState.NOT_SCROLLABLE); else if (reachedTop && !reachedBottom) changeState(ScrollState.TOP); else if (!reachedTop && reachedBottom) changeState(ScrollState.BOTTOM); else changeState(ScrollState.MIDDLE); } private void changeState(ScrollState newState) { if (newState == state) return; state = newState; switch(state) { case NOT_SCROLLABLE: edge.setVerticalScrollable(false, false); return; case TOP: edge.setVerticalScrollable(false, true); return; case BOTTOM: edge.setVerticalScrollable(true, false); return; case MIDDLE: edge.setVerticalScrollable(true, true); return; } } }