編輯:關於Android編程
今天測試發現了游戲的一個問題,系統郵件,如果發了tab,在android上一打開郵件內容就會crash。而且他們很確定是tab的問題。
憑我多個月的經驗(確實沒多年。。。)來看,從來沒聽說在android上會因為一個tab崩潰,而且如果有這個問題,肯定會有很多人遇到,估計早就吵翻天了,搜索了一下,什麼可用信息都沒有。
於是寫個測試工程測試了一下,分別在mac下和windows下,用文本編輯工具編輯了4個txt文檔,utf有bom和無bom,內容是“ tab abcd ”,發現都能正常顯示,也不會crash。如下:
unsigned long fSize = 0; unsigned char *data = CCFileUtils::sharedFileUtils()->getFileData("tab.txt", "rb", &fSize); CCLabelTTF *label = CCLabelTTF::create((const char*)data, "abc", 30); label->setPosition(ccp(visibleSize.width/2, visibleSize.height/2)); addChild(label);
然後開始怒跟代碼,發現工程中使用了一個自定義控件,是為了實現一個富文本框的功能。所謂富文本框就是能顯示各種顏色,能顯示url,有的東西還能點的那種。但是這個東西的實現,其中有一步,是把一個utf8字符串拆開,拆成單個字符,把每個字符的紋理做出來,然後來拼圖,拼成一個文本框。那麼tab肯定會被拆成單個字符,最後發現就是在生成這個tab的紋理的時候,crash了。堆棧如下:
順便科普一下labelTTF顯示的原理,大致就是,通過字體和字號,然後調用相應平台的api,生成一張圖(image),注意是一張圖啊,然後作為紋理,設置給一個精靈。從上面的堆棧來看,就是在生成這個image的時候crash了。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+ICAgIMi7uvPV0rT6wuujrNTaQ0NUZXh0dXJlMkTPwtXStb3Jz8PmttHVu7XE1+6689K7sr2jrMjnz8KjujwvcD4KPHA+PC9wPgo8cHJlIGNsYXNzPQ=="brush:java;">bool CCTexture2D::initWithString(const char *text, const char *fontName, float fontSize, const CCSize& dimensions, CCTextAlignment hAlignment, CCVerticalTextAlignment vAlignment) { … … … … do { CCImage* pImage = new CCImage(); CC_BREAK_IF(NULL == pImage); bRet = pImage->initWithString(text, (int)dimensions.width, (int)dimensions.height, eAlign, fontName, (int)fontSize); CC_BREAK_IF(!bRet); bRet = initWithImage(pImage); CC_SAFE_RELEASE(pImage); } while (0); … … … … return bRet; } 這裡第一步是,new一個image出來,然後用文字去init這個image,然後再用這個image去init這個texture。我們接著看init這個image這裡,android下的代碼是這樣的:
bool CCImage::initWithString( const char * pText, int nWidth/* = 0*/, int nHeight/* = 0*/, ETextAlign eAlignMask/* = kAlignCenter*/, const char * pFontName/* = nil*/, int nSize/* = 0*/) { bool bRet = false; do { CC_BREAK_IF(! pText); BitmapDC &dc = sharedBitmapDC(); CC_BREAK_IF(! dc.getBitmapFromJava(pText, nWidth, nHeight, eAlignMask, pFontName, nSize)); m_pData = dc.m_pData; CC_BREAK_IF(! m_pData); m_nWidth = (short)dc.m_nWidth; m_nHeight = (short)dc.m_nHeight; m_bHasAlpha = true; m_bPreMulti = true; m_nBitsPerComponent = 8; bRet = true; } while (0); return bRet; }其中重點是getBitmapFromJava這個函數,如下
bool getBitmapFromJava(const char *text, int nWidth, int nHeight, CCImage::ETextAlign eAlignMask, const char * pFontName, float fontSize) { return getBitmapFromJavaShadowStroke( text, nWidth, nHeight, eAlignMask, pFontName, fontSize ); }從這裡就知道了,肯定是把文字,字體,字號這些東西,叫給java層,讓它們調用系統相關的東西,返回一個bitmap回來,然後就是下一步,把這個返回的image去初始化texture。但是不需要下一步了,因為到這就crash了,得到如下log:
從這個log看,大概意思就是java層在創建bitmap的時候,需要一個圖片的寬高,但是這個大小等於0了。
但是之前測試是可以顯示tab的,仔細想想,之前的測試有一個問題,就是之前的測試都是tab加其他字符的混合,這個地方因為富文本框的處理,是單個tab字符,那麼再用單個tab測試一下。果然就和上面一樣crash了。
再回到這個crash log本身,這個要生成的圖,就是寫了字的那個圖,那麼這個圖片的寬高應該取決於字符的內容和字符的大小,怎麼會是0呢。難道是因為tab在android上面會被自動忽略。馬上再寫個工程測試:
unsigned long fSize = 0; unsigned char *data = CCFileUtils::sharedFileUtils()->getFileData("tab.txt", "rb", &fSize); CCLabelTTF *label = CCLabelTTF::create((const char*)data, "abc", 30); label->setPosition(ccp(visibleSize.width/2, visibleSize.height/2)); CCLayerColor *col = CCLayerColor::create(ccc4(123, 255,0 , 255)); col->setContentSize(label->getContentSize()); col->ignoreAnchorPointForPosition(false); col->setAnchorPoint(ccp(0.5, 0.5)); col->setPosition(ccp(label->getPosition().x,label->getPosition().y)); addChild(col); addChild(label);
如果在cocos2dx上是這樣,但是他最後會調用到android系統的java層去生成這個bitmap,說明這個不是cocos2dx的問題,那麼在android應用上,tab會不會被忽略呢,果斷開個工程再測試,如下:
tabTest Hello world! Settings
接上次的。 首先Launcher實現了LauncherModel.Callbacks接口,APP信息數據加載成功後 ,回調接口把app信息顯示到Launcher的 wor
(一).前言:今天我們的項目繼續更新,今天我們主要講解MVP開發模式以及具體實例。 (二).簡介:MVP(Model ViewPrese
時候我們需要監聽ScroView的滑動情況,比如滑動了多少距離,是否滑到布局的頂部或者底部。可惜的是SDK並沒有相應的方法,不過倒是提供了一個 復制代碼 代碼如下:pro
一丶音樂播放頁實現功能1.音樂格信息顯示,大圖顯示2.播放功能,上一曲,下一曲,暫停3.音樂進度顯示4.切換播放模式二丶顯示效果三丶原理及代碼實現1.自定義接口回調的方法