• 浅谈网上的zoomlistview存在的问题


      最近项目主要是做一个类似wps文档阅历的功能,以列表的形式显示文档,并且需要实现缩放平移。而网上关于此类功能的实现主要是通过自定义的listview实现的,类名为ZoomListView。

      网上的zoomlistview模板大多是一套,主要核心代码就是以下:

     @Override
        protected void dispatchDraw(Canvas canvas) {
            canvas.save(Canvas.MATRIX_SAVE_FLAG);
            if (mScaleFactor == 1.0f) {
                mPosX = 0.0f;
                mPosY = 0.0f;
            }
            canvas.translate(mPosX, mPosY);
            canvas.scale(mScaleFactor, mScaleFactor);
            super.dispatchDraw(canvas);
            canvas.restore();
            invalidate();
        }

      该函数主要实现了对整体列表的缩放和平移。但是mPosY的值影响了判断当前显示的第一个item,而且当你惯性滑动时,永远滑不到底。所以如何解决这两个问题呢。

      解决第一个问题很简单,canvas.translate(mPosX,0),就可以了。而此时由于没有了纵向的平移,列表肯定会显示不全了。

      如何解决列表显示不全的问题呢。究其原因是因为滚动条滚不到底的原因。由于此时网上也没有这方面的资料,写ZoomListView的大佬也找不到本人,后来的人估计也是copy然后写文章的,问他们其实也都不知道。于是我决定自己看源码解决问题。

      根据代码跟踪发现了滚动的时候会调用trackMotionScroll函数,其中有这么一串代码:

            final boolean cannotScrollDown = (firstPosition == 0 &&
                    firstTop >= listPadding.top && incrementalDeltaY >= 0);
            final boolean cannotScrollUp = (firstPosition + childCount == mItemCount &&
                    lastBottom <= getHeight() - listPadding.bottom && incrementalDeltaY <= 0);
    
            if (cannotScrollDown || cannotScrollUp) {
                return incrementalDeltaY != 0;
            }

       其中cannotScrollUp就是不能向下滚动。看这个式子有没有发现什么问题,判断不能向下滚动的条件是lastBottom <= getHeight() - listPadding.botoom。于是我突发奇想设置paddingbottom的值就好了。设置paddingbottom为对应值后,发现真的可以滚动了,太棒了,问题基本上解决了。

      后来发现又有bug了,在paddingbottom部分居然不能滚动!不能滚动!不能滚动!!!哎,详细也正常,padingbottom本来就是不能滚动的,这时候怎么办呢。然后调试进入ontouchevent函数中,发现触摸该区域其实还是可以会调touchevent事件的。于是我有想到了一个奇妙的方法去解决问题。自己在touchevent中先对ev的y值进行位移,这样该区域就可以滚动了。

      终于解决问题了,经过这一次我明白了一个道理,当你遇到问题的时候,一定要解析问题所在,然后跟踪深入源码,只有知道底层代码才能更好的解决问题。

      想要源码的可以评论,在这里就不贴了。

      这几天又来了一个需求,如何保证中心缩放。这个就有点难了,如何在这个类上修改呢。第一步就是需要优化在双指缩放的时候不能平移画布。这个问题横向的时候好解决,只要判断是否是单指就行了。横向的时候就需要禁用滚动来判断,函数setenable。

      第二步就是找推导公式,进行算出新的平移。以下是纵向调整平移的代码。

                //求y0的推导公式,view是对应中心点item的view。
                /*
                (view.top + y0)*mOldScaleFactor = cy;
                (view.top(新)+y0)*mScaleFactor = cy;
                先求出view.top(新),然后计算出view.top(新)与view.top之间的差。
                然后求得firstitem的view.top(新的值),最后通过setSelectionFromTop滚动到对应区域
                 */
                int iFirstItem = getFirstVisiblePosition();
                int iFirstViewTop = 0;
                for(int iCnt=0;iCnt<getChildCount();++iCnt)
                {
                    View view = getChildAt(iCnt);
                    if(0==iCnt)
                    {
                        iFirstViewTop = view.getTop();
                    }
                    int iViewTop = (int)(view.getTop()*mOldScaleFactor);
                    int iViewBottom = (int)(view.getBottom()*mOldScaleFactor);
                    if(iViewTop<=cy && cy<=iViewBottom)
                    {
                        int iNewViewTop = (int)(cy/mScaleFactor - (cy/mOldScaleFactor-iViewTop));
                        int iNewFirstViewTop = iFirstViewTop + (iNewViewTop-iViewTop);
                        if(0==iFirstItem && iNewFirstViewTop>=0)
                        {
                            iNewFirstViewTop = 0;
                        }
                        setSelectionFromTop(iFirstItem,iNewFirstViewTop);
                        break;
                    }
                }

    主要要算出当前点会平移多少,然后通过setSelectionFromTop来校准。终于经过千辛万苦,把缩放的listview完成的总算可以了!!!

  • 相关阅读:
    常用知识点集合
    LeetCode 66 Plus One
    LeetCode 88 Merge Sorted Array
    LeetCode 27 Remove Element
    LeetCode 26 Remove Duplicates from Sorted Array
    LeetCode 448 Find All Numbers Disappeared in an Array
    LeetCode 219 Contains Duplicate II
    LeetCode 118 Pascal's Triangle
    LeetCode 119 Pascal's Triangle II
    LeetCode 1 Two Sum
  • 原文地址:https://www.cnblogs.com/jlyg/p/10852909.html
Copyright © 2020-2023  润新知