• 浅谈网上的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完成的总算可以了!!!

  • 相关阅读:
    HDU 1175 连连看 (DFS+剪枝)
    CF702F T-Shirts
    UVA12538 Version Controlled IDE
    P2605 [ZJOI2010]基站选址
    P3835 【模板】可持久化平衡树
    CF915E Physical Education Lessons
    P3701 「伪模板」主席树
    P1198 [JSOI2008]最大数
    P3466 [POI2008]KLO-Building blocks
    P3919 【模板】可持久化数组(可持久化线段树/平衡树)
  • 原文地址:https://www.cnblogs.com/jlyg/p/10852909.html
Copyright © 2020-2023  润新知