zoukankan      html  css  js  c++  java
  • 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。

  • 相关阅读:
    基本MVVM 和 ICommand用法举例(转)
    WPF C# 命令的运行机制
    628. Maximum Product of Three Numbers
    605. Can Place Flowers
    581. Shortest Unsorted Continuous Subarray
    152. Maximum Product Subarray
    216. Combination Sum III
    448. Find All Numbers Disappeared in an Array
    268. Missing Number
    414. Third Maximum Number
  • 原文地址:https://www.cnblogs.com/all88/p/4136961.html
Copyright © 2011-2022 走看看