美文网首页Android开发Android技术知识Android开发
在规定区域内自动调整文字位置

在规定区域内自动调整文字位置

作者: 远方的风景2018 | 来源:发表于2019-02-14 20:43 被阅读1次

    问题

    最近在做一个需求,就是涂鸦时,在绘制的图形旁边通过文字显示相关信息.先给大家看看最终的效果:

    效果图

    一开始的时候被这个问题难倒了,怎么找到合适的位置显示文字信息,让它们既不超出显示范围,又互不重叠?

    解决方案

    如果考虑不能重叠的问题,就需要在图形四周的位置遍历一遍直到没有跟其他文字重叠,加上绘制的图形是可以移动问题,这样问题就更复杂了.于是我只能简单化,寻找代价低又基本能满足要求的方式.

    首先,定义一个适配规则:文字优先显示在左边,如果超出显示区域则直接显示在右边,这种右边的情况下如果也超出了显示区域,则往左边偏移文字文字,使其刚好在显示区域边上.确定了左右位置后,接着处理垂直方向,文字优先显示在跟图形最上边位置齐平的位置,如果文字底部超出显示区域,则往上偏移文字,使其底部刚好在显示区域底边.

    以矩形为例,显示效果如下:

    分析图

    对照规则,标注如下:

    文字优先显示在左边(图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!一个功能强大,可自定义和可扩展的涂鸦框架。谢谢大家支持!!!

    相关文章

      网友评论

        本文标题:在规定区域内自动调整文字位置

        本文链接:https://www.haomeiwen.com/subject/jtvyeqtx.html