Cocos2dx3.2编写常用UI组件(五)带滚动的表格GridView

前言:

按照惯例先发上效果图:

正文:

先来吐槽几句,一说起滚动效果大家可能会联想到Cocos2dx给我们提供的ScrollView。我一开始也是打算用ScrollView来实现的,但是用着用着发现出现了各种莫名其妙的错误,所以只好自己重新写一个Node,通过onTouchBegan和onTouhMoved两个事件回调来实现滚动的效果。

GridView使用说明:

1.利用GridView::create(int row,int column)来创建一个GridView,row和column分别指定行数和列数。注意这里的行数是指可见的行数

2.通过GridView::addItem(Node* node)来向GridView里面添加元素

GridView实现思路:

1.创建的时候指定行数和列数

2.GridView里面新建一个Node(visibleNode)用于保存所有的item(以后实现滚动的时候方便点)

3.通过addItem进GridView时,计算出item的位置(x,y)

4.接受触摸事件

5.计算触摸的偏移量,visibleNode移动相应的距离

6.一头一尾的触摸要稍作判断(即不能上方出现空白或全空白)

7.添加遮罩层

核心代码解析:

1、添加Item

void GridView::addItem(Node* item){
	if(getItemSize() == 0){<span style="white-space:pre">		</span>//如果是第一个Item(则以这个item为标准)
		m_visible_node = Node::create();<span style="white-space:pre">	</span>//visibleNode用于保存所有的item
		m_visible_node->setAnchorPoint(Point(0,0));
		m_visible_node_posy_max = 0;<span style="white-space:pre">	</span>//m_visible_posy_max表示现在最大能移上去多少(对应于尾的判断)

		m_item_width = item->getContentSize().width;<span style="white-space:pre">	</span>//利用第一个Item来确定标准
		m_item_height = item->getContentSize().height;
		this->setContentSize(
			Size(m_item_width*m_column_num,m_item_height*m_row_num)
			);
		m_visible_node->setContentSize(
			Size(m_item_width*m_column_num,m_item_height*m_row_num)
			);
		ClippingNode* cliper = ClippingNode::create();<span style="white-space:pre">	</span>//遮罩层
		DrawNode* drawNode = DrawNode::create();
		Point points[] = {Point(getPosition()),
						Point(getPositionX(),getPositionY()+m_row_num*m_item_height),
						Point(getPositionX()+m_column_num*m_item_width,getPositionY()+m_row_num*m_item_height),
						Point(getPositionX()+m_column_num*m_item_width,getPositionY())};

		drawNode->drawPolygon(points,4,Color4F(0,0,0,1),0,Color4F(0,0,0,0));

		LayerColor* stencil = LayerColor::create(Color4B(0x00, 0x00, 0x00, 0xC0),this->getContentSize().width,this->getContentSize().height);
		stencil->setAnchorPoint(Point(0,0));

		cliper->setStencil(stencil);
		cliper->addChild(m_visible_node);
		this->addChild(cliper);

		scrollbar = ScrollBar::create(m_row_num*m_item_height);<span style="white-space:pre">	</span>//滚动条(下面会讲到可以先跳过)
		scrollbar->setPosition(m_item_width*m_column_num,0);
		this->addChild(scrollbar);

	}
	item->setAnchorPoint(Point(0,1));

	int index = getItemSize() + 1;
	float x = (index-1)%m_column_num * m_item_width;<span style="white-space:pre">	</span>//计算出item的x,y
	float y = m_item_height*m_row_num - ((index-1)/m_column_num * m_item_height);
	item->setPosition(Point(x,y));
	int cur_max_row = (index-1)/m_column_num+1;
	if(cur_max_row > m_row_num){<span style="white-space:pre">			</span>//如果当前最大行数超过可见行
		m_visible_node_posy_max = (cur_max_row-m_row_num)*m_item_height;<span style="white-space:pre">	</span>//设置最大能移上去多少
		scrollbar->setButtonSize(m_row_num*1.0/cur_max_row);<span style="white-space:pre">	</span>
	}
	m_visible_node->addChild(item);<span style="white-space:pre">	</span>//添加到visibleNode里面

	m_items.insert(index,item);
}

2、触摸事件

bool GridView::onTouchBegan(Touch* pTouch,Event* pEvent){
	Point p = Director::getInstance()->convertToGL(pTouch->getLocationInView());
	if(this->getBoundingBox().containsPoint(p)){<span style="white-space:pre">	</span>//判断是否触摸到
		move_began = p;
		return true;
	}
	return false;
}

void GridView::onTouchMoved(Touch* pTouch,Event* pEvent){
	CCLOG("Touch Moved");
	move_ing= Director::getInstance()->convertToGL(pTouch->getLocationInView());
	if(!this->getBoundingBox().containsPoint(move_ing)) return;

	float offset_y = move_ing.y - move_began.y;//计算出偏移量
	CCLOG("move_y:%f",offset_y);
	m_visible_node->setPositionY(m_visible_node->getPositionY() + offset_y); //visibleNode移动相应的偏移量
	if(m_visible_node->getPositionY()<0){<span style="white-space:pre">	</span>//头的判断(因为整个GridView的AnchorPoint是(0,0))
		m_visible_node->setPositionY(0);
	}
	if(m_visible_node->getPositionY() > m_visible_node_posy_max){//尾的判断。前面已经计算出最大可以上移的高度
		m_visible_node->setPositionY(m_visible_node_posy_max);
	}
	if(m_visible_node_posy_max>0){<span style="white-space:pre">	</span>//这里主要是用在滚动条
		float delta_y = m_visible_node->getPositionY();
		float percent = delta_y/m_visible_node_posy_max;
		scrollbar->setButtonPos(percent);
	}
	move_began = move_ing;
}

3、滚动条

实现思路:1.滚动条的大小由可见行数决定:滚动条高度=可见行数*每个Item的高度

2.滚动Button的大小由当前最大行数和可见行数决定:滚动Button的大小=可见行/最大行 * 滚动条高度

3.滚动条的位置由GridView当前位置和GridView最大可以上升的位置、滚动Button大小和滚动条大小决定

可以这样理解:

GridView上升高度/最大可以上升高度 =  Button下降高度/Button最大可以下降高度

其中,GridView的上升高度和最大上升高度可以直接获取,Button的最大下降高度= 滚动条大小-Button大小

因此,可以求出Button的下降高度。也就可以确定Button的位置

4、GridView主要用途

GridView可以用来做背包视图,或者一个简单的listView(需要设置列数为1)

最后,附上源码:注意要把那两个图片放到resource文件夹里面哦

点击打开链接

时间: 2024-10-09 22:11:00

Cocos2dx3.2编写常用UI组件(五)带滚动的表格GridView的相关文章

Cocos2dx3.2编写常用UI组件(四)发光的标题BlinkTitile

前言: 如果看了上一节我推荐的blog,并且掌握了遮罩层的运用,那么本节介绍的发光标题就非常的简单了. 没有看也没关系,现在我来具体讲一下ClippingNode 正文: 关于遮罩ClippingNode,我们先来介绍两个名词:模板和底板 不知道大家以前又没有玩过橡皮泥,通常有一下空心的模具,只要把花型的模具按在红色的橡皮泥上面,就可以裁剪出一个花型的红色橡皮泥 这里花型模具就是模板,红色橡皮泥就是底板 在cocos2dx中 模板和底板都可以是Layer/Sprite/Node/DrawNode

Cocos2dx3.2编写常用UI组件(三)收集器效果Collector

前言: 在游戏中,我们经常可以看到,获取分数后,分数会自动升到对应的分数栏上面.今天我们就来实现这种效果 正文: 这种效果实现起来其实非常的简单,只需要对生成出来的分数(通常是一个Sprite或Node)添加动作,让其能够飘到目标位置,然后消失就可以了.这里我提供一个Collector类来供大家使用.方便大家的操作. Collector的使用说明:①通过Collector::create()函数创建一个Collector对象 ②首先要设置Collector的位置 ③如需要元素设置到达收集器之后的

Cocos2dx3.2编写常用UI组件(二)滚动计数器NumberScroller

前言: 废话不多说,先看最终效果图 正文: 1.使用说明: ①引入头文件 "NumberScroller.h" ②用NumberScroller::create(int length,int fontSize) 函数来创建NumberScroller对象 ③利用setNumber(int number)函数来设置计时器里面的值(这里只实现了向后滚动,即设置的值要大于等于当前值) ④利用getNumber获得当前计数器显示的值 ⑤利用setTime(float time)函数来设置计时器

五、vue常用UI组件

下面简单的总结下vue常用的一些UI 组件,有一些我也没怎么用过,这里先罗列出来,便于自己后面使用的时候查找方便,大家有更好的可以给我推荐哦~ vuex: vux github ui demo:https://github.com/airyland/vux Mint UI 项目主页:http://mint-ui.github.io/#!/zh-cn demo:http://elemefe.github.io/mint-ui/#/ github地址:https://github.com/Eleme

Android常用UI组件 - Button

按钮(Button)是Android当中一个常用的UI组件,很小但是在开发中最常用到.一般通过与监听器结合使用,从而触发一些特定事件. Button继承了TextView.它的功能就是提供一个按钮,这个按钮可以供用户点击,当用户对按钮进行操作的时候,触发相应事件,如点击,触摸.一 般对于一个按钮而言,用的最多的就是点击事件,Button间接继承自View,而Android UI中的所有事件,都是定义在View中的. 实例:ButtonDemo 运行效果: 代码清单: 布局文件:main.xml

Android常用UI组件 - EditText

EditText是接受用户输入信息的最重要Android UI组件,可以利用EditText.getText()获取它的文本内容. 实例:EditTextDemo 运行效果: 代码清单: 布局文件:main.xml <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android&quo

Android常用UI组件 - ListView

列表视图(ListView)是Android当中一个非常重要的组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示. 列表的显示需要三个元素: 1.ListVeiw 用来展示列表的View. 2.适配器 用来把数据映射到ListView上的中介. 3.数据 具体的将被映射的字符串,图片,或者基本组件. 首先介绍"适配器"这个基础概念.在列表中定义的数据都通过"适配器"来映射到ListView上,ListView中常用的适配器有两种: ArrayAdap

android常用UI组件 学习整理

AutoCompleteTextView  自动完成输入框  实现输入提示列表供选择 GridView 网格列表 ExpandableListView 可折叠列表组件 Spinner 下拉列表选择框 Gallery 画廊  实现滑动操作的图片集 AdapterViewFlipper 实现图片轮播 StackView 堆叠视图 ProgressBar 进度条 SeekBar 拖动条 RatingBar  星级评分条 ViewAnimator View切换时表现出动画效果 ImageSwitcher

Android常用UI组件 - TextView

布局文件:main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" andr