• Android横向ListView


    在项目开发中,竖向的listview我们经常用到,但是在特殊情况下,我们需要使用横向的listview,所以一下就是一个

    自定义的横向listview,希望对有需要的人有帮助。

    自定义的横向listview

      1 package com.qdsj.jhongbao.view;
      2 
      3 import java.util.LinkedList;
      4 import java.util.Queue;
      5 
      6 import android.content.Context;
      7 import android.database.DataSetObserver;
      8 import android.graphics.Rect;
      9 import android.util.AttributeSet;
     10 import android.view.GestureDetector;
     11 import android.view.GestureDetector.OnGestureListener;
     12 import android.view.MotionEvent;
     13 import android.view.View;
     14 import android.widget.AdapterView;
     15 import android.widget.ListAdapter;
     16 import android.widget.Scroller;
     17 //com.xiaojian.frame.widgets.HorizontalListView
     18 public class HorizontalListView extends AdapterView<ListAdapter> {
     19      
     20     public boolean mAlwaysOverrideTouch = true;
     21     protected ListAdapter mAdapter;
     22     private int mLeftViewIndex = -1;
     23     private int mRightViewIndex = 0;
     24     protected int mCurrentX;
     25     protected int mNextX;
     26     private int mMaxX = Integer.MAX_VALUE;
     27     private int mDisplayOffset = 0;
     28     protected Scroller mScroller;
     29     private GestureDetector mGesture;
     30     private Queue<View> mRemovedViewQueue = new LinkedList<View>();
     31     private OnItemSelectedListener mOnItemSelected;
     32     private OnItemClickListener mOnItemClicked;
     33     private OnItemLongClickListener mOnItemLongClicked;
     34     private boolean mDataChanged = false;
     35      
     36 
     37     public HorizontalListView(Context context, AttributeSet attrs) {
     38             super(context, attrs);
     39             initView();
     40     }
     41      
     42     private synchronized void initView() {
     43             mLeftViewIndex = -1;
     44             mRightViewIndex = 0;
     45             mDisplayOffset = 0;
     46             mCurrentX = 0;
     47             mNextX = 0;
     48             mMaxX = Integer.MAX_VALUE;
     49             mScroller = new Scroller(getContext());
     50             mGesture = new GestureDetector(getContext(), mOnGesture);
     51     }
     52      
     53     @Override
     54     public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) {
     55             mOnItemSelected = listener;
     56     }
     57      
     58     @Override
     59     public void setOnItemClickListener(AdapterView.OnItemClickListener listener){
     60             mOnItemClicked = listener;
     61     }
     62      
     63     @Override
     64     public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) {
     65             mOnItemLongClicked = listener;
     66     }
     67 
     68     private DataSetObserver mDataObserver = new DataSetObserver() {
     69             @Override
     70             public void onChanged() {
     71                     synchronized(HorizontalListView.this){
     72                             mDataChanged = true;
     73                     }
     74                     invalidate();
     75                     requestLayout();
     76             }
     77             @Override
     78             public void onInvalidated() {
     79                     reset();
     80                     invalidate();
     81                     requestLayout();
     82             }
     83     };
     84 
     85     @Override
     86     public ListAdapter getAdapter() {
     87             return mAdapter;
     88     }
     89 
     90     @Override
     91     public View getSelectedView() {
     92             //TODO: implement
     93             return null;
     94     }
     95 
     96     @Override
     97     public void setAdapter(ListAdapter adapter) {
     98             if(mAdapter != null) {
     99                     mAdapter.unregisterDataSetObserver(mDataObserver);
    100             }
    101             mAdapter = adapter;
    102             mAdapter.registerDataSetObserver(mDataObserver);
    103             reset();
    104     }
    105      
    106     private synchronized void reset(){
    107             initView();
    108             removeAllViewsInLayout();
    109             requestLayout();
    110     }
    111 
    112     @Override
    113     public void setSelection(int position) {
    114             //TODO: implement
    115         
    116     }
    117      
    118     private void addAndMeasureChild(final View child, int viewPos) {
    119             LayoutParams params = child.getLayoutParams();
    120             if(params == null) {
    121                     params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
    122             }
    123 
    124             addViewInLayout(child, viewPos, params, true);
    125             child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
    126                             MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
    127     }
    128      
    129     @Override
    130     protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) {
    131             super.onLayout(changed, left, top, right, bottom);
    132 
    133             if(mAdapter == null){
    134                     return;
    135             }
    136             if(mDataChanged){
    137                     int oldCurrentX = mCurrentX;
    138                     initView();
    139                     removeAllViewsInLayout();
    140                     mNextX = oldCurrentX;
    141                     mDataChanged = false;
    142             }
    143             if(mScroller.computeScrollOffset()){
    144                     int scrollx = mScroller.getCurrX();
    145                     mNextX = scrollx;
    146             }
    147             if(mNextX <= 0){
    148                     mNextX = 0;
    149                     mScroller.forceFinished(true);
    150             }
    151             if(mNextX >= mMaxX) {
    152                     mNextX = mMaxX;
    153                     mScroller.forceFinished(true);
    154             }
    155             int dx = mCurrentX - mNextX;
    156             removeNonVisibleItems(dx);
    157             fillList(dx);
    158             positionItems(dx);
    159             mCurrentX = mNextX;
    160             if(!mScroller.isFinished()){
    161                     post(new Runnable(){
    162                             @Override
    163                             public void run() {
    164                                     requestLayout();
    165                             }
    166                     });
    167             }
    168     }
    169      
    170     private void fillList(final int dx) {
    171             int edge = 0;
    172             View child = getChildAt(getChildCount()-1);
    173             if(child != null) {
    174                     edge = child.getRight();
    175             }
    176             fillListRight(edge, dx);
    177              
    178             edge = 0;
    179             child = getChildAt(0);
    180             if(child != null) {
    181                     edge = child.getLeft();
    182             }
    183             fillListLeft(edge, dx);
    184              
    185              
    186     }
    187      
    188     private void fillListRight(int rightEdge, final int dx) {
    189             while(rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) {
    190                      
    191                     View child = mAdapter.getView(mRightViewIndex, mRemovedViewQueue.poll(), this);
    192                     addAndMeasureChild(child, -1);
    193                     rightEdge += child.getMeasuredWidth();
    194                      
    195                     if(mRightViewIndex == mAdapter.getCount()-1) {
    196                             mMaxX = mCurrentX + rightEdge - getWidth();
    197                     }
    198                      
    199                     if (mMaxX < 0) {
    200                             mMaxX = 0;
    201                     }
    202                     mRightViewIndex++;
    203             }
    204              
    205     }
    206      
    207     private void fillListLeft(int leftEdge, final int dx) {
    208             while(leftEdge + dx > 0 && mLeftViewIndex >= 0) {
    209                     View child = mAdapter.getView(mLeftViewIndex, mRemovedViewQueue.poll(), this);
    210                     addAndMeasureChild(child, 0);
    211                     leftEdge -= child.getMeasuredWidth();
    212                     mLeftViewIndex--;
    213                     mDisplayOffset -= child.getMeasuredWidth();
    214             }
    215     }
    216      
    217     private void removeNonVisibleItems(final int dx) {
    218             View child = getChildAt(0);
    219             while(child != null && child.getRight() + dx <= 0) {
    220                     mDisplayOffset += child.getMeasuredWidth();
    221                     mRemovedViewQueue.offer(child);
    222                     removeViewInLayout(child);
    223                     mLeftViewIndex++;
    224                     child = getChildAt(0);
    225                      
    226             }
    227              
    228             child = getChildAt(getChildCount()-1);
    229             while(child != null && child.getLeft() + dx >= getWidth()) {
    230                     mRemovedViewQueue.offer(child);
    231                     removeViewInLayout(child);
    232                     mRightViewIndex--;
    233                     child = getChildAt(getChildCount()-1);
    234             }
    235     }
    236      
    237     private void positionItems(final int dx) {
    238             if(getChildCount() > 0){
    239                     mDisplayOffset += dx;
    240                     int left = mDisplayOffset;
    241                     for(int i=0;i<getChildCount();i++){
    242                             View child = getChildAt(i);
    243                             int childWidth = child.getMeasuredWidth();
    244                             child.layout(left, 0, left + childWidth, child.getMeasuredHeight());
    245                             left += childWidth + child.getPaddingRight();
    246                     }
    247             }
    248     }
    249      
    250     public synchronized void scrollTo(int x) {
    251             mScroller.startScroll(mNextX, 0, x - mNextX, 0);
    252             requestLayout();
    253     }
    254      
    255     @Override
    256     public boolean dispatchTouchEvent(MotionEvent ev) {
    257             boolean handled = super.dispatchTouchEvent(ev);
    258             handled |= mGesture.onTouchEvent(ev);
    259             return handled;
    260     }
    261      
    262     protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
    263                             float velocityY) {
    264             synchronized(HorizontalListView.this){
    265                     mScroller.fling(mNextX, 0, (int)-velocityX, 0, 0, mMaxX, 0, 0);
    266             }
    267             requestLayout();
    268              
    269             return true;
    270     }
    271      
    272     protected boolean onDown(MotionEvent e) {
    273             mScroller.forceFinished(true);
    274             return true;
    275     }
    276      
    277     private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() {
    278 
    279             @Override
    280             public boolean onDown(MotionEvent e) {
    281                     return HorizontalListView.this.onDown(e);
    282             }
    283 
    284             @Override
    285             public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
    286                             float velocityY) {
    287                     return HorizontalListView.this.onFling(e1, e2, velocityX, velocityY);
    288             }
    289 
    290             @Override
    291             public boolean onScroll(MotionEvent e1, MotionEvent e2,
    292                             float distanceX, float distanceY) {
    293                      
    294                     synchronized(HorizontalListView.this){
    295                             mNextX += (int)distanceX;
    296                     }
    297                     requestLayout();
    298                      
    299                     return true;
    300             }
    301 
    302             @Override
    303             public boolean onSingleTapConfirmed(MotionEvent e) {
    304                     for(int i=0;i<getChildCount();i++){
    305                             View child = getChildAt(i);
    306                             if (isEventWithinView(e, child)) {
    307                                     if(mOnItemClicked != null){
    308                                             mOnItemClicked.onItemClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));
    309                                     }
    310                                     if(mOnItemSelected != null){
    311                                             mOnItemSelected.onItemSelected(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));
    312                                     }
    313                                     break;
    314                             }
    315                              
    316                     }
    317                     return true;
    318             }
    319              
    320             @Override
    321             public void onLongPress(MotionEvent e) {
    322                     int childCount = getChildCount();
    323                     for (int i = 0; i < childCount; i++) {
    324                             View child = getChildAt(i);
    325                             if (isEventWithinView(e, child)) {
    326                                     if (mOnItemLongClicked != null) {
    327                                             mOnItemLongClicked.onItemLongClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i));
    328                                     }
    329                                     break;
    330                             }
    331 
    332                     }
    333             }
    334 
    335        private boolean isEventWithinView(MotionEvent e, View child) {
    336         Rect viewRect = new Rect();
    337         int[] childPosition = new int[2];
    338         child.getLocationOnScreen(childPosition);
    339         int left = childPosition[0];
    340         int right = left + child.getWidth();
    341         int top = childPosition[1];
    342         int bottom = top + child.getHeight();
    343         viewRect.set(left, top, right, bottom);
    344         return viewRect.contains((int) e.getRawX(), (int) e.getRawY());
    345     }
    346     };
    347 
    348      
    349 
    350 }

    在布局文件中应用该自定义的横向listview,然后和listview一样设置Adapter,这样就生成了一个横向的listview。

  • 相关阅读:
    Storm:分布式流式计算框架
    GreenPlum:基于PostgreSQL的分布式关系型数据库
    Hive和SparkSQL: 基于 Hadoop 的数据仓库工具
    Linux网络子系统
    Python标准模块--multiprocessing
    Python标准模块--built-ins函数
    Python标准模块--threading
    Python标准模块--import
    Python标准模块--os
    Python标准模块--argparse
  • 原文地址:https://www.cnblogs.com/all88/p/4136961.html
Copyright © 2020-2023  润新知