android文字动态环绕图片效果

目录

效果展示

代码分析

效果展示

代码分析

demo中的效果是手指拖动红色方块,文字自动排版,达到动态环绕的效果。

这里是通过继承View复写onDraw方法实现的。

package com.example.allen.flowtext;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class FlowTextView extends View {

    private String text = "";
    private Paint paint;
    private Paint imgPaint;

    //图片宽高
    private static int IMG_WIDTH = 170;
    private static int IMG_HEIGHT = 170;

    //文字高度,和文字宽度(所有文字的)
    private int textHeight, textWidth;

    //控件宽高(这里是重点表示排版的算法逻辑,onMeasure方法就没做定义,直接写死以充满整个父控件)
    private int width, height;

    //图片的矩形区域
    private Rect imgRect;

    //图片的左下角坐标(控件坐标,左上角为0,0)
    private int rectX, rectY;

    //单个文字的宽高
    private float wordWidth, wordHeight;

    //当前绘制到的位置坐标
    private float currentX, currentY;


    public FlowTextView(Context context) {
        super(context);
    }

    //初始化,文字样式可以在此设置
    public FlowTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        imgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.BLACK);
        paint.setTextSize(50f);
        imgPaint.setColor(Color.RED);

    }

    public FlowTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);//主意布局中不可以为at_most
        width = getMeasuredWidth();
        height = getMeasuredHeight();
        measureTextHeight();
        imgRect = new Rect(rectX, rectY, rectX + IMG_WIDTH, rectY + IMG_HEIGHT);
        currentX = 0;
        currentY = wordHeight;
    }

    public void setText(String text) {
        this.text = text;
        rectX = 200;
        rectY = 200;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        currentX = 0;
        currentY = wordHeight;
        for (int i = 0; i < text.length(); i++) {
            String str = text.substring(i, i + 1);
            if (currentX > width - wordWidth) {//换行
                currentY += wordHeight;
                currentX = 0;
            }
            if (currentX <= imgRect.left && currentY < imgRect.bottom && currentY >= imgRect.top) {
                if (currentX + wordWidth > imgRect.left) {
                    currentX = imgRect.right;
                }
            }
            if (currentY - wordHeight < imgRect.bottom && currentX < imgRect.right && currentX + wordWidth > imgRect.left) {
                if (currentY > imgRect.top) {
                    currentY = imgRect.bottom + wordHeight;
                }
            }

            canvas.drawText(str, currentX, currentY, paint);
            currentX += wordWidth;
        }
        RectF rectF = new RectF(imgRect);
        canvas.drawRoundRect(rectF, 40f, 40f, imgPaint);


    }

    private boolean isDrag;
    private int offsetX, offsetY;


    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                int x = (int) event.getX();
                int y = (int) event.getY();
                if (imgRect.contains(x, y)) {
                    isDrag = true;
                    offsetX = x - rectX;
                    offsetY = y - rectY;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                int moveX = (int) event.getX();
                int moveY = (int) event.getY();
                if (isDrag) {
                    rectX = moveX - offsetX;
                    rectY = moveY - offsetY;
                    if (rectX < 0)
                        rectX = 0;

                    if (rectY < 0) {
                        rectY = 0;
                    }

                    if (rectX > width - IMG_WIDTH) {
                        rectX = width - IMG_WIDTH;
                    }

                    if (rectY > height - IMG_HEIGHT) {
                        rectY = height - IMG_HEIGHT;
                    }

                }
                imgRect.left = rectX;
                imgRect.top = rectY;
                imgRect.right = imgRect.left + IMG_WIDTH;
                imgRect.bottom = imgRect.top + IMG_HEIGHT;
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                isDrag = false;
                offsetX = 0;
                offsetY = 0;
                break;
        }
        return true;
    }

    private void measureTextHeight() {
        Rect rect = new Rect();
        paint.getTextBounds(text, 0, text.length(), rect);
        textWidth = rect.width();//文字宽
        textHeight = rect.height();//文字高

        //单个文字宽高
        wordWidth = textWidth * 1.0f / text.length();
        wordHeight = textHeight * 1.0f;
    }

}

重点是onDraw方法,绘制是以单个文字为单元,每次绘制时判断图片位置是否冲突。另外还多了个换行逻辑。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值