解决水平ListView在ScrollView中出现的滑动冲突
解决的问题有两个:
1)实现水平滑动的ListView。重写AdapterView,上代码:
- package com.liucanwen.horizontallistview.view;
- import java.util.LinkedList;
- import java.util.Queue;
- import android.content.Context;
- import android.database.DataSetObserver;
- import android.graphics.Rect;
- import android.util.AttributeSet;
- import android.view.GestureDetector;
- import android.view.GestureDetector.OnGestureListener;
- import android.view.View.MeasureSpec;
- import android.view.MotionEvent;
- import android.view.View;
- import android.widget.AdapterView;
- import android.widget.ListAdapter;
- import android.widget.Scroller;
- /**
- * 重写ListView,以达到水平滑动
- */
- public class HorizontalListView extends AdapterView<ListAdapter>
- {
- public boolean mAlwaysOverrideTouch = true;
- protected ListAdapter mAdapter;
- ;
- ;
- protected int mCurrentX;
- protected int mNextX;
- private int mMaxX = Integer.MAX_VALUE;
- ;
- 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()
- {
- ;
- ;
- ;
- ;
- ;
- 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;
- }
- )
- {
- ;
- 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)
- {
- ;
- );
- if (child != null)
- {
- edge = child.getRight();
- }
- fillListRight(edge, dx);
- ;
- );
- 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);
- );
- rightEdge += child.getMeasuredWidth();
- )
- {
- mMaxX = mCurrentX + rightEdge - getWidth();
- }
- )
- {
- ;
- }
- mRightViewIndex++;
- }
- }
- private void fillListLeft(int leftEdge, final int dx)
- {
- && mLeftViewIndex >= 0)
- {
- View child = mAdapter.getView(mLeftViewIndex,
- mRemovedViewQueue.poll(), this);
- );
- leftEdge -= child.getMeasuredWidth();
- mLeftViewIndex--;
- mDisplayOffset -= child.getMeasuredWidth();
- }
- }
- private void removeNonVisibleItems(final int dx)
- {
- );
- )
- {
- mDisplayOffset += child.getMeasuredWidth();
- mRemovedViewQueue.offer(child);
- removeViewInLayout(child);
- mLeftViewIndex++;
- );
- }
- );
- while (child != null && child.getLeft() + dx >= getWidth())
- {
- mRemovedViewQueue.offer(child);
- removeViewInLayout(child);
- mRightViewIndex--;
- );
- }
- }
- private void positionItems(final int dx)
- {
- )
- {
- mDisplayOffset += dx;
- int left = mDisplayOffset;
- ; i < getChildCount(); i++)
- {
- View child = getChildAt(i);
- int childWidth = child.getMeasuredWidth();
- , left + childWidth,
- child.getMeasuredHeight());
- left += childWidth + child.getPaddingRight();
- }
- }
- }
- public synchronized void scrollTo(int x)
- {
- , 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)
- {
- , (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)
- {
- ; i < getChildCount(); i++)
- {
- View child = getChildAt(i);
- if (isEventWithinView(e, child))
- {
- if (mOnItemClicked != null)
- {
- mOnItemClicked.onItemClick(HorizontalListView.this,
- + i,
- + i));
- }
- if (mOnItemSelected != null)
- {
- mOnItemSelected.onItemSelected(HorizontalListView.this,
- + i,
- + i));
- }
- break;
- }
- }
- return true;
- }
- @Override
- public void onLongPress(MotionEvent e)
- {
- int childCount = getChildCount();
- ; i < childCount; i++)
- {
- View child = getChildAt(i);
- if (isEventWithinView(e, child))
- {
- if (mOnItemLongClicked != null)
- {
- mOnItemLongClicked.onItemLongClick(
- HorizontalListView.this, child, mLeftViewIndex
- + i,
- + i));
- }
- break;
- }
- }
- }
- private boolean isEventWithinView(MotionEvent e, View child)
- {
- Rect viewRect = new Rect();
- ];
- child.getLocationOnScreen(childPosition);
- ];
- int right = left + child.getWidth();
- ];
- int bottom = top + child.getHeight();
- viewRect.set(left, top, right, bottom);
- return viewRect.contains((int) e.getRawX(), (int) e.getRawY());
- }
- };
- }
2)第一步实现了水平滑动,往往我们会把这个水平ListView放到ScrollView里面(见截图实现),而这两个控件恰好滑动会有冲突,滑动水平ListView时会有卡顿,因此重写ScrollView,以达到流畅滑动:
- package com.liucanwen.horizontallistview.view;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.view.GestureDetector;
- import android.view.GestureDetector.SimpleOnGestureListener;
- import android.view.MotionEvent;
- import android.view.View;
- import android.widget.ScrollView;
- /**
- * 重写ScrollView,以解决ScrollView与水平listView滑动时冲突
- */
- public class MyScrollView extends ScrollView
- {
- private GestureDetector mGestureDetector;
- View.OnTouchListener mGestureListener;
- public MyScrollView(Context context, AttributeSet attrs)
- {
- super(context, attrs);
- mGestureDetector = new GestureDetector(new YScrollDetector());
- );
- }
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev)
- {
- return super.onInterceptTouchEvent(ev)
- && mGestureDetector.onTouchEvent(ev);
- }
- class YScrollDetector extends SimpleOnGestureListener
- {
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2,
- float distanceX, float distanceY)
- {
- if (Math.abs(distanceY) > Math.abs(distanceX))
- {
- return true;
- }
- return false;
- }
- }
- }
好了,大功告成!
以下系项目的源代码下载地址:
http://download.csdn.net/detail/qq15989177612/6943633
解决水平ListView在ScrollView中出现的滑动冲突的更多相关文章
- ListView在ScrollView中不显示全部的问题
在实际应用中,我们可能会遇到把ListView放到ScrollView中的情况,在这种情况下,ListView的滑动属性与ScrollView的滑动出现冲突,从而ListView只显示一项.这里提供一 ...
- PullToRefreshListView中嵌套ViewPager滑动冲突的解决
PullToRefreshListView中嵌套ViewPager滑动冲突的解决 最近恰好遇到PullToRefreshListView中需要嵌套ViewPager的情况,ViewPager 作为头部 ...
- 解决Android ListView 和 ScrollView 共存时冲突 问题 方法其一
转载请注明出处: http://www.goteny.com/articles/2013/11/8.html http://www.cnblogs.com/zjjne/p/3428480.html 当 ...
- 解决嵌套在ScrollView中的TableView滑动手势冲突问题
最近在迭代开发公司项目的时候遇到了一个问题,在可以左右切换标签视图的ScrollView中嵌套了两个TableView用于展示视图,感觉一切so easy的情况下,问题出现了,因为左右两个视图既可以实 ...
- 解决scrollView中嵌套viewPager的冲突问题
很简单,在外层ScrollView中添加android:fillViewport="true"属性,然后给viewPager添加一个固定高度
- 解决ScrollView嵌套百度地图滑动冲突
一.问题描述 scrollview中嵌套百度地图时会出现滑动冲突,地图无法滑动的情况. 二.期望结果 焦点在地图上时,只有地图移动,焦点在地图外部时,可以滑动scrollview. 三.解决方法 自定 ...
- [Android Pro] 完美解决隐藏Listview和RecyclerView去掉滚动条和滑动到边界阴影的方案
reference to : http://blog.csdn.net/ming2316780/article/details/51578621 一.首先是Listview的属性设置 设置滑动到顶部和 ...
- H5使用Swiper过程中遇到的滑动冲突
一.问题 (1)PC端可以鼠标可以拖动中间的轮子让页面上下滑动,点击左键按着也是拖不动 (2)手机端浏览H5手指不能滑动页面,导致很多页面下面的文字看不到 二.解决问题 1.下面分先说css的问题,主 ...
- Scrollview嵌套Recyclerview嵌套滑动冲突,导致滑动时会出现卡顿的现象
recyclerView.setLayoutManager(new GridLayoutManager(mContext,2){ @Override public boolean canScrollV ...
随机推荐
- leetcode 3 Longest Substring Without Repeating Characters最长无重复子串
Given a string, find the length of the longest substring without repeating characters. For example, ...
- Android必知必会-获取视频文件的截图、缩略图
背景 公司最近要求给我负责的APP加上视频录制和发布的功能,我简单的完成了基本的录制和视频压缩功能,后来发现发布接口需要上传视频的截图,网上搜索了一下资料,在这里整理一下. 代码实现 /** * 获取 ...
- PGM:概率图模型Graphical Model
http://blog.csdn.net/pipisorry/article/details/51461878 概率图模型Graphical Models简介 完全通过代数计算来对更加复杂的模型进行建 ...
- C语言获取文件大小
C语言是一种比较底层的语言,有时在其他语言中很容易操作的事情,在C语言中就比较麻烦,例如获取一个文件的大小.Java中File类有个length函数,Python中os.path包中有个getsize ...
- 仿IOS7日期选择控件(新)
前面也写过好几篇仿IOS日期控件的文章,不过基本上都是基于Wheelview修改而来,大致实现了滑轮选择选项的效果,其实和ios7及以上的效果还是相差甚远,而本文中所展现的这个控件虽也是从网上而来(呵 ...
- UNIX网络编程——分析一帧基于UDP的TFTP协议帧
下图是UDP的段格式: 相比TCP段格式,UDP要简单得多,也没啥好说的,需要注意的是UDP数据长度指payload加上首部的长度. 下面分析一帧基于UDP的TFTP协议帧: 以太网首部 0000: ...
- EBS Form个性化的工作原理
Form的个性化是EBS的比较好用的一个东西.好像很少人研究它的工作原理,都是直接用.最近有个同事问我问题,说他在个性化编写的代码无效果.解决之后,才发现,原来传说中的EBS的Form的个性化是这样子 ...
- SVM 使用朗格朗日乘子得到权重向量
紧跟前一篇SVM博文,下面我们用数学推导来导出权重的计算方法.
- oracle ebs应用产品安全性-安全性规则
定义: 通过为段指定包括下限值与上限值的值范围,可以定义安全性规则要素.安全性规则要素适用于包括在指定值范围内的所有段值. 可以将每个安全性规则要素标识为"包括"或"排除 ...
- Java进阶(二十七)使用Dom4j解析XML文件
使用Dom4j解析XML文件 写在前面的话 由于论文实验要求,需要实现操作XML文档,为此想到了dom4j这个工具,使用之后深感受益.在此分享给大家,以此共勉. 注:本文转载自http://blog. ...