您的位置:首页 > 移动开发 > Cocos引擎

CocosUI之ScrollView

2016-04-16 14:46 811 查看

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::EventType
type)
{
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*){return
true; };
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——缩放
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: