ScrollView 重点分析

ScrollView 重点分析,第1张

概述打开ScrollView,跟我一起看源码。 重点1:ScrollView中的container : Node* 的锚点AnchorPoint是被重置为Vec2(0,0),也就是设置大地图的时候要求用左下角作为依赖的参照点。但是,看看Layer的源码, // LayerLayer::Layer(): _touchEnabled(false), _accelerometerEnabled(fal

打开ScrollVIEw,跟我一起看源码。

重点1:ScrollVIEw中的container : Node* 的锚点AnchorPoint是被重置为Vec2(0,0),也就是设置大地图的时候要求用左下角作为依赖的参照点。但是,看看Layer的源码,

// LayerLayer::Layer(): _touchEnabled(false),_accelerometerEnabled(false),_keyboardEnabled(false),_touchListener(nullptr),_keyboardListener(nullptr),_accelerationListener(nullptr),_touchMode(touch::dispatchMode::ALL_AT_ONCE),_swallowstouches(true){    _ignoreAnchorPointForposition = true;    setAnchorPoint(Vec2(0.5f,0.5f));}

ScrollVIEw继承自Layer。


首先回顾一下Layer的坐标系相关:


在Node中有个属性_ignoreAnchorPointForposition,默认为false,不能忽略锚点做节点坐标系中的影响。

Layer和Scene继承自Node,默认contentSize是也为0的,不同的是_ignoreAnchorPointForposition为true,挂载在其他渲染树是都是以(0,0)为参考点,无论怎么设置_ignoreAnchorPointForposition属性都不会对其位置产生变化。以父节点的左下角为节点坐标系为起点很容易符合我们的想法,但是要知道确切意识到是以父节点的contentSize的左下角为原点。而Node、Layer、Scene等容器默认的contentSize是(0,0).而在Sprite为容器的节点坐标系中就不太好控制了,每次应该认真去计算父节点的 contentSize的左下角位置,才能设置当年子节点的具体位置。这是父节点的相关,当然子节点都是以自身锚地为参照点去setPisition().例如,这样子才能将ScrollVIEw正确的显示在屏幕中间,要把ScrollVIEw的cententSize的左下角点因为设置了大小产生的偏移移除掉——这个时候我们多么希望contentSize的_ignoreAnchorPointForposition也是false,这样子就可以使用类似精灵的 *** 作模式,~~可惜不是。例子代码:

pScrollVIEw->setposition(visibleSize.wIDth/2 - pScrollVIEw->getContentSize().wIDth/2,visibleSize.height/2-pScrollVIEw->getContentSize().height/2);


知道了container的锚点相关,我们就可以正确的处理ScrollVIEw的显示问题了。


dragging,拖拽。当touchBegan时设置这个状态,和设置初始的移动位置:

bool ScrollVIEw::ontouchBegan(touch* touch,Event* event){    if (!this->isVisible())    {        return false;    }        Rect frame = getVIEwRect();    //dispatcher does not kNow about clipPing. reject touches outsIDe visible bounds.    if (_touches.size() > 2 ||        _touchmoved          ||        !frame.containsPoint(touch->getLocation()))    {        return false;    }    if (std::find(_touches.begin(),_touches.end(),touch) == _touches.end())    {        _touches.push_back(touch);    }    if (_touches.size() == 1)    { // scrolling        _touchPoint     = this->converttouchToNodeSpace(touch);        _touchmoved     = false;        _dragging     = true; //dragging started        _scrolldistance = Vec2(0.0f,0.0f);        _touchLength    = 0.0f;    }    else if (_touches.size() == 2)    {        _touchPoint = (this->converttouchToNodeSpace(_touches[0]).getMIDpoint(                        this->converttouchToNodeSpace(_touches[1])));                _touchLength = _container->converttouchToNodeSpace(_touches[0]).getdistance(                       _container->converttouchToNodeSpace(_touches[1]));                _dragging  = false;    }     return true;}

拖拽开始后就播放相关的动画和设置坐标:


触摸结束之后reset除位移以为的状态:

voID ScrollVIEw::ontouchended(touch* touch,Event* event){    if (!this->isVisible())    {        return;    }        auto touchIter = std::find(_touches.begin(),touch);        if (touchIter != _touches.end())    {        if (_touches.size() == 1 && _touchmoved)        {            this->schedule(schedule_selector(ScrollVIEw::deaccelerateScrolling));        }        _touches.erase(touchIter);    }     if (_touches.size() == 0)    {        _dragging = false;            _touchmoved = false;    }}


开始减速直至停止播放动画:

voID ScrollVIEw::deaccelerateScrolling(float dt){    if (_dragging)    {        this->unschedule(schedule_selector(ScrollVIEw::deaccelerateScrolling));        return;    }        float newX,newY;    Vec2 maxInset,minInset;        _container->setposition(_container->getposition() + _scrolldistance);        if (_bounceable)    {        maxInset = _maxInset;        minInset = _minInset;    }    else    {        maxInset = this->maxContainerOffset();        minInset = this->minContainerOffset();    }        newX = _container->getposition().x;    newY = _container->getposition().y;        _scrolldistance     = _scrolldistance * SCRolL_DEACCEL_RATE;    this->setContentOffset(Vec2(newX,newY));        if ((fabsf(_scrolldistance.x) <= SCRolL_DEACCEL_disT &&         fabsf(_scrolldistance.y) <= SCRolL_DEACCEL_disT) ||        newY >= maxInset.y || newY <= minInset.y ||        newX >= maxInset.x || newX <= minInset.x)    {        this->unschedule(schedule_selector(ScrollVIEw::deaccelerateScrolling));        this->relocateContainer(true);    }}

重点在于如何计算offset的偏移位置,待续。先从tablevIEw开始下手,处理简单的坐标偏移和移动动画,另外解决更新 *** 作。待续!!





补记:_isUsedCellsDirty 鉴于tableVIEw不能动态更新的问题,可以考虑把_isUsedCellsDirty设为true,然后在渲染的时候就会重新渲染啦。

总结

以上是内存溢出为你收集整理的ScrollView 重点分析全部内容,希望文章能够帮你解决ScrollView 重点分析所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1009760.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-22
下一篇2022-05-22

发表评论

登录后才能评论

评论列表(0条)

    保存