前言

游戏开发中我们一般都会有聊天系统,我们可以同时或单独发文字,图片,表情,超链接等信息的文本即称为富文本。如下图所示:

我使用的是cocos-3.4引擎版本里的RichText富文本控件实现这些操作的,但cocos自带封装的RichText还有一些问题,1:如上图看到的一样,当中英文混输时右边字体没对齐(看需求,QQ都没处理这问题)。2:聊天信息有时会需求像上面一样还要一个背景底框装着,底框大小随发送内容变化,这时我们就需要知道富文本的宽度和高度而cocos的RichText没有封装这个接口需要我们自己扩展。本章就讲讲怎么来解决这两个问题。

解决步骤

1,在UIRichText.h中新增获取富文本大小接口

public:
Size xxgetRealSize();
Size xxrealSize;

2,默认右没不齐是因为它的换行是根据字的平均长度来计算的,即单个字长度=总长度/总字数,而不同字的宽度是很可能不相同的。现在我的改法是:循环计算出每个字的大小求和换行,当然这样的效率是比默认的低,所以这个对齐还是看需求,有的QQ消息也没处理这个对齐问题。下面是UIRichText.cpp修改后的完整代码,有注释,修改处都用@cxx标记了。

/**************************************************************************** copyright (c) 2013 cocos2d-x.org http://www.cocos2d-x.org Permission is hereby granted,free of charge,to any person obtaining a copy of this software and associated documentation files (the "Software"),to deal in the Software without restriction,including without limitation the rights to use,copy,modify,merge,publish,distribute,sublicense,and/or sell copies of the Software,and to permit persons to whom the Software is furnished to do so,subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS",WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,fitness FOR A PARTIculaR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR copYRIGHT HOLDERS BE LIABLE FOR ANY CLaim,damAGES OR OTHER LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE,ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/

#include "UIRichText.h"
#include "platform/CCFileUtils.h"
#include "2d/cclabel.h"
#include "2d/CCSprite.h"
#include "base/ccUTF8.h"
#include "ui/UIHelper.h"

#include "platform/CCDevice.h" //@cxx
#include "base/ccMacros.h" //@cxx
#include "base/CCDirector.h" //@cxx

NS_CC_BEGIN

namespace ui {


bool RichElement::init(int tag,const Color3B &color,glubyte opacity)
{
    _tag = tag;
    _color = color;
    _opacity = opacity;
    return true;
}


RichElementText* RichElementText::create(int tag,glubyte opacity,const std::string& text,const std::string& fontName,float fontSize)
{
    RichElementText* element = new (std::nothrow) RichElementText();
    if (element && element->init(tag,color,opacity,text,fontName,fontSize))
    {
        element->autorelease();
        return element;
    }
    CC_SAFE_DELETE(element);
    return nullptr;
}

bool RichElementText::init(int tag,float fontSize)
{
    if (RichElement::init(tag,opacity))
    {
        _text = text;
        _fontName = fontName;
        _fontSize = fontSize;
        return true;
    }
    return false;
}

RichElementimage* RichElementimage::create(int tag,const std::string& filePath)
{
    RichElementimage* element = new (std::nothrow) RichElementimage();
    if (element && element->init(tag,filePath))
    {
        element->autorelease();
        return element;
    }
    CC_SAFE_DELETE(element);
    return nullptr;
}

bool RichElementimage::init(int tag,const std::string& filePath)
{
    if (RichElement::init(tag,opacity))
    {
        _filePath = filePath;
        return true;
    }
    return false;
}

RichElementCustomNode* RichElementCustomNode::create(int tag,cocos2d::Node *customNode)
{
    RichElementCustomNode* element = new (std::nothrow) RichElementCustomNode();
    if (element && element->init(tag,customNode))
    {
        element->autorelease();
        return element;
    }
    CC_SAFE_DELETE(element);
    return nullptr;
}

bool RichElementCustomNode::init(int tag,cocos2d::Node *customNode)
{
    if (RichElement::init(tag,opacity))
    {
        _customNode = customNode;
        _customNode->retain();
        return true;
    }
    return false;
}

RichText::RichText():
_formatTextDirty(true),_leftSpaceWidth(0.0f),_verticalSpace(0.0f),_elementRenderersContainer(nullptr)
{

}

RichText::~RichText()
{
    _richElements.clear();
}

RichText* RichText::create()
{
    RichText* widget = new (std::nothrow) RichText();
    if (widget && widget->init())
    {
        widget->autorelease();
        return widget;
    }
    CC_SAFE_DELETE(widget);
    return nullptr;
}

bool RichText::init()
{
    if (Widget::init())
    {
        return true;
    }
    return false;
}

void RichText::initRenderer()
{
    _elementRenderersContainer = Node::create();
    _elementRenderersContainer->setAnchorPoint(Vec2(0.5f,0.5f));
    addProtectedChild(_elementRenderersContainer,0,-1);
}

void RichText::insertElement(RichElement *element,int index)
{
    _richElements.insert(index,element);
    _formatTextDirty = true;
}

void RichText::pushBackElement(RichElement *element)
{
    _richElements.pushBack(element);
    _formatTextDirty = true;
}

void RichText::removeElement(int index)
{
    _richElements.erase(index);
    _formatTextDirty = true;
}

void RichText::removeElement(RichElement *element)
{
    _richElements.eraSEObject(element);
    _formatTextDirty = true;
}

    //渲染富文本
void RichText::formatText()
{
    if (_formatTextDirty)
    {
        _elementRenderersContainer->removeAllChildren();
        _elementRenders.clear();
        if (_ignoreSize) //是否忽略换行
        {
            addNewLine();
            for (ssize_t i=0; i<_richElements.size(); i++)
            {
                RichElement* element = _richElements.at(i);
                Node* elementRenderer = nullptr;
                switch (element->_type)
                {
                    case RichElement::Type::TEXT:
                    {
                        RichElementText* elmtText = static_cast<RichElementText*>(element);
                        if (FileUtils::getInstance()->isFileExist(elmtText->_fontName))
                        {
                            elementRenderer = Label::createWithTTF(elmtText->_text.c_str(),elmtText->_fontName,elmtText->_fontSize);
                        }
                        else
                        {
                            elementRenderer = Label::createWithSystemFont(elmtText->_text.c_str(),elmtText->_fontSize);
                        }
                        break;
                    }
                    case RichElement::Type::IMAGE:
                    {
                        RichElementimage* elmtimage = static_cast<RichElementimage*>(element);
                        elementRenderer = Sprite::create(elmtimage->_filePath.c_str());
                        break;
                    }
                    case RichElement::Type::CUSTOM:
                    {
                        RichElementCustomNode* elmtCustom = static_cast<RichElementCustomNode*>(element);
                        elementRenderer = elmtCustom->_customNode;
                        break;
                    }
                    default:
                        break;
                }
                elementRenderer->setColor(element->_color);
                elementRenderer->setopacity(element->_opacity);
                pushToContainer(elementRenderer);
            }
        }
        else
        {
            addNewLine();
            for (ssize_t i=0; i<_richElements.size(); i++)
            {

                RichElement* element = static_cast<RichElement*>(_richElements.at(i));
                switch (element->_type)
                {
                    case RichElement::Type::TEXT:
                    {
                        RichElementText* elmtText = static_cast<RichElementText*>(element);
                        handleTextRenderer(elmtText->_text.c_str(),elmtText->_fontName.c_str(),elmtText->_fontSize,elmtText->_color,elmtText->_opacity);
                        break;
                    }
                    case RichElement::Type::IMAGE:
                    {
                        RichElementimage* elmtimage = static_cast<RichElementimage*>(element);
                        handleImageRenderer(elmtimage->_filePath.c_str(),elmtimage->_color,elmtimage->_opacity);
                        break;
                    }
                    case RichElement::Type::CUSTOM:
                    {
                        RichElementCustomNode* elmtCustom = static_cast<RichElementCustomNode*>(element);
                        handleCustomrenderer(elmtCustom->_customNode);
                        break;
                    }
                    default:
                        break;
                }
            }
        }
        formarRenderers();
        _formatTextDirty = false;
    }
}

//begin @cxx 得到一行文字的个数
bool s_getLineTextNumber(const std::string& text,float fontSize,float rowWidth,int &textNumber)
{
    bool ret =  true ;
    float maxW = rowWidth ;
    int count = 0 ;

    while(true)
    {
        std::string tempChar = Helper::getSubStringOfUTF8String(text,count,1);  //截取字符串
        float tempW,tempH ;
        if(tempChar.length() == 0 )
        {
            break ;
        }
        bool bSuccess = Device::CalculateTextSize(tempChar.c_str(),fontName.c_str(),fontSize,tempW,tempH);
        if( !bSuccess )
        {
            ret = false ;
            break ;
        }
        //tempW = tempW / CC_CONTENT_SCALE_FACTOR();

        maxW -= tempW ;
        if(maxW< -tempW / 2)
        {
            break ;
        }
        count++ ;
    }

    textNumber = count ;

    return ret ;
}
//end @cxx

void RichText::handleTextRenderer(const std::string& text,glubyte opacity)
{
    auto fileExist = FileUtils::getInstance()->isFileExist(fontName);
    Label* textRenderer = nullptr;
    if (fileExist)
    {
        textRenderer = Label::createWithTTF(text,fontSize);
    } 
    else
    {
        textRenderer = Label::createWithSystemFont(text,fontSize);
    }
    float textRendererWidth = textRenderer->getContentSize().width;
    float saveLeftSpaceWidth = _leftSpaceWidth ; //@cxx
    _leftSpaceWidth -= textRendererWidth;
    if (_leftSpaceWidth < 0.0f)
    {
        float overstepPercent = (-_leftSpaceWidth) / textRendererWidth;
        std::string curText = text;
        size_t stringLength = StringUtils::getCharacterCountInUTF8String(text);

        //原来代码(原来是求出整个文字长度和文字个数,用平均长度作为每个字长度,所以混输对不齐)
        //int leftLength = stringLength * (1.0f - overstepPercent);
        //std::string leftWords = Helper::getSubStringOfUTF8String(curText,leftLength);
        //std::string cutWords = Helper::getSubStringOfUTF8String(curText,leftLength,stringLength - leftLength);

        //begin @cxx 现在改为循环计算每个字的长度
        int leftLength = 0 ;
        std::string leftWords = "" ;
        std::string cutWords = "" ;

        float rowWidth = saveLeftSpaceWidth ; //_customSize.width ;
        int textNumber = 0  ;
        if( s_getLineTextNumber( curText,rowWidth,textNumber) )//计算一行多少字
        {
            leftLength = textNumber ;
            leftWords = Helper::getSubStringOfUTF8String(curText,leftLength);
            cutWords = Helper::getSubStringOfUTF8String(curText,stringLength - leftLength);
        }
        else
        {
            leftLength = stringLength * (1.0f - overstepPercent);
            leftWords = Helper::getSubStringOfUTF8String(curText,stringLength - leftLength);
        }
        //end of @cxx

        if (leftLength > 0)
        {
            Label* leftRenderer = nullptr;
            if (fileExist)
            {
                leftRenderer = Label::createWithTTF(Helper::getSubStringOfUTF8String(leftWords,leftLength),fontSize);
            }
            else
            {
                leftRenderer = Label::createWithSystemFont(Helper::getSubStringOfUTF8String(leftWords,fontSize);
            }
            if (leftRenderer)
            {
                leftRenderer->setColor(color);
                leftRenderer->setopacity(opacity);
                pushToContainer(leftRenderer);
            }
        }

        addNewLine();
        handleTextRenderer(cutWords.c_str(),opacity);
    }
    else
    {
        textRenderer->setColor(color);
        textRenderer->setopacity(opacity);
        pushToContainer(textRenderer);
    }
}

void RichText::handleImageRenderer(const std::string& fileParh,glubyte opacity)
{
    Sprite* imageRenderer = Sprite::create(fileParh);
    handleCustomrenderer(imageRenderer);
}

void RichText::handleCustomrenderer(cocos2d::Node *renderer)
{
    Size imgSize = renderer->getContentSize();
    _leftSpaceWidth -= imgSize.width;
    if (_leftSpaceWidth < 0.0f)
    {
        addNewLine();
        pushToContainer(renderer);
        _leftSpaceWidth -= imgSize.width;
    }
    else
    {
        pushToContainer(renderer);
    }
}

void RichText::addNewLine()
{
    _leftSpaceWidth = _customSize.width;
    _elementRenders.push_back(new Vector<Node*>());
}

void RichText::formarRenderers()
{
    if (_ignoreSize)
    {
        float newContentSizeWidth = 0.0f;
        float newContentSizeHeight = 0.0f;

        Vector<Node*>* row = (_elementRenders[0]);
        float nextPosX = 0.0f;
        for (ssize_t j=0; j<row->size(); j++)
        {
            Node* l = row->at(j);
            l->setAnchorPoint(Vec2::ZERO);
            l->setPosition(nextPosX,0.0f);
            _elementRenderersContainer->addChild(l,1);
            Size iSize = l->getContentSize();
            newContentSizeWidth += iSize.width;
            newContentSizeHeight = MAX(newContentSizeHeight,iSize.height);
            nextPosX += iSize.width;
        }
        _elementRenderersContainer->setContentSize(Size(newContentSizeWidth,newContentSizeHeight));
    }
    else
    {
        float newContentSizeHeight = 0.0f;
        float *maxHeights = new float[_elementRenders.size()];

        for (size_t i=0; i<_elementRenders.size(); i++)
        {
            Vector<Node*>* row = (_elementRenders[i]);
            float maxHeight = 0.0f;
            for (ssize_t j=0; j<row->size(); j++)
            {
                Node* l = row->at(j);
                maxHeight = MAX(l->getContentSize().height,maxHeight);
            }
            maxHeights[i] = maxHeight;
            newContentSizeHeight += maxHeights[i];
        }


        float nextPosY = _customSize.height;
        float realWidth = 0 ;  //@cxx
        for (size_t i=0; i<_elementRenders.size(); i++)
        {
            Vector<Node*>* row = (_elementRenders[i]);
            float nextPosX = 0.0f;
            nextPosY -= (maxHeights[i] + _verticalSpace);

            for (ssize_t j=0; j<row->size(); j++)
            {
                Node* l = row->at(j);
                l->setAnchorPoint(Vec2::ZERO);
                l->setPosition(nextPosX,nextPosY);
                _elementRenderersContainer->addChild(l,1);
                nextPosX += l->getContentSize().width;
            }

            if( realWidth < nextPosX ) //@cxx
            {
                realWidth = nextPosX ;//@cxx
            }
        }

        float realHeight = _customSize.height - nextPosY;   //@cxx

        //富文本真实宽高
        this->xxrealSize.height = realHeight;               //@cxx
        this->xxrealSize.width = realWidth ; //_contentSize.width; //@cxx

        _elementRenderersContainer->setContentSize(_contentSize);
        delete [] maxHeights;
    }

    size_t length = _elementRenders.size();
    for (size_t i = 0; i<length; i++)
    {
        Vector<Node*>* l = _elementRenders[i];
        l->clear();
        delete l;
    }    
    _elementRenders.clear();

    if (_ignoreSize)
    {
        Size s = getVirtualRendererSize();
        this->setContentSize(s);
    }
    else
    {
        this->setContentSize(_customSize);
    }
    updateContentSizeWithTextureSize(_contentSize);
    _elementRenderersContainer->setPosition(_contentSize.width / 2.0f,_contentSize.height / 2.0f);
}

//获得富文本大小
Size RichText::xxgetRealSize()//@cxx
{
    //this->xxrealSize = this->getContentSize();
    this->formatText();   //需要手动调用
    return this->xxrealSize;
}

//下帧drawScene时调用(基类调过来),这里是富文本渲染入口
void RichText::adaptRenderers()
{
    this->formatText();
}

void RichText::pushToContainer(cocos2d::Node *renderer)
{
    if (_elementRenders.size() <= 0)
    {
        return;
    }
    _elementRenders[_elementRenders.size()-1]->pushBack(renderer);
}

void RichText::setVerticalSpace(float space)
{
    _verticalSpace = space;
}

void RichText::setAnchorPoint(const Vec2 &pt)
{
    Widget::setAnchorPoint(pt);
    _elementRenderersContainer->setAnchorPoint(pt);
}

Size RichText::getVirtualRendererSize() const
{
    return _elementRenderersContainer->getContentSize();
}

void RichText::ignoreContentAdaptWithSize(bool ignore)
{
    if (_ignoreSize != ignore)
    {
        _formatTextDirty = true;
        Widget::ignoreContentAdaptWithSize(ignore);
    }
}

std::string RichText::getDescription() const
{
    return "RichText";
}

}

NS_CC_END

3,getSubStringOfUTF8String这个截取字符串的接口要修改,它的返回值不对。

std::string Helper::getSubStringOfUTF8String(const std::string& str,std::string::size_type start,std::string::size_type length)
{
    if (length==0)
    {
        return "";
    }
    std::string::size_type c,i,ix,q,min=std::string::npos,max=std::string::npos;
    for (q=0,i=0,ix=str.length(); i < ix; i++,q++)
    {
        if (q==start)
        {
            min = i;
        }
        if (q <= start+length || length==std::string::npos)   //结束是以start位置开始,所以截取是min->max-min
        {
            max = i;
        }

        c = (unsigned char) str[i];

        if      (c<=127) i+=0;
        else if ((c & 0xE0) == 0xC0) i+=1;
        else if ((c & 0xF0) == 0xE0) i+=2;
        else if ((c & 0xF8) == 0xF0) i+=3;
        else return "";//invalid utf8
    }
    if (q <= start+length || length == std::string::npos)
    {
        max = i;
    }
    if (min==std::string::npos || max==std::string::npos)
    {
        return "";
    }
    return str.substr(min,max-min);  //@cxx 原来是: return str.substr(min,max);
}

4,在CCDevice.h中新增计算字体大小的接口,具体实现和平台相关,这里我只实现的ios平台。

static bool CalculateTextSize(const char * text,const char * fontName,float size,float &width,float &height ) ; //@cxx

5,ios平台CalculateTextSize的实现

//@cxx begin
static CGSize _my_calculateStringSize(Nsstring *str,id font,CGSize *constrainSize)
{
    CGSize textRect = CGSizeZero;
    textRect.width = constrainSize->width > 0 ? constrainSize->width
    : 0x7fffffff;
    textRect.height = constrainSize->height > 0 ? constrainSize->height
    : 0x7fffffff;


    CGSize dim;
    if(s_isIOS7OrHigher){
        NSDictionary *attibutes = @{NSFontAttributeName:font};
        dim = [str boundingRectWithSize:textRect options:(NsstringDrawingOptions)(NsstringDrawingUsesLineFragmentOrigin|NsstringDrawingUsesFontLeading) attributes:attibutes context:nil].size;
    }
    else {
        dim = [str sizeWithFont:font constrainedToSize:textRect];
    }

    dim.width = (dim.width);
    dim.height = (dim.height);

    return dim;
}

// 计算字体大小
bool Device::CalculateTextSize(const char * text,const char * fontName,float size,float &width,float &height )
{
    //float constrainWidth,float constrainHeight,
    bool ret = false ;
    CGSize dim,constrainSize ;
    dim.width = 0.0f ;
    dim.height = 0.0f;
    constrainSize.width = 0.0f ; //constrainWidth ;
    constrainSize.height = 0.0f ;// constrainHeight ;
    do
    {
        CC_BREAK_IF(! text );

        Nsstring * str          = [Nsstring stringWithUTF8String:text];
        Nsstring * fntName      = [Nsstring stringWithUTF8String:fontName];

        fntName = [[fntName lastPathComponent] stringByDeletingPathExtension];

        // create the font
        id font = [UIFont fontWithName:fntName size:size];

        if (font)
        {
            dim = _my_calculateStringSize(str,font,&constrainSize);
        }
        else
        {
            if (!font)
            {
                font = [UIFont systemFontOfSize:size];
            }

            if (font)
            {
                dim = _my_calculateStringSize(str,&constrainSize);
            }
        }

        if (font)
        {
            ret = true ;
        }
    }while(false);

    width = dim.width ;
    height = dim.height ;

    return ret;
}
//@cxx end

测试示例

auto _richText = RichText::create();
_richText->ignoreContentAdaptWithSize(false);
_richText->setContentSize(Size(100,100));

auto str1 = "是减肥了快iii速的减肥了快SD卡路附近ffm国恢复共和国fkdsjfkldsj假了jjiij经济ii的快速减肥了mshfjksdhKSDFHJKDSJFKLlfj。、里的时刻福建路口的.sdfdsjflkjlksdjfl JlkdsjflkdsfjkldsjflkdsjfkljLjkd是福建代理商福建路口的";

RichElementText* re1 = RichElementText::create(1,Color3B::WHITE,255,str1,"Marker Felt",20);

_richText->pushBackElement(re1);
_richText->setPosition(Vec2(visibleSize.width / 2,visibleSize.height / 2 + 100));
this->addChild(_richText);

系统默认的对齐效果图:

修改后的对齐效果图:

Cocos2dx-- 聊天系统之富文本(RichText)与字体对齐的更多相关文章

  1. HTML5 WebSocket实现点对点聊天的示例代码

    这篇文章主要介绍了HTML5 WebSocket实现点对点聊天的示例代码的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. 使用layui实现左侧菜单栏及动态操作tab项的方法

    这篇文章主要介绍了使用layui实现左侧菜单栏及动态操作tab项的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. ios – 在Swift的UIView中找到UILabel

    我正在尝试在我的UIViewControllers的超级视图中找到我的UILabels.这是我的代码:这是在Objective-C中推荐的方式,但是在Swift中我只得到UIViews和CALayer.我肯定在提供给这个方法的视图中有UILabel.我错过了什么?我的UIViewController中的调用:解决方法使用函数式编程概念可以更轻松地实现这一目标.

  4. ios – 在Swift中将输入字段字符串转换为Int

    所以我非常擅长制作APP广告Swift,我试图在文本字段中做一些非常简单的输入,取值,然后将它们用作Int进行某些计算.但是’vardistance’有些东西不正确它是导致错误的最后一行代码.它说致命错误:无法解开Optional.None解决方法在你的例子中,距离是一个Int?否则称为可选的Int..toInt()返回Int?因为从String到Int的转换可能失败.请参阅以下示例:

  5. 如何在iOS中检测文本(字符串)语言?

    例如,给定以下字符串:我想检测每个声明的字符串中使用的语言.让我们假设已实现函数的签名是:如果没有检测到语言,则返回可选字符串.因此,适当的结果将是:有一个简单的方法来实现它吗?

  6. xamarin – 崩溃在AccountStore.Create().保存(e.Account,“);

    在Xamarin.Forms示例TodoAwsAuth中https://developer.xamarin.com/guides/xamarin-forms/web-services/authentication/oauth/成功登录后,在aOnAuthenticationCompleted事件中,应用程序在尝试保存到Xamarin.Auth时崩溃错误说不能对钥匙串说期待着寻求帮助.解决方法看看你

  7. ios – 将视频分享到Facebook

    我正在编写一个简单的测试应用程序,用于将视频从iOS上传到Facebook.由于FacebookSDK的所有文档都在Objective-C中,因此我发现很难在线找到有关如何使用Swift执行此操作的示例/教程.到目前为止我有这个在我的UI上放置一个共享按钮,但它看起来已禁用,从我读到的这是因为没有内容设置,但我看不出这是怎么可能的.我的getVideoURL()函数返回一个NSURL,它肯定包含视

  8. xcode – 错误“线程1:断点2.1”

    我正在研究RESTAPI管理器.这是一个错误,我无法解决它.我得到的错误在下面突出显示.当我打电话给这个班级获取资源时:我评论的线打印:Thread1:breakpoint2.1我需要修复错误的建议.任何建议都非常感谢解决方法您可能在不注意的情况下意外设置了断点.单击并拖动代表断路器外部断点的蓝色刻度线以将其擦除.

  9. ios – 更改导航栏标题swift中的字符间距

    类型的值有人可以帮我这个或建议一种不同的方式来改变swift中导航栏标题中的字符间距吗?解决方法您无法直接设置属性字符串.你可以通过替换titleView来做一个技巧

  10. ios – 如何从变量访问属性或方法?

    是否可以使用变量作为Swift中方法或属性的名称来访问方法或属性?在PHP中,您可以使用$object->{$variable}.例如编辑:这是我正在使用的实际代码:解决方法你可以做到,但不能使用“纯粹的”Swift.Swift的重点是防止这种危险的动态属性访问.你必须使用Cocoa的Key-ValueCoding功能:非常方便,它完全穿过你要穿过的字符串到属性名称的桥,但要注意:这里是龙.

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部