软件编程
位置:首页>> 软件编程>> Android编程>> Android中实现水平滑动(横向滑动)ListView示例

Android中实现水平滑动(横向滑动)ListView示例

作者:junjie  发布时间:2021-09-07 18:15:03 

标签:Android,水平滑动,横向滑动,ListView

水平的ListView-HorizontalListView的使用

Android中ListView默认的是竖直方向的滑动,由于项目的需求,需要ListView是水平滑动的。有很多的方式可以实现,但是比较好的一种方式就是自己封装一个控件,使用方式和ListView的使用方式是一样的。需要完善的地方:获取到的图片大小没有处理。在界面上展示的是图片的原大小。为了更好的展示效果,应该压缩成统一的尺寸。

HorizontalListView.java 代码如下:


/**
* 横向的ListView
*
* * @author scd
*
*/
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 + child.getPaddingRight();
     }
   }
 }

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());
   }
 };

}

适配器 HorizontalListViewAdapter .java如下:


public class HorizontalListViewAdapter extends BaseAdapter {  /** 上下文 */  private Context mContext;  /** 图像数据源 */  private ArrayList<Map<String, Integer>> mImageList;  /** 数据源 */  private ArrayList<Map<String, Integer>> mTextList;  /** Image */  private static String IMAGE = "ic_";  private Map<String, Integer> mMap = null;  /** 构造方法 */  public HorizontalListViewAdapter(Context context) {    this.mContext = context;    initData();  }  /** 初始化数据 */  public void initData() {    mImageList = new ArrayList<Map<String, Integer>>();    /*     * 反射技术     */    Class<?> imageClzz = R.drawable.class;    R.drawable instance = new R.drawable();    // 取得drawable类中所有的字段    Field[] fields = imageClzz.getDeclaredFields();    for (Field field : fields) {      // 获得字段的名字      String name = field.getName();      if (name != null && name.startsWith(IMAGE)) {        try {          mMap = new HashMap<String, Integer>();          mMap.put(IMAGE, (Integer) field.get(instance));          mImageList.add(mMap);        } catch (IllegalAccessException e) {          e.printStackTrace();        }      }    }  }  @Override  public int getCount() {    return mImageList.size();  }  @Override  public Map<String, Integer> getItem(int position) {    return mImageList == null ? null : mImageList.get(position);  }  @Override  public long getItemId(int position) {    return position;  }  @Override  public View getView(int position, View convertView, ViewGroup parent) {    ViewHolder holder;    if (convertView == null) {      holder = new ViewHolder();      convertView = LayoutInflater.from(mContext).inflate(          R.layout.horizontal_list_item, null);      holder.mImage = (ImageView) convertView          .findViewById(R.id.iv_list_item);      holder.mTitle = (TextView) convertView          .findViewById(R.id.tv_list_item);      convertView.setTag(holder);    } else {      holder = (ViewHolder) convertView.getTag();    }    if (position == mSelectIndex) {      convertView.setSelected(true);    } else {      convertView.setSelected(false);    }    holder.mImage.setImageResource(getItem(position).get(IMAGE));    return convertView;  }  private class ViewHolder {    /** 图像 */    private ImageView mImage;  }}

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com