CocosUI之ScrollView

来源:互联网 发布:天刀少女体型捏脸数据 编辑:程序博客网 时间:2024/06/06 05:08

Slider滑动控件(如调节音量)

同样是一堆精灵组成这个控件外观

ControlSlider* slider =ControlSlider::create(

            "ccs-res/cocosui/sliderTrack.png",

            "ccs-res/cocosui/sliderProgress.png",

            "ccs-res/cocosui/sliderThumb.png");

 

addChild(slider);

slider->setPosition(200,200);

 

/* 可以设置滑动范围 0——1之间 */

slider->setMinimumValue(0);

slider->setMaximumValue(1);

/*  最大和最小允许滑动范围      */

slider->setMaximumAllowedValue(.7f);

slider->setMinimumAllowedValue(.2f);

/*  设置初始位置        */

slider->setValue(.5f);

/* 设置事件监听——监听滑动状态*/

slider->addTargetWithActionForControlEvents(this, (Control::Handler)(&T020701UI::HandlerSlider),Control::EventType::VALUE_CHANGED);

/* 回调函数*/

void HandlerSlider(Ref*sender, Control::EventTypetype)

{

        ControlSlider* s = (ControlSlider*)sender;

        CCLOG("called valueis %f",s->getValue());

}

 

ScrollView(滑动窗口)

基本使用

通常作为游戏选关的控件,用法

1.ScrollView* view =ScrollView::create(winSize); //创建一个ScrollView,参数1是显示大小,这里设置的大小是屏幕大小。参数2——Node*,是滚动的区域,参数2可以不写,create函数会自动生成——通过getContainer

view->setTag(100); //保存一下

 

2.Node* node =view->getContainer();//获取保存在ScrollView中的Node对象,这个Node对象是存留滑动选项的重要对象

3./*  向Node对象中添加滑动选项精灵 */

for (int i = 0; i < 9;++i)

{

        char buf[128];

        sprintf(buf, "Images/background%d.jpg", (i % 3) + 1);

        Sprite* sprite =Sprite::create(buf);

        node->addChild(sprite);

 

        sprite->setPosition(winSize.width / 2+ i* winSize.width, winSize.height / 2);

}

4.addChild(view); //添加这个ScrollView

//node->setContentSize(Size(winSize.width* 3, winSize.height));一定要注意,这里设置node的大小不能用node的setcontentSize

5.view->setContentSize(Size(winSize.width * 9,winSize.height));反而是用view

 

6.view->setDirection(ScrollView::Direction::HORIZONTAL); //设置滑动方向

 

{       /*     设置触摸滑动      */

7.      auto ev = EventListenerTouchOneByOne::create();

        ev->onTouchBegan = [](Touch*,Event*){returntrue; };

        ev->onTouchEnded = [&](Touch*touch, Event*)

        {

                Vec2 posStart =touch->getStartLocation();//获取按下时的位置

                Vec2 posNow =touch->getLocation();//获取当前位置

                //if (posStart !=posNow) //滑动

                if(posStart.getDistanceSq(posNow) > 25)// 如果滑动距离大于5,认为是滑动,这里用了getDistanceSq

                {

                    CCLOG("Touchended********************");

                    // 启动定时器,检测container不动了

                    schedule(schedule_selector(T020701UI::detectScrollViewStop));

                    _lastXPosOfView =winSize.width * 9; //初始化位置记录器为一个不可能用的值

                }

                else // 如果是点击

                {

                    // 判断哪个图片被点击了

                    ScrollView* view = (ScrollView*)getChildByTag(100);

                    Node* node =view->getContainer();

                    Vec2 posNowInNode =node->convertToNodeSpace(posNow); //坐标转换

 

                    Vector<Node*>& children= node->getChildren();//获取node的所有儿子

                    int idx = 0;

                    for (Node* child : children) //遍历儿子,看看在哪个儿子里面

                    {

                        Rect rcChild =child->getBoundingBox();

                       

                        if(rcChild.containsPoint(posNowInNode))

                        {

                            CCLOG("idx = %d", idx);

                            break;

                        }

                        idx++;

                    }

                }

            };

            this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(ev,this);

}
/*探查滑动是否停止如果没有停止则修正*/

voiddetectScrollViewStop(float)

{

        CCLOG("detect**************************");

        ScrollView* view = (ScrollView*)getChildByTag(100);

        Node* node =view->getContainer();

        float x = node->getPositionX();//获取node当前位置

        if (_lastXPosOfView !=x) //如果每次都不想等,则说明正在滑动

        {

            _lastXPosOfView = x;

        }

        else

        {

            CCLOG("adjust**********************************");

            // 如果_lastXPosOfView== x,说明container已经停止了

            // 调整container的位置

            adjustContainer();//修正位置

            unschedule(schedule_selector(T020701UI::detectScrollViewStop)); //必须停止探测

    }

}

 

float _lastXPosOfView; //位置记录器

void adjustContainer()

{

        auto winSize = Director::getInstance()->getWinSize();

        ScrollView* view = (ScrollView*)getChildByTag(100);

        Node* node =view->getContainer();

 

        Vector<Node*>& children= node->getChildren();

 

        for (auto it =children.begin(); it != children.end(); ++it)

        {

            Node* child = *it;

            Vec2 pos =child->getPosition();//获取节点位置,这个位置就是中心位置了

            Vec2 childInWorld =node->convertToWorldSpace(pos);

 

            float dist =abs(childInWorld.x - winSize.width / 2); //只需判断当前位置和屏幕中央的距离绝对值就可以了

            if (dist <winSize.width / 2)

            {

                MoveBy* move =MoveBy::create(dist / 200,Vec2(winSize.width / 2 -childInWorld.x, 0)); //用动作把其移回,速度为200像素/秒,这里正好距离差可以作为移动方式

                node->runAction(move);

                break;

            }

        }

}

总结:

1.      创建ScrollView

2.      获取Node(通过获取container)——设置Node——添加精灵们(精灵们设置)——设置大小(用ScrollView的函数)

3.      Add这个Node,Add这个View

4.      添加触摸(是在Ended中设置的)——先判断是滑动还是点击,如果滑动范围非常小就认为是点击。是滑动则等其滑动完(触发滑动检测和滑动调整),是点击则判定点击哪个图片

5.      滑动检测是判断node的当前位置和过去位置是否不同

6.      滑动调整是判断哪个精灵图片距离屏幕中央最近,然后将其移动到屏幕中央

7.      记得安上定时器后要删除定时

还是要注意一下getChildren返回的是引用。

我们设置的触摸并不影响ScrollView本身的触摸,因为没有做Swallow

 

源码(触摸)

ScrollView派生于Layer和ActionTweenDelegate类

在其create函数中用initWithViewSize设置了触摸(_touches),同时还设置了一个默认Node——container

类中也有:

virtual bool onTouchBegan(Touch *touch,Event *event)override;

virtual void onTouchMoved(Touch *touch,Event *event)override;

virtual void onTouchEnded(Touch *touch,Event *event)override;

virtual void onTouchCancelled(Touch *touch,Event *event)override;

其触摸按照_ touches数目为1——滑动,为2——缩放

 

0 0
原创粉丝点击