cocos2dx之彩色编辑输入框的设计

****************************************************************************

时间:2015-01-26

作者:Sharing_Li

转载出处http://www.jb51.cc/article/p-ostkmqhm-rx.html

****************************************************************************

在游戏开发当中,我们可能有比较特殊的需求,比如今天要讲解的,做一个具有游戏特色的简单的编辑输入框。还是老规矩,先看一下效果图吧,这里有三张,因为输入的键盘的弹出方式有三种,这里根据每种情况对其功能需求做一下简要说明:

首先是一般的形式:

(画面太美,不忍直视。。。)

功能需求:

1、只有点击输入框才弹出键盘;

2、键盘出来的简单动画和点击键盘按钮的简单动画;

3、输入框实时显示键盘的输入,可以删除输入内容;

4、点击确定按钮,或点击除了输入框和键盘的地方,键盘消失的简单动画。

有的时候,键盘弹出来会挡住输入框,看着有点不爽,所以我们可以如下方案:

功能需求:

1、和前一个相比,其实就是改变了键盘的弹出方式,其实也没改变,就是让原来不动的背景图也跟着一起动。

可是这种显示方案也不足,要是输入框所处的位置比较便上,那么背景图上移的时候,很可能就看不到输入框了。那么,问题来了,学挖掘机........键盘弹出方案哪家强?(打字打顺了~。~),想必大部分人都知道了,来看看最后一种显示:

功能需求:

1、和前面的相比,变成了全屏输入,多加了一个阴影层和输入框。

PS:1、补充下,那个键盘要适配屏幕的大小。

2、我们可以将键盘上的按钮图片换成具有自己游戏中的元素的图片

接下来,来看看代码的大致实现:

先浏览下头文件:

#ifndef _COLOR_EDIT_H_
#define _COLOR_EDIT_H_

#include "cocos2d.h"
#include "cocos-ext.h"

USING_NS_CC;
USING_NS_CC_EXT;

enum EditType
{
	EditType_No = 0,Edit_Number,Edit_Alphabet,Edit_PinYin
};

enum EditLocation
{
	EditLocation_No = 0,Location_Down,Location_Nature,Location_Screen
};

enum KeyBtn
{
	Key_Num_0 = 0,Key_Num_1,Key_Num_2,Key_Num_3,Key_Num_4,Key_Num_5,Key_Num_6,Key_Num_7,Key_Num_8,Key_Num_9,Key_Delete,Key_Sure
};

class ColorEdit : public cocos2d::Layer
{
public:
	~ColorEdit();
	ColorEdit();

	static ColorEdit * create(const Size & size,const char * BgFile,Node * parent,EditLocation editLocation,EditType editType = Edit_Number);
	static ColorEdit * create(const Size & size,Scale9Sprite * pBgSprite,EditType editType = Edit_Number);
	bool myInit(Scale9Sprite * pBgSprite,EditType editType);

protected:
	virtual bool onTouchBegan(Touch* touch,Event* pEvent);

	void onNumBtnCallback(Ref * obj);
	void onFunBtnCallback(Ref * obj);

	int getMaxZOrder(Node * node);
	void moveAction(bool isShow);
	void updateText();
private:
	Scale9Sprite * m_pEditBg;
	Sprite * m_pKeyBoard;
	EditType m_editType;
	EditLocation m_editLocation;
	Sprite * m_keyBg;
	Node * m_pTarget;
	bool m_isKeyShow;
	std::string m_text;
};

#endif

再来具体看看实现部分:

首先初始化:

bool ColorEdit::myInit(Scale9Sprite * pBgSprite,EditType editType)
{
	if (!Layer::init())
	{
		return false;
	}
	m_pEditBg = pBgSprite;
	m_pTarget = parent;
	m_editLocation = editLocation;
	m_editType = editType;

	this->addChild(m_pEditBg);
	auto centerSize = m_pEditBg->getContentSize();
	//这里要设置好九宫图中间的矩形的大小,因为我们要把输入的内容显示在上面,否则会看起来乱七八糟
	m_pEditBg->setCapInsets(Rect(0,centerSize.width * 0.9,centerSize.height * 0.9));
	auto pLabel = Label::createWithTTF("","fonts/Marker Felt.ttf",centerSize.height * 0.75);
	pLabel->setColor(Color3B::WHITE);
	pLabel->setAnchorPoint(Vec2(0,0.5));
	pLabel->setTag(103);
	pLabel->setPosition(Vec2(centerSize.width * 0.08,centerSize.height * 0.5));
	m_pEditBg->addChild(pLabel,2);
	//如果是全屏显示类型
	if (m_editLocation == Location_Screen)
	{
		//添加阴影层,先隐藏
		auto keyLayer = LayerColor::create(Color4B(0,100));
		keyLayer->setPosition(Point::ZERO);
		keyLayer->setTag(100);
		m_pTarget->addChild(keyLayer,this->getMaxZOrder(parent) + 2);
		keyLayer->setVisible(false);
		//添加上方的输入框
		auto key_bigbg = Scale9Sprite::create("coloredit/key_bigbg.png");
		key_bigbg->setContentSize(Size(Director::getInstance()->getWinSize().width,key_bigbg->getContentSize().height));
		key_bigbg->setTag(101);
		key_bigbg->setAnchorPoint(Vec2(0.5,0));
		auto upSize = key_bigbg->getContentSize();
		key_bigbg->setPosition(Vec2(m_pTarget->getContentSize().width / 2,m_pTarget->getContentSize().height));
		m_pTarget->addChild(key_bigbg,this->getMaxZOrder(parent) + 2);
		//同样设置九宫图中间的矩形
		key_bigbg->setCapInsets(Rect(0,upSize.width * 0.9,upSize.height * 0.9));
		auto label_up = Label::createWithTTF("",upSize.height * 0.75);
		label_up->setColor(Color3B::WHITE);
		label_up->setAnchorPoint(Vec2(0,0.5));
		label_up->setTag(102);
		label_up->setPosition(Vec2(upSize.width * 0.08,upSize.height / 2));
		key_bigbg->addChild(label_up);
	}

	m_keyBg = Sprite::create("coloredit/key_bg.png");
	m_keyBg->setAnchorPoint(Vec2(0.5,1));
	m_keyBg->setPosition(Vec2(m_pTarget->getContentSize().width / 2,0));
	m_pTarget->addChild(m_keyBg,this->getMaxZOrder(parent) + 2);

	auto bgSize = m_keyBg->getContentSize();
	auto pMenu = Menu::create();
	pMenu->setPosition(Vec2::ZERO);
	m_keyBg->addChild(pMenu);
	if (m_editType == Edit_Number)//添加数字键盘
	{
		for (int i = 0; i < 2; i++)
		{
			for (int j = 0; j < 5; j++)
			{
				auto numSprNor = Sprite::create(__String::createWithFormat("coloredit/num_%d.png",i * 5 + j)->getCString());
				auto numSprSel = Sprite::create(__String::createWithFormat("coloredit/num_%d.png",i * 5 + j)->getCString());
				auto numBtn = MenuItemSprite::create(numSprNor,numSprSel,CC_CALLBACK_1(ColorEdit::onNumBtnCallback,this));
				numBtn->setTag(Key_Num_0 + i * 5 + j);

				numBtn->setPosition(Vec2(bgSize.width / 10 * (j * 2 + 1),bgSize.height / 6 * ((3 - i) * 2 - 1)));
				pMenu->addChild(numBtn);
			}
		}

		auto delSprNor = Sprite::create("coloredit/btn_del.png");
		auto delSprSel = Sprite::create("coloredit/btn_del.png");
		auto delBtn = MenuItemSprite::create(delSprNor,delSprSel,CC_CALLBACK_1(ColorEdit::onFunBtnCallback,this));
		delBtn->setTag(Key_Delete);
		delBtn->setPosition(Vec2(bgSize.width / 4 - 15,bgSize.height / 6));
		pMenu->addChild(delBtn);

		auto sureSprNor = Sprite::create("coloredit/btn_sure.png");
		auto sureSprSel = Sprite::create("coloredit/btn_sure.png");
		auto sureBtn = MenuItemSprite::create(sureSprNor,sureSprSel,this));
		sureBtn->setTag(Key_Sure);
		sureBtn->setPosition(Vec2(bgSize.width / 4 * 3 + 15,bgSize.height / 6));
		pMenu->addChild(sureBtn);
	}
	else if (m_editType == Edit_Alphabet)//和number差不多,多了些按钮而已
	{
	}
	else if (m_editType == Edit_PinYin)//这个要是实现的话,就成输入法了,咱们还是调用系统的吧。
	{
	}

	//简单暴力的屏幕适配
	auto rate_x = Director::getInstance()->getWinSize().width / bgSize.width;
	m_keyBg->setScaleX(rate_x);

	auto listenerT = EventListenerTouchOneByOne::create();
	listenerT->onTouchBegan = CC_CALLBACK_2(ColorEdit::onTouchBegan,this);
	listenerT->setSwallowTouches(false);
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listenerT,this);

	return true;
}


然后是触摸函数的实现:

bool ColorEdit::onTouchBegan(Touch* touch,Event* pEvent)
{
	auto touchPoint = touch->getLocation();
	//如果是全屏显示类型,并且键盘已弹出
	if (m_editLocation == Location_Screen && m_isKeyShow)
	{
		auto key_upEdit = (Scale9Sprite *)m_pTarget->getChildByTag(101);
		//如果点击除了顶层输入框和键盘的其他地方,则键盘消失
		if (!m_keyBg->getBoundingBox().containsPoint(touchPoint) && 
			!key_upEdit->getBoundingBox().containsPoint(touchPoint))
		{
			this->moveAction(false);
			return true;
		}
		return false;
	}

	//将触摸点转为在当前子层下的坐标
	touchPoint = this->convertToNodeSpace(touchPoint);
	if (!m_pEditBg->getBoundingBox().containsPoint(touchPoint))
	{
		if (m_isKeyShow)
		{
			if (!m_keyBg->getBoundingBox().containsPoint(Vec2(touch->getLocation().x,touch->getLocation().y - (m_editLocation == Location_Down ? 1 : 0) * m_keyBg->getContentSize().height)))
			{
				this->moveAction(false);
			}
		} 
		return false;
	}
	//如果点击了输入框,并且键盘还未弹出
	if (!m_isKeyShow)
	{
		this->updateText();
		this->moveAction(true);
	} 

	return true;
}


这里有个要注意的地方:

if (!m_keyBg->getBoundingBox().containsPoint(Vec2(touch->getLocation().x,touch->getLocation().y - (m_editLocation == Location_Down ? 1 : 0) * m_keyBg->getContentSize().height)))
			{
				this->moveAction(false);
			}


当键盘的弹出方式是效果图第二张时,因为背景图向上移动了一段距离,touch->getLocation()的y坐标要做一下修改,否则getBoundingBox的判断不正确。

再来看看对于键盘点击的响应函数:

void ColorEdit::onNumBtnCallback(Ref * obj)
{
	int tag = ((Node *)obj)->getTag();
	//点击按钮的简单动画
	((MenuItemSprite *)obj)->runAction(Sequence::create(ScaleTo::create(0.1,10 / 8.0),ScaleTo::create(0.1,1),NULL));
	
	char temp[3];
	sprintf(temp,"%d",tag);
	m_text += temp;
	//更新内容
	this->updateText();

	log("keyboard------->%d",tag);
}

void ColorEdit::onFunBtnCallback(Ref * obj)
{
	((MenuItemSprite *)obj)->runAction(Sequence::create(ScaleTo::create(0.1,NULL));

	if (((Node *)obj)->getTag() == Key_Sure)
	{
		this->moveAction(false);
	}
	else
	{
		auto n = m_text.size();
		if (n > 0)
		{
			m_text = m_text.substr(0,n - 1);
		}
		this->updateText();
	}
}

接着是键盘的出现与消失:

void ColorEdit::moveAction(bool isShow)
{
	if (m_editLocation == Location_Screen)
	{
		auto keyLayer = (LayerColor *)m_pTarget->getChildByTag(100);
		auto key_upEdit = (Scale9Sprite *)m_pTarget->getChildByTag(101);

		keyLayer->setVisible(isShow);
		key_upEdit->runAction(MoveBy::create(0.35,Vec2(0,(isShow ? -1 : 1) * key_upEdit->getContentSize().height)));
		m_keyBg->runAction(MoveBy::create(0.35,(isShow ? 1 : -1) * m_keyBg->getContentSize().height)));
	}
	else if (m_editLocation == Location_Down)
	{
		Director::getInstance()->getRunningScene()->runAction(MoveBy::create(0.35,(isShow ? 1 : -1) * m_keyBg->getContentSize().height)));
	}
	else if (m_editLocation == Location_Nature)
	{
		m_keyBg->runAction(MoveBy::create(0.35,(isShow ? 1 : -1) * m_keyBg->getContentSize().height)));
	}

	m_isKeyShow = isShow;
	if (!isShow)
	{
		m_text = "";
	}
}

剩下的其他函数:

//获取最大的Zorder
int ColorEdit::getMaxZOrder(Node * node)
{
	int zorder = -1;
	Vector<Node *> nodeVec = node->getChildren();
	for (auto node : nodeVec)
	{
		int temp = node->getLocalZOrder();
		if (temp > zorder)
		{
			zorder = temp;
		}
	}
	log("children's max zorder is %d",zorder);

	return zorder;
}

void ColorEdit::updateText()
{
	if (m_editLocation == Location_Screen)
	{
		((Label *)((Scale9Sprite *)(m_pTarget->getChildByTag(101)))->getChildByTag(102))->setString(m_text);
	}
	else
	{
		((Label *)(m_pEditBg->getChildByTag(103)))->setString(m_text);
	}
}

最后我们在使用的时候,只需几行代码就行了。

auto colorEdit = ColorEdit::create(Size(250,40),"coloredit/input_box.png",this,Location_Nature);
colorEdit->setPosition(Vec2(bgSize.width / 2,bgSize.height / 2));
bg->addChild(colorEdit);

到这里基本上说完了,写的不好的地方还请见谅。

资源下载处:http://download.csdn.net/detail/sharing_li/8398363

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


    本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991.  软件准备 下载地址:http://cn.cocos2d-x.org/download 2.  简介2.1         引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download  v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0    有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
 下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建
2019独角兽企业重金招聘Python工程师标准>>>cocos2d2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是ios里的短信气泡了),这就要求图
原文链接:http://www.cnblogs.com/linji/p/3599478.html1.环境和工具准备Win7VS2010/2012,至于2008v2版本之后似乎就不支持了。 2.安装pythonv.2.0版本之前是用vs模板创建工程的,到vs2.2之后就改用python创建了。到python官网下载版本2.7.5的,然后
环境:ubuntu14.04adt-bundle-linux-x86_64android-ndk-r9d-linux-x86_64cocos2d-x-3.0正式版apache-ant1.9.3python2.7(ubuntu自带)加入环境变量exportANDROID_SDK_ROOT=/home/yangming/adt-bundle-linux/sdkexportPATH=${PATH}:/$ANDROID_SDK_ROOTools/export
1开发背景游戏程序设计涉及了学科中的各个方面,鉴于目的在于学习与进步,本游戏《FlappyBird》采用了两个不同的开发方式来开发本款游戏,一类直接采用win32底层API来实现,另一类采用当前火热的cocos2d-x游戏引擎来开发本游戏。2需求分析2.1数据分析本项目要开发的是一款游
原文链接:http://www.cnblogs.com/linji/p/3599912.html//纯色色块控件(锚点默认左下角)CCLayerColor*ccc=CCLayerColor::create(ccc4(255,0,0,128),200,100);//渐变色块控件CCLayerGradient*ccc=CCLayerGradient::create(ccc4(255,0,0,
原文链接:http://www.cnblogs.com/linji/p/3599488.html//载入一张图片CCSprite*leftDoor=CCSprite::create("loading/door.png");leftDoor->setAnchorPoint(ccp(1,0.5));//设置锚点为右边中心点leftDoor->setPosition(ccp(240,160));/
为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院关老师的Cocos2d-x课程之一可以送智捷课堂编写图书一本(专题可以送3本)。一、Cocos2d-x课程列表:1、Cocos2d-x入门与提高视频教程__Part22、Cocos2d-x数据持久化与网络通信__Part33、Cocos2d-x架构设计与性能优化内存优
Spawn让多个action同时执行。Spawn有多种不同的create方法,最终都调用了createWithTwoActions(FiniteTimeAction*action1,FiniteTimeAction*action2)方法。createWithTwoActions调用initWithTwoActions方法:对两个action变量初始化:_one=action1;_two=action2;如果两个a
需要环境:php,luajit.昨天在cygwin上安装php和luajit环境,这真特么是一个坑。建议不要用虚拟环境安装打包环境,否则可能会出现各种莫名问题。折腾了一下午,最终将环境转向linux。其中,luajit的安装脚本已经在quick-cocos2d-x-develop/bin/中,直接luajit_install.sh即可。我的lin
v3.0相对v2.2来说,最引人注意的。应该是对触摸层级的优化。和lambda回调函数的引入(嗯嗯,不枉我改了那么多类名。话说,每次cocos2dx大更新。总要改掉一堆类名函数名)。这些特性应该有不少人研究了,所以今天说点跟图片有关的东西。v3.0在载入图片方面也有了非常大改变,仅仅只是