diff --git a/devsmartlib/src/com/devsmart/android/ui/HorizontalListView.java b/devsmartlib/src/com/devsmart/android/ui/HorizontalListView.java index 076ed38..a305bbe 100644 --- a/devsmartlib/src/com/devsmart/android/ui/HorizontalListView.java +++ b/devsmartlib/src/com/devsmart/android/ui/HorizontalListView.java @@ -1,389 +1,398 @@ -/* - * HorizontalListView.java v1.5 - * - * - * The MIT License - * Copyright (c) 2011 Paul Soucy (paul@dev-smart.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -package com.devsmart.android.ui; - -import java.util.LinkedList; -import java.util.Queue; - -import android.content.Context; -import android.database.DataSetObserver; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.GestureDetector; -import android.view.GestureDetector.OnGestureListener; -import android.view.MotionEvent; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ListAdapter; -import android.widget.Scroller; - -public class HorizontalListView extends AdapterView { - - public boolean mAlwaysOverrideTouch = true; - protected ListAdapter mAdapter; - private int mLeftViewIndex = -1; - private int mRightViewIndex = 0; - protected int mCurrentX; - protected int mNextX; - private int mMaxX = Integer.MAX_VALUE; - private int mDisplayOffset = 0; - protected Scroller mScroller; - private GestureDetector mGesture; - private Queue mRemovedViewQueue = new LinkedList(); - private OnItemSelectedListener mOnItemSelected; - private OnItemClickListener mOnItemClicked; - private OnItemLongClickListener mOnItemLongClicked; - private boolean mDataChanged = false; - - - public HorizontalListView(Context context, AttributeSet attrs) { - super(context, attrs); - initView(); - } - - private synchronized void initView() { - mLeftViewIndex = -1; - mRightViewIndex = 0; - mDisplayOffset = 0; - mCurrentX = 0; - mNextX = 0; - mMaxX = Integer.MAX_VALUE; - mScroller = new Scroller(getContext()); - mGesture = new GestureDetector(getContext(), mOnGesture); - } - - @Override - public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) { - mOnItemSelected = listener; - } - - @Override - public void setOnItemClickListener(AdapterView.OnItemClickListener listener){ - mOnItemClicked = listener; - } - - @Override - public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) { - mOnItemLongClicked = listener; - } - - private DataSetObserver mDataObserver = new DataSetObserver() { - - @Override - public void onChanged() { - synchronized(HorizontalListView.this){ - mDataChanged = true; - } - invalidate(); - requestLayout(); - } - - @Override - public void onInvalidated() { - reset(); - invalidate(); - requestLayout(); - } - - }; - - @Override - public ListAdapter getAdapter() { - return mAdapter; - } - - @Override - public View getSelectedView() { - //TODO: implement - return null; - } - - @Override - public void setAdapter(ListAdapter adapter) { - if(mAdapter != null) { - mAdapter.unregisterDataSetObserver(mDataObserver); - } - mAdapter = adapter; - mAdapter.registerDataSetObserver(mDataObserver); - reset(); - } - - private synchronized void reset(){ - initView(); - removeAllViewsInLayout(); - requestLayout(); - } - - @Override - public void setSelection(int position) { - //TODO: implement - } - - private void addAndMeasureChild(final View child, int viewPos) { - LayoutParams params = child.getLayoutParams(); - if(params == null) { - params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); - } - - addViewInLayout(child, viewPos, params, true); - child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), - MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST)); - } - - - - @Override - protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - - if(mAdapter == null){ - return; - } - - if(mDataChanged){ - int oldCurrentX = mCurrentX; - initView(); - removeAllViewsInLayout(); - mNextX = oldCurrentX; - mDataChanged = false; - } - - if(mScroller.computeScrollOffset()){ - int scrollx = mScroller.getCurrX(); - mNextX = scrollx; - } - - if(mNextX <= 0){ - mNextX = 0; - mScroller.forceFinished(true); - } - if(mNextX >= mMaxX) { - mNextX = mMaxX; - mScroller.forceFinished(true); - } - - int dx = mCurrentX - mNextX; - - removeNonVisibleItems(dx); - fillList(dx); - positionItems(dx); - - mCurrentX = mNextX; - - if(!mScroller.isFinished()){ - post(new Runnable(){ - @Override - public void run() { - requestLayout(); - } - }); - - } - } - - private void fillList(final int dx) { - int edge = 0; - View child = getChildAt(getChildCount()-1); - if(child != null) { - edge = child.getRight(); - } - fillListRight(edge, dx); - - edge = 0; - child = getChildAt(0); - if(child != null) { - edge = child.getLeft(); - } - fillListLeft(edge, dx); - - - } - - private void fillListRight(int rightEdge, final int dx) { - while(rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) { - - View child = mAdapter.getView(mRightViewIndex, mRemovedViewQueue.poll(), this); - addAndMeasureChild(child, -1); - rightEdge += child.getMeasuredWidth(); - - if(mRightViewIndex == mAdapter.getCount()-1) { - mMaxX = mCurrentX + rightEdge - getWidth(); - } - - if (mMaxX < 0) { - mMaxX = 0; - } - mRightViewIndex++; - } - - } - - private void fillListLeft(int leftEdge, final int dx) { - while(leftEdge + dx > 0 && mLeftViewIndex >= 0) { - View child = mAdapter.getView(mLeftViewIndex, mRemovedViewQueue.poll(), this); - addAndMeasureChild(child, 0); - leftEdge -= child.getMeasuredWidth(); - mLeftViewIndex--; - mDisplayOffset -= child.getMeasuredWidth(); - } - } - - private void removeNonVisibleItems(final int dx) { - View child = getChildAt(0); - while(child != null && child.getRight() + dx <= 0) { - mDisplayOffset += child.getMeasuredWidth(); - mRemovedViewQueue.offer(child); - removeViewInLayout(child); - mLeftViewIndex++; - child = getChildAt(0); - - } - - child = getChildAt(getChildCount()-1); - while(child != null && child.getLeft() + dx >= getWidth()) { - mRemovedViewQueue.offer(child); - removeViewInLayout(child); - mRightViewIndex--; - child = getChildAt(getChildCount()-1); - } - } - - private void positionItems(final int dx) { - if(getChildCount() > 0){ - mDisplayOffset += dx; - int left = mDisplayOffset; - for(int i=0;i { + + public boolean mAlwaysOverrideTouch = true; + protected ListAdapter mAdapter; + private int mLeftViewIndex = -1; + private int mRightViewIndex = 0; + protected int mCurrentX; + protected int mNextX; + private int mMaxX = Integer.MAX_VALUE; + private int mDisplayOffset = 0; + protected Scroller mScroller; + private GestureDetector mGesture; + private Queue mRemovedViewQueue = new LinkedList(); + private OnItemSelectedListener mOnItemSelected; + private OnItemClickListener mOnItemClicked; + private OnItemLongClickListener mOnItemLongClicked; + private boolean mDataChanged = false; + + + public HorizontalListView(Context context, AttributeSet attrs) { + super(context, attrs); + initView(); + } + + private synchronized void initView() { + mLeftViewIndex = -1; + mRightViewIndex = 0; + mDisplayOffset = 0; + mCurrentX = 0; + mNextX = 0; + mMaxX = Integer.MAX_VALUE; + mScroller = new Scroller(getContext()); + mGesture = new GestureDetector(getContext(), mOnGesture); + } + + @Override + public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) { + mOnItemSelected = listener; + } + + @Override + public void setOnItemClickListener(AdapterView.OnItemClickListener listener){ + mOnItemClicked = listener; + } + + @Override + public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) { + mOnItemLongClicked = listener; + } + + private DataSetObserver mDataObserver = new DataSetObserver() { + + @Override + public void onChanged() { + synchronized(HorizontalListView.this){ + mDataChanged = true; + } + invalidate(); + requestLayout(); + } + + @Override + public void onInvalidated() { + reset(); + invalidate(); + requestLayout(); + } + + }; + + @Override + public ListAdapter getAdapter() { + return mAdapter; + } + + @Override + public View getSelectedView() { + //TODO: implement + return null; + } + + @Override + public void setAdapter(ListAdapter adapter) { + if(mAdapter != null) { + mAdapter.unregisterDataSetObserver(mDataObserver); + } + mAdapter = adapter; + mAdapter.registerDataSetObserver(mDataObserver); + reset(); + } + + private synchronized void reset(){ + initView(); + removeAllViewsInLayout(); + requestLayout(); + } + + @Override + public void setSelection(int position) { + //TODO: implement + } + + private void addAndMeasureChild(final View child, int viewPos) { + LayoutParams params = child.getLayoutParams(); + if(params == null) { + params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + } + + addViewInLayout(child, viewPos, params, true); + child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), + MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST)); + } + + + + @Override + protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + if(mAdapter == null){ + return; + } + + if(mDataChanged){ + int oldCurrentX = mCurrentX; + initView(); + removeAllViewsInLayout(); + mNextX = oldCurrentX; + mDataChanged = false; + } + + if(mScroller.computeScrollOffset()){ + int scrollx = mScroller.getCurrX(); + mNextX = scrollx; + } + + if(mNextX <= 0){ + mNextX = 0; + mScroller.forceFinished(true); + } + if(mNextX >= mMaxX) { + mNextX = mMaxX; + mScroller.forceFinished(true); + } + + int dx = mCurrentX - mNextX; + + removeNonVisibleItems(dx); + fillList(dx); + positionItems(dx); + + mCurrentX = mNextX; + + if(!mScroller.isFinished()){ + post(new Runnable(){ + @Override + public void run() { + requestLayout(); + } + }); + + } + } + + private void fillList(final int dx) { + int edge = 0; + View child = getChildAt(getChildCount()-1); + if(child != null) { + edge = child.getRight(); + } + fillListRight(edge, dx); + + edge = 0; + child = getChildAt(0); + if(child != null) { + edge = child.getLeft(); + } + fillListLeft(edge, dx); + + + } + + private void fillListRight(int rightEdge, final int dx) { + while(rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) { + + View child = mAdapter.getView(mRightViewIndex, mRemovedViewQueue.poll(), this); + addAndMeasureChild(child, -1); + rightEdge += child.getMeasuredWidth(); + + if(mRightViewIndex == mAdapter.getCount()-1) { + mMaxX = mCurrentX + rightEdge - getWidth(); + } + + if (mMaxX < 0) { + mMaxX = 0; + } + mRightViewIndex++; + } + + } + + private void fillListLeft(int leftEdge, final int dx) { + while(leftEdge + dx > 0 && mLeftViewIndex >= 0) { + View child = mAdapter.getView(mLeftViewIndex, mRemovedViewQueue.poll(), this); + addAndMeasureChild(child, 0); + leftEdge -= child.getMeasuredWidth(); + mLeftViewIndex--; + mDisplayOffset -= child.getMeasuredWidth(); + } + } + + private void removeNonVisibleItems(final int dx) { + View child = getChildAt(0); + while(child != null && child.getRight() + dx <= 0) { + mDisplayOffset += child.getMeasuredWidth(); + mRemovedViewQueue.offer(child); + removeViewInLayout(child); + mLeftViewIndex++; + child = getChildAt(0); + + } + + child = getChildAt(getChildCount()-1); + while(child != null && child.getLeft() + dx >= getWidth()) { + mRemovedViewQueue.offer(child); + removeViewInLayout(child); + mRightViewIndex--; + child = getChildAt(getChildCount()-1); + } + } + + private void positionItems(final int dx) { + if(getChildCount() > 0){ + mDisplayOffset += dx; + int left = mDisplayOffset; + for(int i=0;i