Cocos2d-x学习(四):带光标的输入框

2024-06-17 11:08

本文主要是介绍Cocos2d-x学习(四):带光标的输入框,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Cocos2d-x学习(四):带光标的输入框       

        分类:            Cocos2d-X学习 13331人阅读 评论(12) 收藏 举报
alignment 输入法 float input 跨平台 keyboard

目录(?)[+]

  1. CCTextFieldTTF分析
    1. 1静态初始化方法
    2. 2输入法控制方法
    3. 3字符输入处理方法
  2. 自定义带光标的输入框 CursorTextField
    1. 1 首先我们需要知道输入框控件要提供哪些想要的操作而要完成这些操作我们需要继承哪些父类
    2. 2 实现一些必要的方法
  3. 使用

cocos2d-x为我们提供了一个跨平台的输入框,CCTextFieldTTF,初看时感觉提供的功能很少,当看到tests中TextInputTest这个例子的时候,感觉它的使用还真是很复杂,其原因无非是一些设置和判断的繁琐。不过话说回来了,输入框最主要的是跨平台监听输入,而不是样式!至于我们想要做的,就是根据游戏的需要相对封装一个简单的输入框而已!

今天我就以一个简单的带光标的输入框为例子,简单的解释一下输入框的工作原理和简单的封装,做到了控件使用时的简单,但是这只是一个简单的模型,目前只支持单行输入!


1.CCTextFieldTTF分析

这个类纯属是cocos2d-x的一个UI控件的扩展,当我们看到它的父类的时候,就会恍然大悟,喔!原来就是一个CCLabelTTF的子类啊!对,CCTextFieldTTF就是一个“动态”的CCLabelTTF,所谓的动态就是在监听到输入的时候动态的设置Label上的文字显示,仅此而已!而输入法的监听,则由其另一个父类CCIMEDelegate来实现。

[cpp] view plain copy print ?
  1. <span style="font-size: 16px;">class CC_DLL CCTextFieldTTF : public CCLabelTTF, public CCIMEDelegate</span> 
class CC_DLL CCTextFieldTTF : public CCLabelTTF, public CCIMEDelegate

再看其方法,总结为三大类:

(1)静态初始化方法,

[cpp] view plain copy print ?
  1. <span style="font-size: 16px;">/** creates a CCTextFieldTTF from a fontname, alignment, dimension and font size */ 
  2.     static CCTextFieldTTF * textFieldWithPlaceHolder(const char *placeholder, const CCSize& dimensions, CCTextAlignment alignment, const char *fontName, float fontSize); 
  3.     /** creates a CCLabelTTF from a fontname and font size */ 
  4.     static CCTextFieldTTF * textFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize); 
  5.     /** initializes the CCTextFieldTTF with a font name, alignment, dimension and font size */ 
  6.     bool initWithPlaceHolder(const char *placeholder, const CCSize& dimensions, CCTextAlignment alignment, const char *fontName, float fontSize); 
  7.     /** initializes the CCTextFieldTTF with a font name and font size */ 
  8.     bool initWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize);</span> 
/** creates a CCTextFieldTTF from a fontname, alignment, dimension and font size */static CCTextFieldTTF * textFieldWithPlaceHolder(const char *placeholder, const CCSize& dimensions, CCTextAlignment alignment, const char *fontName, float fontSize);/** creates a CCLabelTTF from a fontname and font size */static CCTextFieldTTF * textFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize);/** initializes the CCTextFieldTTF with a font name, alignment, dimension and font size */bool initWithPlaceHolder(const char *placeholder, const CCSize& dimensions, CCTextAlignment alignment, const char *fontName, float fontSize);/** initializes the CCTextFieldTTF with a font name and font size */bool initWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize);

(2)输入法控制方法,

[cpp] view plain copy print ?
  1. <span style="font-size: 16px;">/**
  2.     @brief  Open keyboard and receive input text.
  3.     */ 
  4.     virtual bool attachWithIME(); 
  5.  
  6.     /**
  7.     @brief  End text input  and close keyboard.
  8.     */ 
  9.     virtual bool detachWithIME();</span> 
/**@brief	Open keyboard and receive input text.*/virtual bool attachWithIME();/**@brief	End text input  and close keyboard.*/virtual bool detachWithIME();

(3)字符输入处理方法

[cpp] view plain copy print ?
  1. <span style="font-size: 16px;"><span style="white-space: pre;"> </span>virtual void insertText(const char * text, int len); 
  2. <span style="white-space: pre;">    </span>virtual void deleteBackward(); 
  3. <span style="white-space: pre;">    </span>virtual const char * getContentText();</span> 
	virtual void insertText(const char * text, int len);
	virtual void deleteBackward();
	virtual const char * getContentText();

具体使用方法可以参考tests中的TextInputTest例子,用法很复杂,如果我们在每个需要输入的Layer中都去实现,那估计是会疯的!理所应当的做法是根据我们游戏的需要将其封装一下,以满足我们的需求!


2.自定义带光标的输入框 CursorTextField

(1) 首先,我们需要知道输入框控件要提供哪些想要的操作,而要完成这些操作,我们需要继承哪些父类

偷个懒,输入的任务就交给cocos2d-x的CCTextFieldTTF了,输入框中字符串的处理我们需要CCTextFieldDelegate,而要从Layer中将触摸判断解放出来,我们还需要CCTouchDelegate,所以,我们的自定义输入框的声明会是这样

[cpp] view plain copy print ?
  1. <span style="font-size: 16px;">class CursorTextField: public CCTextFieldTTF, public CCTextFieldDelegate, public CCTouchDelegate 
  2. private
  3.     // 点击开始位置 
  4.     CCPoint m_beginPos; 
  5.      
  6.     // 光标精灵 
  7.     CCSprite *m_pCursorSprite; 
  8.      
  9.     // 光标动画 
  10.     CCAction *m_pCursorAction; 
  11.                   
  12.     // 光标坐标 
  13.     CCPoint m_cursorPos; 
  14.      
  15.     // 输入框内容 
  16.     std::string *m_pInputText; 
  17. public
  18.     CursorTextField(); 
  19.     ~CursorTextField(); 
  20.      
  21.     // static 
  22.     static CursorTextField* textFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize); 
  23.      
  24.     // CCLayer 
  25.     void onEnter(); 
  26.     void onExit(); 
  27.      
  28.     // 初始化光标精灵 
  29.     void initCursorSprite(int nHeight); 
  30.      
  31.     // CCTextFieldDelegate 
  32.     virtual bool onTextFieldAttachWithIME(CCTextFieldTTF *pSender); 
  33.     virtual bool onTextFieldDetachWithIME(CCTextFieldTTF * pSender); 
  34.     virtual bool onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen); 
  35.     virtual bool onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, int nLen); 
  36.      
  37.     // CCLayer Touch 
  38.     bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); 
  39.     void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent); 
  40.      
  41.     // 判断是否点击在TextField处 
  42.     bool isInTextField(CCTouch *pTouch); 
  43.     // 得到TextField矩形 
  44.     CCRect getRect(); 
  45.      
  46.     // 打开输入法 
  47.     void openIME(); 
  48.     // 关闭输入法 
  49.     void closeIME(); 
  50. }; 
  51.  
  52. #endif</span> 
class CursorTextField: public CCTextFieldTTF, public CCTextFieldDelegate, public CCTouchDelegate
{
private:// 点击开始位置CCPoint m_beginPos;// 光标精灵CCSprite *m_pCursorSprite;// 光标动画CCAction *m_pCursorAction;// 光标坐标CCPoint m_cursorPos;// 输入框内容std::string *m_pInputText;
public:CursorTextField();~CursorTextField();// staticstatic CursorTextField* textFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize);// CCLayervoid onEnter();void onExit();// 初始化光标精灵void initCursorSprite(int nHeight);// CCTextFieldDelegatevirtual bool onTextFieldAttachWithIME(CCTextFieldTTF *pSender);virtual bool onTextFieldDetachWithIME(CCTextFieldTTF * pSender);virtual bool onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen);virtual bool onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, int nLen);// CCLayer Touchbool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);// 判断是否点击在TextField处bool isInTextField(CCTouch *pTouch);// 得到TextField矩形CCRect getRect();// 打开输入法void openIME();// 关闭输入法void closeIME();
};#endif

(ps:这只是一个简单的版本,所以没有提供更复杂的初始化等方法,可以根据需要后续丰满)

(2) 实现一些必要的方法

a.延续了cocos2d-x的风格,将静态方法和初始化方法分开,这里几乎是CCTextFieldTTF的翻版,不过这里有一个小知识点,就是创建一个纯色精灵的办法,代码如下

[cpp] view plain copy print ?
  1. <span style="font-size: 16px;">    int column = 4; 
  2.     int pixels[nHeight][column]; 
  3.     for (int i=0; i<nHeight; ++i) { 
  4.         for (int j=0; j<column; ++j) { 
  5.              pixels[i][j] = 0xffffffff; 
  6.         } 
  7.     } 
  8.  
  9.     CCTexture2D *texture = new CCTexture2D(); 
  10.     texture->initWithData(pixels, kCCTexture2DPixelFormat_RGB888, 1, 1, CCSizeMake(column, nHeight)); 
  11.      
  12.     m_pCursorSprite = CCSprite::spriteWithTexture(texture); 
  13. </span> 
    int column = 4;int pixels[nHeight][column];for (int i=0; i<nHeight; ++i) {for (int j=0; j<column; ++j) {pixels[i][j] = 0xffffffff;}}CCTexture2D *texture = new CCTexture2D();texture->initWithData(pixels, kCCTexture2DPixelFormat_RGB888, 1, 1, CCSizeMake(column, nHeight));m_pCursorSprite = CCSprite::spriteWithTexture(texture);
我用一个纯色精灵做了一个白色的光标,哈哈,虽然很山寨,但是在用的时候不用导入光标的图片资源了!

b.触摸判断

这个是有必要的,我们要判断触摸点是否在输入框上,如果在的话,需要弹出输入法;如果不在,需要关闭输入法,这样的用户体验还是不错的!

判断方法

[cpp] view plain copy print ?
  1. <span style="font-size: 16px;">bool CursorTextField::isInTextField(cocos2d::CCTouch *pTouch) 
  2.     return CCRect::CCRectContainsPoint(getRect(), convertTouchToNodeSpaceAR(pTouch)); 
  3. </span> 
bool CursorTextField::isInTextField(cocos2d::CCTouch *pTouch)
{return CCRect::CCRectContainsPoint(getRect(), convertTouchToNodeSpaceAR(pTouch));
}
开启和关闭输入法的方法(顺便带上了光标的显示)

[cpp] view plain copy print ?
  1. <span style="font-size: 16px;">void CursorTextField::openIME() 
  2.     m_pCursorSprite->setIsVisible(true); 
  3.     this->attachWithIME(); 
  4.  
  5. void CursorTextField::closeIME() 
  6.     m_pCursorSprite->setIsVisible(false); 
  7.     this->detachWithIME(); 
  8. }</span> 
void CursorTextField::openIME()
{m_pCursorSprite->setIsVisible(true);this->attachWithIME();
}void CursorTextField::closeIME()
{m_pCursorSprite->setIsVisible(false);this->detachWithIME();
}
c.还需要处理的地方是关于输入框中的字符串的添加和删减

我们可以监听到添加和删减,CCTextFieldDelegate所提供的方法,但是需要我们自己记录输入框中的内容,因为我们需要根据输入框中字符串的长度来确定光标的位置,而监听到添加字符的方法时,如果调用getString方法总会是差一个字符的,所以需要我们单独记录,我们手动调用setString方法,CCTextFieldTTF是根据字符串的宽度动态变化宽度的,于是有了下面的方法

[cpp] view plain copy print ?
  1. <span style="font-size: 16px;">bool CursorTextField::onTextFieldInsertText(cocos2d::CCTextFieldTTF *pSender, const char *text, int nLen) 
  2.     CCLOG("Width: %f", pSender->getContentSize().width); 
  3.     CCLOG("Text: %s", text); 
  4.     CCLOG("Length: %d", nLen); 
  5.      
  6.     m_pInputText->append(text); 
  7.     setString(m_pInputText->c_str()); 
  8.      
  9.     m_pCursorSprite->setPositionX(getContentSize().width); 
  10.      
  11.     return true
  12.  
  13. bool CursorTextField::onTextFieldDeleteBackward(cocos2d::CCTextFieldTTF *pSender, const char *delText, int nLen) 
  14.     m_pInputText->resize(m_pInputText->size() - nLen); 
  15.     setString(m_pInputText->c_str()); 
  16.      
  17.     m_pCursorSprite->setPositionX(getContentSize().width); 
  18.      
  19.     if (m_pInputText->empty()) { 
  20.         m_pCursorSprite->setPositionX(0); 
  21.     } 
  22.      
  23.     return false
  24. }</span> 
bool CursorTextField::onTextFieldInsertText(cocos2d::CCTextFieldTTF *pSender, const char *text, int nLen)
{CCLOG("Width: %f", pSender->getContentSize().width);CCLOG("Text: %s", text);CCLOG("Length: %d", nLen);m_pInputText->append(text);setString(m_pInputText->c_str());m_pCursorSprite->setPositionX(getContentSize().width);return true;
}bool CursorTextField::onTextFieldDeleteBackward(cocos2d::CCTextFieldTTF *pSender, const char *delText, int nLen)
{m_pInputText->resize(m_pInputText->size() - nLen);setString(m_pInputText->c_str());m_pCursorSprite->setPositionX(getContentSize().width);if (m_pInputText->empty()) {m_pCursorSprite->setPositionX(0);}return false;
}

OK,我们自定义的输入框类基本上就写好了,省略了些简单的部分,需要的在结尾处会有源码下载链接!

3. 使用

我们想要的就是使用简单,我们想要的就是不去每层都设置触摸判断,我们想要的就是像cocos2d-x为我们提供的精灵一样使用,所以使用代码如下

[cpp] view plain copy print ?
  1. <span style="font-size: 16px;"><span style="white-space: pre;"> </span>m_pCursorTextField = CursorTextField::textFieldWithPlaceHolder("Input Text", "Thonburi", 64); 
  2.         m_pCursorTextField->setPosition(ccp(winSize.width / 2, winSize.height / 2 + 100)); 
  3.         this->addChild(m_pCursorTextField);</span> 
	m_pCursorTextField = CursorTextField::textFieldWithPlaceHolder("Input Text", "Thonburi", 64);m_pCursorTextField->setPosition(ccp(winSize.width / 2, winSize.height / 2 + 100));this->addChild(m_pCursorTextField);

效果图如下




这只是一个简单的例子,记录了一些简单的接口,目前只支持单行的正常显示,多行的和更完善的版本,下次补上!


源码下载

这篇关于Cocos2d-x学习(四):带光标的输入框的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1069274

相关文章

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

前端知识点之Javascript选择输入框confirm用法

《前端知识点之Javascript选择输入框confirm用法》:本文主要介绍JavaScript中的confirm方法的基本用法、功能特点、注意事项及常见用途,文中通过代码介绍的非常详细,对大家... 目录1. 基本用法2. 功能特点①阻塞行为:confirm 对话框会阻塞脚本的执行,直到用户作出选择。②

如何解决Pycharm编辑内容时有光标的问题

《如何解决Pycharm编辑内容时有光标的问题》文章介绍了如何在PyCharm中配置VimEmulator插件,包括检查插件是否已安装、下载插件以及安装IdeaVim插件的步骤... 目录Pycharm编辑内容时有光标1.如果Vim Emulator前面有对勾2.www.chinasem.cn如果tools工

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

element-ui下拉输入框+resetFields无法回显的问题解决

《element-ui下拉输入框+resetFields无法回显的问题解决》本文主要介绍了在使用ElementUI的下拉输入框时,点击重置按钮后输入框无法回显数据的问题,具有一定的参考价值,感兴趣的... 目录描述原因问题重现解决方案方法一方法二总结描述第一次进入页面,不做任何操作,点击重置按钮,再进行下

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]