cocos2dx实现RichText中英文不被强行截断

  这几天需要使用RichText实现富文本的需要,看了下cocos2dx3.3中已实现的RichText,发现写的还是比较粗糙的。如果在富文本中使用英文的话,分段时会把单词强行截断,这是个烦恼的问题,一般英文的换行都是根据“ ”来分段。

  查看问题所在,发现在RichText中的handleTextRenderer(const std::string& text, const std::string& fontName, float fontSize, const Color3B &color, GLubyte opacity)函数中,该函数的作用就是判断传入的text是否在改行已超过指定宽度,如果否继续放该行,否则就打断text,前部分放该行,后部分放在新的一行中,而他截断方式竟然是使用平均长度来分,这方式让人有点。。。于是参考label类的自动换行,自己重写了handleTextRenderer方法。

  代码如下:

  

  auto fileExist = FileUtils::getInstance()->isFileExist(fontName);
  Label* textRenderer = nullptr;
  if (fileExist)
  {
    textRenderer = Label::createWithTTF(text, fontName, fontSize);
  }
  else
  {
    textRenderer = Label::createWithSystemFont(text, fontName, fontSize);
  }

  if (!textRenderer){

  return;
  }

  float textRendererWidth = textRenderer->getContentSize().width;
  float leftSpaceWidth = _leftSpaceWidth;
  leftSpaceWidth -= textRendererWidth;
  if (leftSpaceWidth < 0.0f)
  {
  std::string curText = text;
  //寻找空格位置
  int found = text.find_last_of(" ");

  int stringLength = text.length();
  //判断text是否有空格
  if (found >= stringLength - 1 || found == -1)
  {
    addNewLine();
    handleTextRenderer(curText.c_str(), fontName, fontSize, color, opacity);
  }
  else
  {
    std::string leftWords = Helper::getSubStringOfUTF8String(curText,0,found);
    std::string cutWords = Helper::getSubStringOfUTF8String(curText, found, stringLength - found);

    while (true)
    {
      if (leftWords.length() > 0)
      {
        textRenderer->setString(leftWords);

        float leftRendererWidth = textRenderer->getContentSize().width;
        float tmpLeftSpaceWidth = _leftSpaceWidth;
        tmpLeftSpaceWidth -= leftRendererWidth;

        if (tmpLeftSpaceWidth < 0.0f)
        {
          int leftWordsLen = (int)leftWords.length();
          if (leftWordsLen <= 0)
          {
            break;
          }
          else
          {
            //cut char one by one to get the fit length
            int foundPos = leftWords.find_last_of(" ");

            if (foundPos >= leftWords.length() - 1 || foundPos == -1)
            {
              //剩余字符串已没有“ ”
              break;
            }
            leftWords = Helper::getSubStringOfUTF8String(text, 0, foundPos);
            cutWords = Helper::getSubStringOfUTF8String(text, foundPos, stringLength - foundPos);
          }
        }
        else {
          //if _leftSpaceWidth > 0 break
          break;
        }
      }
      else {
        //if leftWords is empty, break
        break;
      }
    }

    if (textRenderer)
    {
      textRenderer->setString(leftWords);
      float leftRendererWidth = textRenderer->getContentSize().width;
      float leftSpaceWidth = _leftSpaceWidth;
      leftSpaceWidth -= leftRendererWidth;
      if (leftSpaceWidth < 0)
      {
        addNewLine();
        handleTextRenderer(cutWords.c_str(), fontName, fontSize, color, opacity);

        return;
      }
      else
      {
        _leftSpaceWidth = leftSpaceWidth;

        textRenderer->setColor(color);
        textRenderer->setOpacity(opacity);
        pushToContainer(textRenderer);
      }
    }
    addNewLine();
    handleTextRenderer(cutWords.c_str(), fontName, fontSize, color, opacity);
   }
  }
  else
  {
    _leftSpaceWidth = leftSpaceWidth;

    textRenderer->setColor(color);
    textRenderer->setOpacity(opacity);
    pushToContainer(textRenderer);
  }

  我的思路就是判断该text是否超框,不是就继续放这行,是的话就判断text是否有“ ”,无则新增一行,有“ ”的话逐个判断“ ”位置前的text内容是否超框,直到找到一个不超框的放在这一行,“ ”后的内容放下一行。

posted @ 2016-07-14 15:17  泫鱼  阅读(2382)  评论(1编辑  收藏  举报