在規定區域內自動調整文字位置
問題
最近在做一個需求,就是塗鴉時,在繪製的圖形旁邊通過文字顯示相關資訊.先給大家看看最終的效果:

效果圖
一開始的時候被這個問題難倒了,怎麼找到合適的位置顯示文字資訊,讓它們既不超出顯示範圍,又互不重疊?
解決方案
如果考慮不能重疊的問題,就需要在圖形四周的位置遍歷一遍直到沒有跟其他文字重疊,加上繪製的圖形是可以移動問題,這樣問題就更復雜了.於是我只能簡單化,尋找代價低又基本能滿足要求的方式.
首先,定義一個適配規則: 文字優先顯示在左邊,如果超出顯示區域則直接顯示在右邊,這種右邊的情況下如果也超出了顯示區域,則往左邊偏移文字文字,使其剛好在顯示區域邊上.確定了左右位置後,接著處理垂直方向,文字優先顯示在跟圖形最上邊位置齊平的位置,如果文字底部超出顯示區域,則往上偏移文字,使其底部剛好在顯示區域底邊.
以矩形為例,顯示效果如下:

分析圖
對照規則,標註如下:
文字優先顯示在左邊( 圖1,2,4,6,7,10
),如果超出顯示區域則直接顯示在右邊( 圖3,5
),這種右邊的情況下如果也超出了顯示區域,則往左邊偏移文字文字,使其剛好在顯示區域邊上( 圖9
).確定了左右位置後,接著處理垂直方向,文字優先顯示在跟圖形最上邊位置齊平的位置( 除圖8外的所有圖形
),如果文字底部超出顯示區域,則往上偏移文字,使其底部剛好在顯示區域底邊( 圖8
).
這樣就限定了影象顯示在規定區域內啦!至於如何解決文字直接重疊的問題,這裡並不能直接給出答案,筆者上面只是把問題簡單化,提供解決問題的思路.
實現
最後給出主要程式碼的程式碼實現,包括了矩形,圓,線的文字位置調整:
String msg = getInfo(); StaticLayout textStaticLayout = new StaticLayout(msg, mTextPaint, (int) getMaxWidth(msg, mTextPaint) + 1, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); mTextBounds.set(0, 0, textStaticLayout.getWidth(), textStaticLayout.getHeight()); float x = 0, y = 0; if (getShape() == DoodleShape.HOLLOW_RECT || getShape() == DoodleShape.HOLLOW_CIRCLE) { float diff = -mTextPaint.getTextSize() / 3 ; x = mShapeBounds.right - diff; y = mShapeBounds.top; // 左右限定, 優先在右 if (x + getLocation().x + mTextBounds.width() > getDoodle().getBitmap().getWidth()) { x = mShapeBounds.left + diff - textStaticLayout.getWidth(); } // 移到左邊後,左邊邊界限定 if (x + getLocation().x < 0) { x = 0; } // 上下限定,優先在上 if (y + getLocation().y + mTextBounds.height() > getDoodle().getBitmap().getHeight()) { y = mShapeBounds.bottom - textStaticLayout.getHeight(); } if (y + getLocation().y < 0) { y = 0; } } else { //線 PointF sxy = this.mSxy; // 起點 PointF dxy = this.mDxy; // 終點 if (this.mSxy.x > this.mDxy.x) { // 保證起點在左,終點在右的相對位置 sxy = this.mDxy; dxy = this.mSxy; } x = dxy.x + mTextPaint.getTextSize() / 3; y = dxy.y; // 左右限定, 優先在右 if (x + getLocation().x + mTextBounds.width() > getDoodle().getBitmap().getWidth()) { x = sxy.x - mTextPaint.getTextSize() / 3 - textStaticLayout.getWidth(); y = sxy.y; } // 移到左邊後,左邊邊界限定 if (x + getLocation().x < 0) { x = 0; } // 上下限定, 優先在上 if (y + getLocation().y + mTextBounds.height() > getDoodle().getBitmap().getHeight()) { y = y - ((y + getLocation().y + mTextBounds.height()) - getDoodle().getBitmap().getHeight()); } if (y + getLocation().y < 0) { y = 0; } } canvas.save(); canvas.translate(x, y); textStaticLayout.draw(canvas); canvas.restore();
文中一開始的效果的塗鴉程式碼在我的開源框架的開源專案 >>>>開源專案Doodle!一個功能強大,可自定義和可擴充套件的塗鴉框架 。謝謝大家支援!!!