Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现 (附源码下载)

package org.com.cctest.adapter;  
02.  
03.import java.util.ArrayList;  
04.import java.util.List;  
05.  
06.import org.com.cctest.R;  
07.import org.com.cctest.bean.VideoBean;  
08.import android.content.Context;  
09.import android.view.LayoutInflater;  
10.import android.view.View;  
11.import android.view.ViewGroup;  
12.import android.widget.BaseAdapter;  
13.import android.widget.ImageView;  
14.import android.widget.TextView;  
15.  
16.public class HorizontalListViewAdapter extends BaseAdapter{  
17.  
18.    public HorizontalListViewAdapter(Context con){  
19.        mInflater=LayoutInflater.from(con);  
20.    }  
21.    @Override  
22.    public int getCount() {  
23.        return 5;  
24.    }  
25.    private LayoutInflater mInflater;  
26.    @Override  
27.    public Object getItem(int position) {  
28.        return position;  
29.    }  
30.    private ViewHolder vh    =new ViewHolder();  
31.    private static class ViewHolder {  
32.        private TextView time ;  
33.        private TextView title ;  
34.        private ImageView im;  
35.    }  
36.    @Override  
37.    public long getItemId(int position) {  
38.        return position;  
39.    }  
40.  
41.    @Override  
42.    public View getView(int position, View convertView, ViewGroup parent) {  
43.        if(convertView==null){  
44.            convertView = mInflater.inflate(R.layout.horizontallistview_item, null);  
45.            vh.im=(ImageView)convertView.findViewById(R.id.iv_pic);  
46.            vh.time=(TextView)convertView.findViewById(R.id.tv_time);  
47.            vh.title=(TextView)convertView.findViewById(R.id.tv_name);  
48.            convertView.setTag(vh);  
49.        }else{  
50.            vh=(ViewHolder)convertView.getTag();  
51.        }  
52.        vh.time.setText("00:00");  
53.        vh.title.setText("XXXXXX");  
54.        return convertView;  
55.    }  
56.}  

http://blog.csdn.net/yanzi1225627/article/details/21294553
package org.com.cctest.listview;  
02.  
03./* 
04. * HorizontalListView.java v1.5 
05. * 
06. *  
07. * The MIT License 
08. * Copyright (c) 2011 Paul Soucy (paul@dev-smart.com) 
09. *  
10. * Permission is hereby granted, free of charge, to any person obtaining a copy 
11. * of this software and associated documentation files (the "Software"), to deal 
12. * in the Software without restriction, including without limitation the rights 
13. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
14. * copies of the Software, and to permit persons to whom the Software is 
15. * furnished to do so, subject to the following conditions: 
16. *  
17. * The above copyright notice and this permission notice shall be included in 
18. * all copies or substantial portions of the Software. 
19. *  
20. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
21. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
22. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
23. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
24. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
25. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
26. * THE SOFTWARE. 
27. * 
28. */  
29.  
30.  
31.import java.util.LinkedList;  
32.import java.util.Queue;  
33.  
34.import android.content.Context;  
35.import android.database.DataSetObserver;  
36.import android.graphics.Rect;  
37.import android.util.AttributeSet;  
38.import android.view.GestureDetector;  
39.import android.view.GestureDetector.OnGestureListener;  
40.import android.view.MotionEvent;  
41.import android.view.View;  
42.import android.widget.AdapterView;  
43.import android.widget.ListAdapter;  
44.import android.widget.Scroller;  
45.  
46.public class HorizontalListView extends AdapterView<ListAdapter> {  
47.  
48.    public boolean mAlwaysOverrideTouch = true;  
49.    protected ListAdapter mAdapter;  
50.    private int mLeftViewIndex = -1;  
51.    private int mRightViewIndex = 0;  
52.    protected int mCurrentX;  
53.    protected int mNextX;  
54.    private int mMaxX = Integer.MAX_VALUE;  
55.    private int mDisplayOffset = 0;  
56.    protected Scroller mScroller;  
57.    private GestureDetector mGesture;  
58.    private Queue<View> mRemovedViewQueue = new LinkedList<View>();  
59.    private OnItemSelectedListener mOnItemSelected;  
60.    private OnItemClickListener mOnItemClicked;  
61.    private OnItemLongClickListener mOnItemLongClicked;  
62.    private boolean mDataChanged = false;  
63.      
64.  
65.    public HorizontalListView(Context context, AttributeSet attrs) {  
66.        super(context, attrs);  
67.        initView();  
68.    }  
69.      
70.    private synchronized void initView() {  
71.        mLeftViewIndex = -1;  
72.        mRightViewIndex = 0;  
73.        mDisplayOffset = 0;  
74.        mCurrentX = 0;  
75.        mNextX = 0;  
76.        mMaxX = Integer.MAX_VALUE;  
77.        mScroller = new Scroller(getContext());  
78.        mGesture = new GestureDetector(getContext(), mOnGesture);  
79.    }  
80.      
81.    @Override  
82.    public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) {  
83.        mOnItemSelected = listener;  
84.    }  
85.      
86.    @Override  
87.    public void setOnItemClickListener(AdapterView.OnItemClickListener listener){  
88.        mOnItemClicked = listener;  
89.    }  
90.      
91.    @Override  
92.    public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) {  
93.        mOnItemLongClicked = listener;  
94.    }  
95.  
96.    private DataSetObserver mDataObserver = new DataSetObserver() {  
97.  
98.        @Override  
99.        public void onChanged() {  
100.            synchronized(HorizontalListView.this){  
101.                mDataChanged = true;  
102.            }  
103.            invalidate();  
104.            requestLayout();  
105.        }  
106.  
107.        @Override  
108.        public void onInvalidated() {  
109.            reset();  
110.            invalidate();  
111.            requestLayout();  
112.        }  
113.          
114.    };  
115.  
116.    @Override  
117.    public ListAdapter getAdapter() {  
118.        return mAdapter;  
119.    }  
120.  
121.    @Override  
122.    public View getSelectedView() {  
123.        //TODO: implement  
124.        return null;  
125.    }  
126.  
127.    @Override  
128.    public void setAdapter(ListAdapter adapter) {  
129.        if(mAdapter != null) {  
130.            mAdapter.unregisterDataSetObserver(mDataObserver);  
131.        }  
132.        mAdapter = adapter;  
133.        mAdapter.registerDataSetObserver(mDataObserver);  
134.        reset();  
135.    }  
136.      
137.    private synchronized void reset(){  
138.        initView();  
139.        removeAllViewsInLayout();  
140.        requestLayout();  
141.    }  
142.  
143.    @Override  
144.    public void setSelection(int position) {  
145.        //TODO: implement  
146.    }  
147.      
148.    private void addAndMeasureChild(final View child, int viewPos) {  
149.        LayoutParams params = child.getLayoutParams();  
150.        if(params == null) {  
151.            params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);  
152.        }  
153.  
154.        addViewInLayout(child, viewPos, params, true);  
155.        child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),  
156.                MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));  
157.    }  
158.      
159.      
160.  
161.    @Override  
162.    protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) {  
163.        super.onLayout(changed, left, top, right, bottom);  
164.  
165.        if(mAdapter == null){  
166.            return;  
167.        }  
168.          
169.        if(mDataChanged){  
170.            int oldCurrentX = mCurrentX;  
171.            initView();  
172.            removeAllViewsInLayout();  
173.            mNextX = oldCurrentX;  
174.            mDataChanged = false;  
175.        }  
176.  
177.        if(mScroller.computeScrollOffset()){  
178.            int scrollx = mScroller.getCurrX();  
179.            mNextX = scrollx;  
180.        }  
181.          
182.        if(mNextX <= 0){  
183.            mNextX = 0;  
184.            mScroller.forceFinished(true);  
185.        }  
186.        if(mNextX >= mMaxX) {  
187.            mNextX = mMaxX;  
188.            mScroller.forceFinished(true);  
189.        }  
190.          
191.        int dx = mCurrentX - mNextX;  
192.          
193.        removeNonVisibleItems(dx);  
194.        fillList(dx);  
195.        positionItems(dx);  
196.          
197.        mCurrentX = mNextX;  
198.          
199.        if(!mScroller.isFinished()){  
200.            post(new Runnable(){  
201.                @Override  
202.                public void run() {  
203.                    requestLayout();  
204.                }  
205.            });  
206.              
207.        }  
208.    }  
209.      
210.    private void fillList(final int dx) {  
211.        int edge = 0;  
212.        View child = getChildAt(getChildCount()-1);  
213.        if(child != null) {  
214.            edge = child.getRight();  
215.        }  
216.        fillListRight(edge, dx);  
217.          
218.        edge = 0;  
219.        child = getChildAt(0);  
220.        if(child != null) {  
221.            edge = child.getLeft();  
222.        }  
223.        fillListLeft(edge, dx);  
224.          
225.          
226.    }  
227.      
228.    private void fillListRight(int rightEdge, final int dx) {  
229.        while(rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) {  
230.              
231.            View child = mAdapter.getView(mRightViewIndex, mRemovedViewQueue.poll(), this);  
232.            addAndMeasureChild(child, -1);  
233.            rightEdge += child.getMeasuredWidth();  
234.              
235.            if(mRightViewIndex == mAdapter.getCount()-1) {  
236.                mMaxX = mCurrentX + rightEdge - getWidth();  
237.            }  
238.              
239.            if (mMaxX < 0) {  
240.                mMaxX = 0;  
241.            }  
242.            mRightViewIndex++;  
243.        }  
244.          
245.    }  
246.      
247.    private void fillListLeft(int leftEdge, final int dx) {  
248.        while(leftEdge + dx > 0 && mLeftViewIndex >= 0) {  
249.            View child = mAdapter.getView(mLeftViewIndex, mRemovedViewQueue.poll(), this);  
250.            addAndMeasureChild(child, 0);  
251.            leftEdge -= child.getMeasuredWidth();  
252.            mLeftViewIndex--;  
253.            mDisplayOffset -= child.getMeasuredWidth();  
254.        }  
255.    }  
256.      
257.    private void removeNonVisibleItems(final int dx) {  
258.        View child = getChildAt(0);  
259.        while(child != null && child.getRight() + dx <= 0) {  
260.            mDisplayOffset += child.getMeasuredWidth();  
261.            mRemovedViewQueue.offer(child);  
262.            removeViewInLayout(child);  
263.            mLeftViewIndex++;  
264.            child = getChildAt(0);  
265.              
266.        }  
267.          
268.        child = getChildAt(getChildCount()-1);  
269.        while(child != null && child.getLeft() + dx >= getWidth()) {  
270.            mRemovedViewQueue.offer(child);  
271.            removeViewInLayout(child);  
272.            mRightViewIndex--;  
273.            child = getChildAt(getChildCount()-1);  
274.        }  
275.    }  
276.      
277.    private void positionItems(final int dx) {  
278.        if(getChildCount() > 0){  
279.            mDisplayOffset += dx;  
280.            int left = mDisplayOffset;  
281.            for(int i=0;i<getChildCount();i++){  
282.                View child = getChildAt(i);  
283.                int childWidth = child.getMeasuredWidth();  
284.                child.layout(left, 0, left + childWidth, child.getMeasuredHeight());  
285.                left += childWidth + child.getPaddingRight();  
286.            }  
287.        }  
288.    }  
289.      
290.    public synchronized void scrollTo(int x) {  
291.        mScroller.startScroll(mNextX, 0, x - mNextX, 0);  
292.        requestLayout();  
293.    }  
294.      
295.    @Override  
296.    public boolean dispatchTouchEvent(MotionEvent ev) {  
297.        boolean handled = super.dispatchTouchEvent(ev);  
298.        handled |= mGesture.onTouchEvent(ev);  
299.        return handled;  
300.    }  
301.      
302.    protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,  
303.                float velocityY) {  
304.        synchronized(HorizontalListView.this){  
305.            mScroller.fling(mNextX, 0, (int)-velocityX, 0, 0, mMaxX, 0, 0);  
306.        }  
307.        requestLayout();  
308.          
309.        return true;  
310.    }  
311.      
312.    protected boolean onDown(MotionEvent e) {  
313.        mScroller.forceFinished(true);  
314.        return true;  
315.    }  
316.      
317.    private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() {  
318.  
319.        @Override  
320.        public boolean onDown(MotionEvent e) {  
321.            return HorizontalListView.this.onDown(e);  
322.        }  
323.  
324.        @Override  
325.        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,  
326.                float velocityY) {  
327.            return HorizontalListView.this.onFling(e1, e2, velocityX, velocityY);  
328.        }  
329.  
330.        @Override  
331.        public boolean onScroll(MotionEvent e1, MotionEvent e2,  
332.                float distanceX, float distanceY) {  
333.              
334.            synchronized(HorizontalListView.this){  
335.                mNextX += (int)distanceX;  
336.            }  
337.            requestLayout();  
338.              
339.            return true;  
340.        }  
341.  
342.        @Override  
343.        public boolean onSingleTapConfirmed(MotionEvent e) {  
344.            for(int i=0;i<getChildCount();i++){  
345.                View child = getChildAt(i);  
346.                if (isEventWithinView(e, child)) {  
347.                    if(mOnItemClicked != null){  
348.                        mOnItemClicked.onItemClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));  
349.                    }  
350.                    if(mOnItemSelected != null){  
351.                        mOnItemSelected.onItemSelected(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));  
352.                    }  
353.                    break;  
354.                }  
355.                  
356.            }  
357.            return true;  
358.        }  
359.          
360.        @Override  
361.        public void onLongPress(MotionEvent e) {  
362.            int childCount = getChildCount();  
363.            for (int i = 0; i < childCount; i++) {  
364.                View child = getChildAt(i);  
365.                if (isEventWithinView(e, child)) {  
366.                    if (mOnItemLongClicked != null) {  
367.                        mOnItemLongClicked.onItemLongClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i));  
368.                    }  
369.                    break;  
370.                }  
371.  
372.            }  
373.        }  
374.  
375.        private boolean isEventWithinView(MotionEvent e, View child) {  
376.            Rect viewRect = new Rect();  
377.            int[] childPosition = new int[2];  
378.            child.getLocationOnScreen(childPosition);  
379.            int left = childPosition[0];  
380.            int right = left + child.getWidth();  
381.            int top = childPosition[1];  
382.            int bottom = top + child.getHeight();  
383.            viewRect.set(left, top, right, bottom);  
384.            return viewRect.contains((int) e.getRawX(), (int) e.getRawY());  
385.        }  
386.    };  
387.  
388.      
389.  
390.}  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值