首页 > 系统 > Android > 正文

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

2019-10-24 21:12:35
字体:
来源:转载
供稿:网友

这篇文章主要介绍了Android中实现水平滑动(横向滑动)ListView示例,本文用自己封装一个控件的方法解决了这个需求,需要的朋友可以参考下

水平的ListView-HorizontalListView的使用

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

HorizontalListView.java 代码如下:

 

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

适配器 HorizontalListViewAdapter .java如下:

 

 
  1. public class HorizontalListViewAdapter extends BaseAdapter { 
  2. /** 上下文 */ 
  3. private Context mContext; 
  4. /** 图像数据源 */ 
  5. private ArrayList<Map<String, Integer>> mImageList; 
  6.  
  7. /** 数据源 */ 
  8. private ArrayList<Map<String, Integer>> mTextList; 
  9. /** Image */ 
  10. private static String IMAGE = "ic_"
  11.  
  12. private Map<String, Integer> mMap = null
  13.  
  14. /** 构造方法 */ 
  15. public HorizontalListViewAdapter(Context context) { 
  16. this.mContext = context; 
  17. initData(); 
  18.  
  19. /** 初始化数据 */ 
  20. public void initData() { 
  21. mImageList = new ArrayList<Map<String, Integer>>(); 
  22. /* 
  23. * 反射技术 
  24. */ 
  25. Class<?> imageClzz = R.drawable.class
  26. R.drawable instance = new R.drawable(); 
  27. // 取得drawable类中所有的字段 
  28. Field[] fields = imageClzz.getDeclaredFields(); 
  29. for (Field field : fields) { 
  30. // 获得字段的名字 
  31. String name = field.getName(); 
  32. if (name != null && name.startsWith(IMAGE)) { 
  33. try { 
  34. mMap = new HashMap<String, Integer>(); 
  35. mMap.put(IMAGE, (Integer) field.get(instance)); 
  36. mImageList.add(mMap); 
  37. catch (IllegalAccessException e) { 
  38. e.printStackTrace(); 
  39.  
  40.  
  41.  
  42. @Override 
  43. public int getCount() { 
  44. return mImageList.size(); 
  45.  
  46. @Override 
  47. public Map<String, Integer> getItem(int position) { 
  48.  
  49. return mImageList == null ? null : mImageList.get(position); 
  50.  
  51. @Override 
  52. public long getItemId(int position) { 
  53. return position; 
  54.  
  55. @Override 
  56. public View getView(int position, View convertView, ViewGroup parent) { 
  57.  
  58. ViewHolder holder; 
  59. if (convertView == null) { 
  60. holder = new ViewHolder(); 
  61. convertView = LayoutInflater.from(mContext).inflate( 
  62. R.layout.horizontal_list_item, null); 
  63. holder.mImage = (ImageView) convertView 
  64. .findViewById(R.id.iv_list_item); 
  65. holder.mTitle = (TextView) convertView 
  66. .findViewById(R.id.tv_list_item); 
  67. convertView.setTag(holder); 
  68. else { 
  69. holder = (ViewHolder) convertView.getTag(); 
  70.  
  71. if (position == mSelectIndex) { 
  72. convertView.setSelected(true); 
  73. else { 
  74. convertView.setSelected(false); 
  75. holder.mImage.setImageResource(getItem(position).get(IMAGE)); 
  76. return convertView; 
  77.  
  78. private class ViewHolder { 
  79. /** 图像 */ 
  80. private ImageView mImage; 

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表