首页 > 其他分享 >横向滑动的ListView

横向滑动的ListView

时间:2023-04-06 21:37:58浏览次数:37  
标签:int void 横向 private dx child 滑动 ListView public

我通常把GridView设置成1行来代替横向的listview了,呵呵。
下面这个类留着以后试试。

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

        

}




Android Horizontal ListView


http://www.dev-smart.com/archives/34


标签:int,void,横向,private,dx,child,滑动,ListView,public
From: https://blog.51cto.com/u_5454003/6174161

相关文章

  • 运用手势操作ListView中的Item
    如下面这个图:需要实现的功能是:用手指在某条记录上从左往右划一下,出现一条横线,用于表示这个菜已经上过了;倒过来划,取消这条横线,表示这个菜没上过。如何实现呢?看我的吧!首先需要一个Item的布局,在布局的最上方有一个ImageView用于显示这条横线,如果没有就把这个I......
  • 分别设置listview加载中、空数据、加载数据失败三种状态的显示
    设置listview加载中,空数据,加载数据失败三种状态的显示.基本用法:importjava.util.ArrayList;importjava.util.Arrays;importcom.kanak.emptylayout.EmptyLayout;importandroid.os.Bundle;importandroid.view.View;importandroid.view.View.OnCl......
  • 在ListView上滑动显示Delete按钮
    SwipeLayout实现listview滑动删除功能http://www.devstore.cn/code/info/579.html首先设置listView.setOnTouchListener(onTouchListener);listView=(ListView)findViewById(R.id.listView);listView.setOnItemClickListener(onItemClickListener);li......
  • ListView之setEmptyView的问题
    使用listView或者gridView时,当列表为空时,有时需要显示一个特殊的emptyview来提示用户,一般情况下,如果你是继承ListActivity,只要<ListViewandroid:id="@id/android:list".../><TextViewandroid:id="@id/android:empty.../>当列表为空时就会自动显示Tex......
  • HJ64_MP3光标位置_数组_模拟思路_滑动窗口
    思路:用模拟跟踪U、D得输出的歌曲,用双指针跟踪歌曲当前窗口。注意,在第一首向上滑动,和最后一首向下滑是,窗口特殊跳动,此时双指针指向特殊处理。留意到,不管是特殊情况还是普通情况,指针上划时歌曲减一。如1调到10,10上划为9,视为减一。得到代码如下:importsysa=int(sys.stdin.......
  • 773. 滑动谜题
    题目描述数字华容道,只有6个数字问把0换到最后最少需要多少步?f1-构建状态表示的mask+bfs基本分析bfs的时候,当前状态怎么表示?把矩阵拉平,变成字符串怎么快速可以得到某个字符串可以变成哪些字符串?(1)怎么快速知道不同情况下0周围的索引?枚举余处理(2)怎么知道不同mask对应的可......
  • 直播小程序源码,小程序页面左右滑动如何解决
    直播小程序源码,小程序页面左右滑动如何解决1、css解决//最外层父元素 width:100%;overflow-x:hidden;​2、pages.json中配置     {"path":"platforms/mp-weixin/mine/mine","style":{          //disableScroll:控制当前页面不可滑动"disabl......
  • 力扣-数组-滑动窗口
    题目顺序209长度最小的子数组,904水果成篮解题思路1.滑动窗口求解的题目中,关键词为”求解连续“2.暴力解法是双重for循环,相当于对滑动窗口的起始和终止点都遍历3.滑动窗口求解是,只遍历终止点,当sum符合条件时,start++,向前一步缩小窗口4.终止条件是终止点end遍历完  1c......
  • C语言中的窗口滑动技术
    学习文章:C语言中的窗口滑动技术C语言中的窗口滑动技术循环几乎是每个复杂问题的一部分。太多的循环/嵌套循环会增加所需的时间,从而增加程序的时间复杂性。窗口滑动技术是一种计算技术,用于减少程序中使用的嵌套循环的数量,通过用单个循环代替嵌套循环来提高程序的效率。如果......
  • 滑动窗口-leetcode344-反转字符出啊
    编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用O(1)的额外空间解决这一问题。示例1:输入:s=["h","e","l","l","o"]输出:["o","l","l","e","h"]示例......