CCScrollView添加滚动条和滚动背景

cocos2d-X里提供的CCScrollView里并没有提供滚动条和滚动条背景,我对它进行了一些修改,所用的cocos2d-x 版本为3.0

使用方法

   CCBarScrollView* scrollView = CCBarScrollView::create();
    scrollView->initWithViewSize((Size(280.0f,150.0f)));
    scrollView->setContentSize(Size(280,150*10.0f));
    scrollView->setDirection(cocos2d::extension::ScrollView::Direction::VERTICAL);
    scrollView->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    scrollView->setBounceable(true);
    this->addChild(scrollView,0);

    auto bgImage = Scale9Sprite::create("bg_pd_item.png");
    auto barImage = Scale9Sprite::create("bg2.png");

    scrollView->setBarImage(bgImage, barImage);
//    scrollView->setAutoHidden(true);

    for (int i = 0; i < 50; i++) {
        auto sprite1 = Sprite::create("CloseNormal.png");
        sprite1->setPosition(20, 20+i*40);
        scrollView->addChild(sprite1);
    }

控件代码:点击打开链接

class CCBarScrollView:public ScrollView
{
public:
    static CCBarScrollView* create(Size size, Node* container = NULL);
    static CCBarScrollView* create();

    using Node::addChild;
    void setBarImage(Scale9Sprite* barBg,Scale9Sprite* barImage);
    virtual void addChild(Node * child, int zOrder, int tag) override;

    void setContentOffset(Point offset, bool animated = false);

    void setAutoHidden(bool autoHidden); //设置是否自动隐藏

    virtual bool onTouchBegan(Touch *touch, Event *event);
    virtual void onTouchEnded(Touch *touch, Event *event);
protected:

    void deaccelerateScrolling(float dt);
    void updateBarPos();
    Scale9Sprite* barBg;       //滚动条背景
    Scale9Sprite* barImage;    //滚动条
    bool isAutoHidden;         //滚动条是否自动隐藏
};

设置滚动条背景和滚动条

void CCBarScrollView::setBarImage(Scale9Sprite* barBg, Scale9Sprite* barImage)
{

    Size contentSize = this->getContentSize();
    auto layer1 = LayerColor::create(Color4B(255, 0, 255, 255), contentSize.width, contentSize.height);
    layer1->setCascadeColorEnabled(false);
    layer1->setPosition( Point(0, 0));
    this->addChild(layer1);

    Size viewSize = this->getViewSize();

    this->barBg = barBg;

    this->barBg->setContentSize(Size(20,viewSize.height));
    this->barBg->setPosition(Point(viewSize.width - 10,viewSize.height/2));
    this->barImage = barImage;
    Layer::addChild(this->barBg);
    Layer::addChild(this->barImage);

    this->barImage->setContentSize(Size(20,viewSize.height*(viewSize.height/contentSize.height)));

    this->updateBarPos();
}

设置滚动条是否自动隐藏

void CCBarScrollView::setAutoHidden(bool autoHidden)
{
    this->isAutoHidden = autoHidden;

    if(this->barImage != nullptr && this->isAutoHidden == true)
    {
        this->barImage->setVisible(false);
    }
}

在父类里,addChild会把子节点加入滚动container里面,但是滚动条和背景应该都在它的父节点上,所以要重载次方法

void CCBarScrollView::addChild(Node *child, int zOrder, int tag)
{
    if (_container != child && barBg != child && barImage != child)
    {
        _container->addChild(child, zOrder, tag);
    } else
    {
        Layer::addChild(child, zOrder, tag);
    }
}

在contentOffset发生改变的时候,需要更新滚动条的位置

void CCBarScrollView::setContentOffset(Point offset, bool animated/* = false*/)
{
    if (animated)
    { //animate scrolling
        this->setContentOffsetInDuration(offset, BOUNCE_DURATION);
    }
    else
    { //set the container position directly
        if (!_bounceable)
        {
            const Point minOffset = this->minContainerOffset();
            const Point maxOffset = this->maxContainerOffset();

            offset.x = MAX(minOffset.x, MIN(maxOffset.x, offset.x));
            offset.y = MAX(minOffset.y, MIN(maxOffset.y, offset.y));
        }

        _container->setPosition(offset);

        if (_delegate != NULL)
        {
            _delegate->scrollViewDidScroll(this);
        }
    }

    this->updateBarPos();
//    CCLOG("CCBarScrollView::setContentOffset");
}

更新滚动条的位置函数

void CCBarScrollView::updateBarPos()
{
//    Point currentOffset = this->_container->getPosition();
    Point currentOffset = this->getContentOffset();
    Size contentSize = this->getContentSize();
    Size viewSize = this->getViewSize();

    Size barSize = this->barImage->getContentSize();
    Point p =Point(viewSize.width-10,barSize.height/2 + viewSize.height*(-currentOffset.y/contentSize.height));

//    CCLOG("barImage %f,%f,%f,%f",p.x,p.y,barSize.width,barSize.height);
//    CCLOG("currentOffset %f",currentOffset.y);
    if(p.y < barSize.height/2)
    {
        p.y = barSize.height/2;
    }
    else if(p.y + barSize.height/2 > viewSize.height)
    {
        p.y = viewSize.height- barSize.height/2;
    }

    this->barImage->setPosition(p);
}

滚动条在点击松开的时候,会做减速的运动,所以也要在减速函数做相应的处理

void CCBarScrollView::deaccelerateScrolling(float dt)
{
    if (_dragging)
    {
        this->unschedule(schedule_selector(CCBarScrollView::deaccelerateScrolling));
        return;
    }

    float newX, newY;
    Point 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(Point(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)
    {

        if(this->isAutoHidden)
        {
            FiniteTimeAction *faseOut;
            faseOut = FadeOut::create(0.2);
            this->barImage->runAction(faseOut);
        }

        this->unschedule(schedule_selector(CCBarScrollView::deaccelerateScrolling));
        this->relocateContainer(true);
    }

    this->updateBarPos();
}

点击事件开始和结束的处理

bool CCBarScrollView::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()))
    {
        CCLOG("outside visible bounds.");
        return false;
    }

    if (std::find(_touches.begin(), _touches.end(), touch) == _touches.end())
    {
        _touches.push_back(touch);
        //        CCLOG("_touches.push_back");
    }

    if (_touches.size() == 1)
    { // scrolling
        _touchPoint     = this->convertTouchToNodeSpace(touch);
        _touchMoved     = false;
        _dragging     = true; //dragging started
        _scrollDistance = Point(0.0f, 0.0f);
        _touchLength    = 0.0f;

        if(isAutoHidden)
        {
            FiniteTimeAction *faseIn;
            faseIn = FadeIn::create(0.2);
            this->barImage->setVisible(true);
            this->barImage->setOpacity(0);
            this->barImage->runAction(faseIn);
        }

        //        CCLOG("scrolling");
    }
    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;
        this->barImage->setVisible(false);
        //        CCLOG("_dragging");
    }
    return true;
}
void CCBarScrollView::onTouchEnded(Touch* touch, Event* event)
{
    if (!this->isVisible())
    {
        return;
    }

    auto touchIter = std::find(_touches.begin(), _touches.end(), touch);
    bool isDeaccelerateScrolling = false;
    if (touchIter != _touches.end())
    {
        if (_touches.size() == 1 && _touchMoved)
        {
            isDeaccelerateScrolling = true;
            this->schedule(schedule_selector(CCBarScrollView::deaccelerateScrolling));
        }
        _touches.erase(touchIter);
    }

    if (_touches.size() == 0)
    {
        if(this->isAutoHidden && isDeaccelerateScrolling == false)
        {
            FiniteTimeAction *faseOut;
            faseOut = FadeOut::create(0.2);
            this->barImage->runAction(faseOut);
        }
        _dragging = false;
        _touchMoved = false;
    }
}

CCScrollView添加滚动条和滚动背景

时间: 2024-10-23 08:21:53

CCScrollView添加滚动条和滚动背景的相关文章

UGUI Text添加滚动条 实现滚动显示

Project 说明:Content(GameObject)为text的父物体,text用于显示文本内容.ScrollBar为滚动条. 实现效果: Hierarchy: Inspector: 步骤: 1:GameObject新命名为Content,添加Text用于显示文本内容,ScrollBar的设置如下: Direction 设置为Bottom to Top 2:在Content上依次添加组件:ScrollRect ,Image,Mask. Vertical,Horzional属性消除勾号,S

JScrollPane控件中添加其他控件的问题&&JScrollPane设置滚动条&&调整滚动速度

如果要在JScrollPane控件中添加其他控件,不能用下面这种方法 JScrollPane j = new JScrollPane();j.add(new JButton("点击")); 只能通过以下方法添加 JScrollPane j = new JScrollPane(new JButton("点击")); 或者 JScrollPane j = new JScrollPane();j.getViewport().add(new JButton("点击

css控制背景图像不随滚动条的滚动而滚动

这几天在写一个demo,设置背景图像, background: url("../images/bg.jpg") repeat ; 在使用 $(window).scroll(function() { ....}); 监听滚动条时,在google下正常运行,背景图像没有异常 在ie.360.火狐下滚动滚动条时,背景图像一闪一闪的,很难受. 百度:说需要调显示器的监视器的屏幕刷新频率 > 70 Hz . 可是我的电脑只有60Hz ,那么问题来了,很多小伙伴的电脑或许跟我的一样,那怎么办

Cocos2d-x3.0游戏实例之《别救我》第三篇——循环滚动背景

好,这篇我们来讲解无限循环滚动背景,这个知识已经被讲到烂了,我以前的文章也介绍过,所以就不那么详细地说明了. 笨木头花心贡献,啥?花心?不呢,是用心~ 转载请注明,原文地址:http://www.benmutou.com/blog/archives/823 文章来源:笨木头与游戏开发 为什么是循环滚动背景? 用循环滚动背景,其实是因为我想偷懒,因为这样我只需要准备一张图片就可以了. 我们最终要创建这样的背景,如图: 背景是在滚动的,大家有没有看到?(小若:看你妹,这是jpg,不是gif) 大家是

C#超简单方法实现两个richtextbox控件滚动条同步滚动

此文章属于作者原创,转载请注明,谢谢 有时候我们需要实现对照文章等,往往将文本放到两个richtextbox控件中,但是,如果我们需要同步滚动查看,来达到更好的观看效果. 当然,传统的方法重载控件或者自定义控件都可以达到目的,但是对于新手或者想仅仅只用一次这个控件的人来说,是非常麻烦的.所以,接 下来我来提供一种简单快捷的方法来实现:richtextbox滚动条同步的功能. 首先,我们在winform窗体创建两个richtextbox控件 下面介绍两个方法,我经常用到 第一个方法,获得当前鼠标所

android textview添加滚动条

给textview添加滚动条 方式一: xml代码: //设置滚动条的方向 android:scrollbars="vertical" java中设置 tView=(TextView) findViewById(R.id.tv1); //设置滚动方式tView.setMovementMethod(ScrollingMovementMethod.getInstance()); 方式二: 直接通过ScrollView <ScrollView android:layout_width=

为窗口添加滚动条事件

为窗口添加滚动条事件其实非常的简单, window.onscroll=function(){}; 注意在获取滚动条距离的时候 谷歌不识别document.documentElement.scrollTop,必须要加上document.body.scrollTop:即 var scrolltop=document.documentElement.scrollTop||document.body.scrollTop; 这样才能兼容各个浏览器! var scrollTop = window.pageY

笔记-[js兼容]-滚动条的滚动距离的兼容性问题解决方法。

在我们操作JS实现些效果的时候,可能会涉及到滚动条滚动距离的问题; 在IE和非IE下是存在兼容性问题的 在IE下支持:document.body.scrollTop(scrollLeft);//在ie下获取滚动条距离的属性 在非IE下支持:document.documentElement.scrollTop(scrollLeft);//在非ie下获取滚动条距离的属性 代码兼容: var scrollTop;//定义一个变量名为scrollTop为滚动条的距离 滚动高度 :  var scroll

添加滚动条,内容多时显示,内容少时隐藏

CSS样式: ? 1 2 3 <style type="text/css"><br> .scroll{<br> overflow-x:auto;  overflow-y:auto;  height:800px;<br> }<br> </style> 添加滚动条,内容多时显示,内容少时隐藏,布布扣,bubuko.com