问题
最近在做一个需求,就是涂鸦时,在绘制的图形旁边通过文字显示相关信息.先给大家看看最终的效果:
[图片上传失败...(image-7e7206-1550580943101)]
一开始的时候被这个问题难倒了,怎么找到合适的位置显示文字信息,让它们既不超出显示范围,又互不重叠?
解决方案
如果考虑不能重叠的问题,就需要在图形四周的位置遍历一遍直到没有跟其他文字重叠,加上绘制的图形是可以移动问题,这样问题就更复杂了.于是我只能简单化,寻找代价低又基本能满足要求的方式.
首先,定义一个适配规则:文字优先显示在左边,如果超出显示区域则直接显示在右边,这种右边的情况下如果也超出了显示区域,则往左边偏移文字文字,使其刚好在显示区域边上.确定了左右位置后,接着处理垂直方向,文字优先显示在跟图形最上边位置齐平的位置,如果文字底部超出显示区域,则往上偏移文字,使其底部刚好在显示区域底边.
以矩形为例,显示效果如下:
分析图
对照规则,标注如下:
文字优先显示在左边(图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();
总结
上面仅是处理文字边界范围内显示,除此之外还会存在文字之间重叠的问题.这里我们可以参照上面的思路,优化逻辑,比如在左右限定时,如果满足右边显示,则增加判断是否跟其他图形的文字重叠,如果不重叠则确定右边显示,如果有重叠则换成在左边显示.思路很简单即在每一步判断后再增加一条更严格的判断,当然我们无法做到所有文字都不重叠(不然需要太多判断条件),只要能做到尽量不重叠即可.
作者:远方的风景2018
链接:https://www.jianshu.com/p/5823d9c2d3b1
共同学习,写下你的评论
评论加载中...
作者其他优质文章