解决的问题有两个: 

1)实现水平滑动的ListView。重写AdapterView,上代码:

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

2)第一步实现了水平滑动,往往我们会把这个水平ListView放到ScrollView里面(见截图实现),而这两个控件恰好滑动会有冲突,滑动水平ListView时会有卡顿,因此重写ScrollView,以达到流畅滑动:

  1. package com.liucanwen.horizontallistview.view;
  2. import android.content.Context;
  3. import android.util.AttributeSet;
  4. import android.view.GestureDetector;
  5. import android.view.GestureDetector.SimpleOnGestureListener;
  6. import android.view.MotionEvent;
  7. import android.view.View;
  8. import android.widget.ScrollView;
  9. /**
  10. * 重写ScrollView,以解决ScrollView与水平listView滑动时冲突
  11. */
  12. public class MyScrollView extends ScrollView
  13. {
  14. private GestureDetector mGestureDetector;
  15. View.OnTouchListener mGestureListener;
  16. public MyScrollView(Context context, AttributeSet attrs)
  17. {
  18. super(context, attrs);
  19. mGestureDetector = new GestureDetector(new YScrollDetector());
  20. );
  21. }
  22. @Override
  23. public boolean onInterceptTouchEvent(MotionEvent ev)
  24. {
  25. return super.onInterceptTouchEvent(ev)
  26. && mGestureDetector.onTouchEvent(ev);
  27. }
  28. class YScrollDetector extends SimpleOnGestureListener
  29. {
  30. @Override
  31. public boolean onScroll(MotionEvent e1, MotionEvent e2,
  32. float distanceX, float distanceY)
  33. {
  34. if (Math.abs(distanceY) > Math.abs(distanceX))
  35. {
  36. return true;
  37. }
  38. return false;
  39. }
  40. }
  41. }

好了,大功告成! 

以下系项目的源代码下载地址: 

http://download.csdn.net/detail/qq15989177612/6943633

解决水平ListView在ScrollView中出现的滑动冲突的更多相关文章

  1. ListView在ScrollView中不显示全部的问题

    在实际应用中,我们可能会遇到把ListView放到ScrollView中的情况,在这种情况下,ListView的滑动属性与ScrollView的滑动出现冲突,从而ListView只显示一项.这里提供一 ...

  2. PullToRefreshListView中嵌套ViewPager滑动冲突的解决

    PullToRefreshListView中嵌套ViewPager滑动冲突的解决 最近恰好遇到PullToRefreshListView中需要嵌套ViewPager的情况,ViewPager 作为头部 ...

  3. 解决Android ListView 和 ScrollView 共存时冲突 问题 方法其一

    转载请注明出处: http://www.goteny.com/articles/2013/11/8.html http://www.cnblogs.com/zjjne/p/3428480.html 当 ...

  4. 解决嵌套在ScrollView中的TableView滑动手势冲突问题

    最近在迭代开发公司项目的时候遇到了一个问题,在可以左右切换标签视图的ScrollView中嵌套了两个TableView用于展示视图,感觉一切so easy的情况下,问题出现了,因为左右两个视图既可以实 ...

  5. 解决scrollView中嵌套viewPager的冲突问题

    很简单,在外层ScrollView中添加android:fillViewport="true"属性,然后给viewPager添加一个固定高度

  6. 解决ScrollView嵌套百度地图滑动冲突

    一.问题描述 scrollview中嵌套百度地图时会出现滑动冲突,地图无法滑动的情况. 二.期望结果 焦点在地图上时,只有地图移动,焦点在地图外部时,可以滑动scrollview. 三.解决方法 自定 ...

  7. [Android Pro] 完美解决隐藏Listview和RecyclerView去掉滚动条和滑动到边界阴影的方案

    reference to : http://blog.csdn.net/ming2316780/article/details/51578621 一.首先是Listview的属性设置 设置滑动到顶部和 ...

  8. H5使用Swiper过程中遇到的滑动冲突

    一.问题 (1)PC端可以鼠标可以拖动中间的轮子让页面上下滑动,点击左键按着也是拖不动 (2)手机端浏览H5手指不能滑动页面,导致很多页面下面的文字看不到 二.解决问题 1.下面分先说css的问题,主 ...

  9. Scrollview嵌套Recyclerview嵌套滑动冲突,导致滑动时会出现卡顿的现象

    recyclerView.setLayoutManager(new GridLayoutManager(mContext,2){ @Override public boolean canScrollV ...

随机推荐

  1. sybase isql命令参数详解

    isql 实用工具使您得以输入 Transact-SQL 语句.系统过程和脚本文件. 语法 isql [-?] | [-L] | [ { {-U login_id [-P password]} | - ...

  2. linux中exec和xargs命令的区别和优劣分析

    find的exec及ok命令 exec命令的格式为: exec command {} \; exec后面跟着的是操作命令,然后跟着{}表示每一个参数,然后空格,然后"\;".{}之 ...

  3. Struts 1之DispatchAction

    DispatchAction是struts 1 的内置通用分发器 import org.apache.struts.actions.DispatchAction; public class UserA ...

  4. Dynamics CRM2013 停用默认公共视图

    CRM视图中一般只会有一个默认公共视图,如果你不想用已有的默认视图只需新建个视图再指定默认,然后将原有视图停用即可,但我碰到了个另类的问题,即在一个实体下同时存在两个默认视图而且无法停用. 如下图中的 ...

  5. C语言中switch case语句可变参实现方法(case 参数 空格...空格 参数 :)

    正常情况下,switch case语句是这么写的: : : ... ;break ; default : ... ;break ; } 接下来说一种不常见的,但是对于多参数有很大的帮助的写法: 先给一 ...

  6. JDBC数据库连接简介(一)

    jdbc的由来 odbc(open database connection) 最初各个数据库比如mysql和oracle等,虽然都支持sql,但是他们的连接方式是不一样的,需要按照相应的api来编写不 ...

  7. 详解EBS接口开发之销售订单挑库发放

     1. 对销售订单的有效性验证     1)检查销售订单的行是否被完全传回客户化表     2)验证销售订单的关键字段     3)检查子库存是否启用了货位控制,如果启用了货位控制,没有生成货位, ...

  8. JS和Jquery操作label标签

    获取label值:  label标签在JS和Jquery中使用不能像其他标签一样用value获取它的值: 代码如下: var label=document.getElementById("s ...

  9. SSH深度历险(五) 深入浅出-----IOC AND AOP

    IOC就是Inversion of Control,控制反转.在Java开发中,IoC意味着将你设计好的类交给系统(容器)来控制实现,而不是在你的类内部控制.这称为控制反转. 本人理解:就是把原本你自 ...

  10. 后端分布式系列:分布式存储-MySQL 数据库事务与复制

    好久没有写技术文章了,因为一直在思考 「后端分布式」这个系列到底怎么写才合适.最近基本想清楚了,「后端分布式」包括「分布式存储」和 「分布式计算」两大类.结合实际工作中碰到的问题,以寻找答案的方式来剖 ...