最近在作一個需求,就是塗鴉時,在繪製的圖形旁邊經過文字顯示相關信息.先給你們看看最終的效果:java
一開始的時候被這個問題難倒了,怎麼找到合適的位置顯示文字信息,讓它們既不超出顯示範圍,又互不重疊?git
若是考慮不能重疊的問題,就須要在圖形四周的位置遍歷一遍直到沒有跟其餘文字重疊,加上繪製的圖形是能夠移動問題,這樣問題就更復雜了.因而我只能簡單化,尋找代價低又基本能知足要求的方式.github
首先,定義一個適配規則:文字優先顯示在左邊,若是超出顯示區域則直接顯示在右邊,這種右邊的狀況下若是也超出了顯示區域,則往左邊偏移文字文字,使其恰好在顯示區域邊上.肯定了左右位置後,接着處理垂直方向,文字優先顯示在跟圖形最上邊位置齊平的位置,若是文字底部超出顯示區域,則往上偏移文字,使其底部恰好在顯示區域底邊.canvas
以矩形爲例,顯示效果以下:框架
對照規則,標註以下:優化
文字優先顯示在左邊(圖1,2,4,6,7,10
),若是超出顯示區域則直接顯示在右邊(圖3,5
),這種右邊的狀況下若是也超出了顯示區域,則往左邊偏移文字文字,使其恰好在顯示區域邊上(圖9
).肯定了左右位置後,接着處理垂直方向,文字優先顯示在跟圖形最上邊位置齊平的位置(除圖8外的全部圖形
),若是文字底部超出顯示區域,則往上偏移文字,使其底部恰好在顯示區域底邊(圖8
).this
這樣就限定了圖像顯示在規定區域內啦!spa
最後給出主要代碼的代碼實現,包括了矩形,圓,線的文字位置調整:rest
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();
複製代碼
上面僅是處理文字邊界範圍內顯示,除此以外還會存在文字之間重疊的問題.這裏咱們能夠參照上面的思路,優化邏輯,好比在左右限定時,若是知足右邊顯示,則增長判斷是否跟其餘圖形的文字重疊,若是不重疊則肯定右邊顯示,若是有重疊則換成在左邊顯示.思路很簡單即在每一步判斷後再增長一條更嚴格的判斷,固然咱們沒法作到全部文字都不重疊(否則須要太多判斷條件),只要能作到儘可能不重疊便可.code
文中一開始的效果的塗鴉代碼在個人開源框架的開源項目>>>>開源項目Doodle!一個功能強大,可自定義和可擴展的塗鴉框架。謝謝你們支持!!!