• 自定制横向ListView资料分享 Binary


    首先,感谢该组件作者,:) 。

    组件下载地址:https://github.com/dinocore1/DevsmartLib-Android

    组件介绍地址:http://www.dev-smart.com/archives/34

    组件名称:HorizontalListView

    组件代码:如下所示

    /*
     * 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<ListAdapter> {
    
        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<View> mRemovedViewQueue = new LinkedList<View>();
        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<getChildCount();i++){
                    View child = getChildAt(i);
                    int childWidth = child.getMeasuredWidth();
                    child.layout(left, 0, left + childWidth, child.getMeasuredHeight());
                    left += childWidth;
                }
            }
        }
        
        public synchronized void scrollTo(int x) {
            mScroller.startScroll(mNextX, 0, x - mNextX, 0);
            requestLayout();
        }
        
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            boolean handled = super.dispatchTouchEvent(ev);
            handled |= mGesture.onTouchEvent(ev);
            return handled;
        }
        
        protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                    float velocityY) {
            synchronized(HorizontalListView.this){
                mScroller.fling(mNextX, 0, (int)-velocityX, 0, 0, mMaxX, 0, 0);
            }
            requestLayout();
            
            return true;
        }
        
        protected boolean onDown(MotionEvent e) {
            mScroller.forceFinished(true);
            return true;
        }
        
        private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() {
    
            @Override
            public boolean onDown(MotionEvent e) {
                return HorizontalListView.this.onDown(e);
            }
    
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                    float velocityY) {
                return HorizontalListView.this.onFling(e1, e2, velocityX, velocityY);
            }
    
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2,
                    float distanceX, float distanceY) {
                
                synchronized(HorizontalListView.this){
                    mNextX += (int)distanceX;
                }
                requestLayout();
                
                return true;
            }
    
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                for(int i=0;i<getChildCount();i++){
                    View child = getChildAt(i);
                    if (isEventWithinView(e, child)) {
                        if(mOnItemClicked != null){
                            mOnItemClicked.onItemClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));
                        }
                        if(mOnItemSelected != null){
                            mOnItemSelected.onItemSelected(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));
                        }
                        break;
                    }
                    
                }
                return true;
            }
            
            @Override
            public void onLongPress(MotionEvent e) {
                int childCount = getChildCount();
                for (int i = 0; i < childCount; i++) {
                    View child = getChildAt(i);
                    if (isEventWithinView(e, child)) {
                        if (mOnItemLongClicked != null) {
                            mOnItemLongClicked.onItemLongClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i));
                        }
                        break;
                    }
    
                }
            }
    
            private boolean isEventWithinView(MotionEvent e, View child) {
                Rect viewRect = new Rect();
                int[] childPosition = new int[2];
                child.getLocationOnScreen(childPosition);
                int left = childPosition[0];
                int right = left + child.getWidth();
                int top = childPosition[1];
                int bottom = top + child.getHeight();
                viewRect.set(left, top, right, bottom);
                return viewRect.contains((int) e.getRawX(), (int) e.getRawY());
            }
        };
    
        
    
    
  • 相关阅读:
    变量的作用域
    内联函数inline
    数组、函数和指针
    关于android:configChanges的属性的简介
    Android 更新UI的两种方法
    android开发两种退出程序方式
    google内购In-App Billing
    谷歌登陆sdk对接
    openssl测试版本小工具
    关于facebook登陆不安装openssl的情况下怎么获得Facebook Key Hash的简单方法
  • 原文地址:https://www.cnblogs.com/nmj1986/p/2637942.html
Copyright © 2020-2023  润新知