iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Android实现文本排版
  • 945
分享到

Android实现文本排版

Android 2022-06-06 08:06:54 945人浏览 八月长安
摘要

  在项目中有一个小功能需要实现,就是对多行文本进行排版布局,每一行的内容又分为两部分,左边为标题,右边为描述,左边内容长度不确定,右边的内容需要对齐,如有换行也需要

  在项目中有一个小功能需要实现,就是对多行文本进行排版布局,每一行的内容又分为两部分,左边为标题,右边为描述,左边内容长度不确定,右边的内容需要对齐,如有换行也需要对齐右边的文本。

一、效果图

       

可以看到内容分成了两部分,左边的颜色与右边不一致,右边的描述文案统一对齐。

二、实现方案

       以上功能,由于输入内容输入行数不确定,并且左边的文案长度也不确定,因此不能直接在布局中实现,基于此这里主要实现了以下6种方式

方案1

       采用自定义控件的方式,继承TextView,重新onDraw函数,实现如下:



public class TypographyView1 extends TextView {
  private Paint leftPaint = new Paint();
  private Paint rightPaint = new Paint();
  private int fullWidth;
  private float textSize;
  private JSONArray array;
  private int middlePadding = 0;
  float maxLeftWidth = 0;
  int itemSize = 0;
  public TypographyView1(Context context) {
    super(context);
    init();
  }
  public TypographyView1(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  }
  public TypographyView1(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
  }
  private void init() {
    textSize = getResources().getDimensionPixelSize(R.dimen.text_size_13);
    leftPaint.setAntiAlias(true);
    leftPaint.setTextSize(textSize);
    leftPaint.setColor(getResources().getColor(R.color.color_black_999999));
    rightPaint.setAntiAlias(true);
    rightPaint.setTextSize(textSize);
    rightPaint.setColor(getResources().getColor(R.color.color_black));
    middlePadding = getResources().getDimensionPixelSize(R.dimen.padding_value);
  }
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    fullWidth = getWidth();// 整个textView的宽度
  }
  public void setText(jsONArray array) {
    this.array = array;
    if (array != null) {
      try {
        int size = itemSize = array.length();
        for (int i = 0; i < size; ++i) {
          JSONArray o = (JSONArray) array.get(i);
          String key = o.getString(0);
          String value = o.getString(1);
          if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) {
            itemSize--;
            continue;
          }
          float curWidth = leftPaint.measureText(key);
          if (curWidth > maxLeftWidth) {
            maxLeftWidth = curWidth;
          }
        }
        maxLeftWidth = maxLeftWidth + middlePadding;
        invalidate();
      } catch (Exception e) {
      }
    }
  }
  boolean setHeight = false;
  @Override
  protected void onDraw(canvas canvas) {
    if (array == null) {
      return;
    }
    int lineCount = 0;
    try {
      JSONArray item;
      float offsetY;
      for (int i = 0; i < itemSize; ++i) {
        item = (JSONArray) array.get(i);
        offsetY = (lineCount + 1) * textSize;
        canvas.drawText(item.getString(0), 0, offsetY, leftPaint);
        String value = item.getString(1);
        float valueWidth = rightPaint.measureText(value);
        if (valueWidth > fullWidth - maxLeftWidth) {// 一行显示不完
          char[] textCharArray = value.toCharArray();
          float charWidth;
          float drawWidth = maxLeftWidth;
          for (int j = 0; j < textCharArray.length; j++) {
            charWidth = rightPaint.measureText(textCharArray, j, 1);
            if (fullWidth - drawWidth < charWidth) {
              lineCount++;
              drawWidth = maxLeftWidth;
              offsetY += textSize;
            }
            canvas.drawText(textCharArray, j, 1, drawWidth, offsetY, rightPaint);
            drawWidth += charWidth;
          }
        } else {
          canvas.drawText(value, maxLeftWidth, offsetY, rightPaint);
        }
        lineCount += 2;
      }
      if (!setHeight) {
        setHeight((lineCount + 1) * (int) textSize);
        setHeight = true;
      }
    } catch (JSONException e) {
      e.printStackTrace();
    }
  }
}

       添加了setText(JSONArray array)作为数据输入,并且在这里面测量了左边title的最大宽度,之后调用invalidate触发重绘,在onSizeChanged获取整个控件的宽度,重绘会调用onDraw函数,这里不需要调用super函数,TextView的onDraw函数做了非常多的操作,解析传入的数据,分别一行一行调用canvas来进行drawText操作,当绘制描述时,先计算宽度,如果超过剩余控件说明需要换行,最后调用setHeight设置高度,这个加一个判断条件,因为会触发requestLayout()进行重新布局和invalidate()进行重绘,如果不加判断会一直重绘。

方案2

       方式2与方式1差不多,不同为所有计算都在onDraw函数中:



public class TypographyView2 extends TextView {
  private Paint paint1 = new Paint();
  private Paint paint2 = new Paint();
  private int middlePadding = 0;
  int width;
  private float textSize;
  private JSONArray array;
  public TypographyView2(Context context) {
    super(context);
    init();
  }
  public TypographyView2(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  }
  public TypographyView2(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
  }
  private void init() {
    textSize = getResources().getDimensionPixelSize(R.dimen.text_size_13);
    paint1.setAntiAlias(true);
    paint1.setTextSize(textSize);
    paint1.setColor(getResources().getColor(R.color.color_black_999999));
    paint2.setAntiAlias(true);
    paint2.setTextSize(textSize);
    paint2.setColor(getResources().getColor(R.color.color_black));
    middlePadding = getResources().getDimensionPixelSize(R.dimen.padding_value);
  }
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    width = getWidth();// 整个textView的宽度
  }
  public void setText(JSONArray array) {
    this.array = array;
    if (array != null) {
      invalidate();
    }
  }
  boolean setHeight = false;
  @Override
  protected void onDraw(Canvas canvas) {
    // super.onDraw(canvas);
    int lineCount = 0;
    int size = array.length();
    float maxLeftWidth = 0;
    float drawWidth = 0;
    try {
      for (int i = 0; i < size; ++i) {
        JSONArray o = (JSONArray) array.get(i);
        String key = o.getString(0);
        float v = paint1.measureText(key);
        if (v > maxLeftWidth) {
          maxLeftWidth = v;
        }
      }
      maxLeftWidth = maxLeftWidth + middlePadding;
      for (int i = 0; i < size; ++i) {
        JSONArray o = (JSONArray) array.get(i);
        String key = o.getString(0);
        canvas.drawText(key, 0, (lineCount + 1) * textSize, paint1);
        String value = o.getString(1);
        char[] textCharArray = value.toCharArray();
        float charWidth;
        drawWidth = maxLeftWidth;
        for (int j = 0; j < textCharArray.length; j++) {
          charWidth = paint1.measureText(textCharArray, j, 1);
          if (width - drawWidth < charWidth) {
            lineCount++;
            drawWidth = maxLeftWidth;
          }
          canvas.drawText(textCharArray, j, 1, drawWidth, (lineCount + 1) * textSize, paint2);
          drawWidth += charWidth;
        }
        lineCount += 2;
      }
      if (!setHeight) {
        setHeight((lineCount + 1) * (int) textSize + 5);
        setHeight = true;
      }
    } catch (JSONException e) {
      e.printStackTrace();
    }
  }
}

       该方案的实现是不太好的,方案1也是在此基础上进行调整的,在这里放出来只是为了说明,所有的计算不要全部放在onDraw里面,因为该方法可能会反复调用多次,这样就降低了性能。

方案3

       将数据源拼接成SpannableString,重写onDraw函数,根据内容draw每一个字符:



public class TypographyView3 extends TextView {
  private Paint leftPaint = new Paint();
  private Paint rightPaint = new Paint();
  int width;
  private String text;
  private float textSize;
  float maxLeftWidth = 0;
  private int middlePadding = 0;
  public TypographyView3(Context context) {
    super(context);
    init();
  }
  public TypographyView3(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  }
  public TypographyView3(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
  }
  private void init() {
    textSize = getResources().getDimensionPixelSize(R.dimen.text_size_13);
    textSize = getResources().getDimensionPixelSize(R.dimen.text_size_13);
    leftPaint.setAntiAlias(true);
    leftPaint.setTextSize(textSize);
    leftPaint.setColor(getResources().getColor(R.color.color_black_999999));
    rightPaint.setAntiAlias(true);
    rightPaint.setTextSize(textSize);
    rightPaint.setColor(getResources().getColor(R.color.color_black));
    middlePadding = getResources().getDimensionPixelSize(R.dimen.padding_value);
  }
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    width = getWidth();// 整个textView的宽度
  }
  public void setText(JSONArray data) {
    if (data == null) {
      return;
    }
    try {
      int size = data.length();
      for (int i = 0; i < size; ++i) {
        JSONArray o = (JSONArray) data.get(i);
        String key = o.getString(0);
        float v = leftPaint.measureText(key);
        if (v > maxLeftWidth) {
          maxLeftWidth = v;
        }
      }
      maxLeftWidth += middlePadding;
      SpannableStringBuilder ssb = new SpannableStringBuilder();
      for (int i = 0; i < size; ++i) {
        addItem((JSONArray) data.get(i), ssb, i != 0);
      }
      setText(ssb, BufferType.SPANNABLE);
    } catch (Exception e) {
    }
  }
  private void addItem(JSONArray item, SpannableStringBuilder ssb, boolean breakLine) {
    try {
      if (item == null || item.length() == 0) {
        return;
      }
      String key = item.getString(0);
      String value = (item.length() >= 2) ? item.getString(1) : "";
      if (TextUtils.isEmpty(key) && TextUtils.isEmpty(value)) {
        return;
      }
      if (breakLine) {// 换行
        ssb.append("\r\n");
        ssb.append("\r\n");
      }
      SpannableString span = new SpannableString(key);
      //      span.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorAccent)), 0, key
      // .length(),
      //          Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      ssb.append(span);
      ssb.append(value);
    } catch (JSONException e) {
      e.printStackTrace();
    }
  }
  @Override
  protected void onDraw(Canvas canvas) {
    // super.onDraw(canvas);
    int lineCount = 0;
    text = this.getText().toString();
    if (text == null)
      return;
    char[] textCharArray = text.toCharArray();
    // 已绘的宽度
    float drawWidth = 0;
    float charWidth;
    Paint paint = leftPaint;
    for (int i = 0; i < textCharArray.length; i++) {
      charWidth = leftPaint.measureText(textCharArray, i, 1);
      if (textCharArray[i] == '\n') {
        lineCount++;
        drawWidth = 0;
        paint = leftPaint;
        continue;
      }
      if (width - drawWidth < charWidth) {
        lineCount++;
        drawWidth = maxLeftWidth;
      }
      if (i > 1 && textCharArray[i - 1] == ':') {
        drawWidth = maxLeftWidth;
        paint = rightPaint;
      }
      canvas.drawText(textCharArray, i, 1, drawWidth, (lineCount + 1) * textSize, paint);
      drawWidth += charWidth;
    }
    //may be need set height
    //setHeight((lineCount + 1) * (int) textSize + 5);
  }
}

       这里先计算左边title的最大宽度,同时将所有的数据拼接成一个SpannableStringBuilder,调用setText函数会触发重绘,在onDraw函数中进行处理,由于未重新super函数,因此SpannableString的setSpan函数失效,该方案主要根据分隔符来进行分割,因此分隔符需要唯一。

方案4

       采用GridLayout方式实现,但是原始控件有展示问题,因此对此进行了修改:


public class Typography4Activity extends BaseActivity {
  public static void start(Context context) {
    Intent intent = new Intent();
    intent.setClass(context, Typography4Activity.class);
    context.startActivity(intent);
  }
  private LinearLayout root;
  private Paint leftPaint = new Paint();
  private float textSize;
  private float maxLeftWidth;
  private int middlePadding = 0;
  private float maxRightWidth;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    root = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.activity_typography4, null);
    setContentView(root);
    initPaint();
    findViews();
    loadData();
  }
  private void initPaint() {
    textSize = getResources().getDimensionPixelSize(R.dimen.text_size_13);
    leftPaint.setAntiAlias(true);
    leftPaint.setTextSize(textSize);
    leftPaint.setColor(getResources().getColor(R.color.color_black_999999));
    middlePadding = getResources().getDimensionPixelSize(R.dimen.padding_value);
  }
  private void findViews() {
  }
  private void loadData() {
    addGridLayout(DataSource.getArray());
    TextView view = new TextView(this);
    view.setText("修改后的实现");
    view.setGravity(Gravity.CENTER);
    view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 160));
    root.addView(view);
    addModifyGridLayout(DataSource.getArray());
  }
  private void addGridLayout(JSONArray data) {
    try {
      GridLayout layout = createGridLayout();
      int size = data.length();
      for (int i = 0; i < size; ++i) {
        JSONArray item = (JSONArray) data.get(i);
        String key = item.getString(0);
        String value = (item.length() >= 2) ? item.getString(1) : "";
        GridLayout.Spec row = GridLayout.spec(i);
        GridLayout.Spec col1 = GridLayout.spec(0);
        GridLayout.Spec col2 = GridLayout.spec(1);
        GridLayout.LayoutParams params = new GridLayout.LayoutParams(row, col1);
        TextView title = getLeftTextView(key);
        layout.addView(title, params);
        params = new GridLayout.LayoutParams(row, col2);
        TextView desc = getRightTextView(value);
        layout.addView(desc, params);
      }
      root.addView(layout);
    } catch (Exception e) {
    }
  }
  @NonNull
  private TextView getRightTextView(String value) {
    TextView desc = new TextView(this);
    desc.setTextSize(13);
    desc.setTextColor(getResources().getColor(R.color.black));
    desc.setText(value);
    return desc;
  }
  @NonNull
  private TextView getLeftTextView(String key) {
    TextView title = new TextView(this);
    title.setText(key);
    title.setPadding(0, middlePadding, middlePadding, 0);
    title.setTextColor(getResources().getColor(R.color.color_black_999999));
    title.setTextSize(13);
    return title;
  }
  private void addModifyGridLayout(JSONArray data) {
    try {
      calculateLeftMaxWidth(data);
      GridLayout layout = createGridLayout();
      int size = data.length();
      for (int i = 0; i < size; ++i) {
        JSONArray item = (JSONArray) data.get(i);
        GridLayout.Spec row = GridLayout.spec(i);
        String key = item.getString(0);
        GridLayout.Spec col1 = GridLayout.spec(0);
        GridLayout.LayoutParams params = new GridLayout.LayoutParams(row, col1);
        TextView title = getLeftTextView(key);
        layout.addView(title, params);
        String value = (item.length() >= 2) ? item.getString(1) : "";
        GridLayout.Spec col2 = GridLayout.spec(1);
        params = new GridLayout.LayoutParams(row, col2);
        TextView desc = getRightTextView(value);
        params.width = (int) maxRightWidth;
        params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
        layout.addView(desc, params);
      }
      root.addView(layout);
    } catch (Exception e) {
    }
  }
  private void calculateLeftMaxWidth(JSONArray data) {
    try {
      DisplayUtil.init(this);// 这个可以在应用程序起来的时候init
      int size = data.length();
      for (int i = 0; i < size; ++i) {
        JSONArray o = (JSONArray) data.get(i);
        String key = o.getString(0);
        String value = o.getString(1);
        if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) {
          continue;
        }
        float curWidth = leftPaint.measureText(key);
        if (curWidth > maxLeftWidth) {
          maxLeftWidth = curWidth;
        }
      }
      maxLeftWidth = maxLeftWidth + middlePadding;
      maxRightWidth = DisplayUtil.screenWidth - DisplayUtil.dp2px(this, 32 + 10) - maxLeftWidth;
    } catch (Exception e) {
    }
  }
  private GridLayout createGridLayout() {
    GridLayout layout = new GridLayout(this);
    layout.setColumnCount(2);
    //layout.setRowCount(5);
    layout.setOrientation(GridLayout.HORIZONTAL);
    return layout;
  }
}

       如果直接创建一个GridLayout,里面添加每一项,如果描述过长都导致显示不全,这个是系统的一个bug,计算的宽度有问题,因此需要对此方案进行更改。
       更改方式为先计算左边占用的最大宽度,在添加右边的项时,设置布局参数控制最大的长度。

方案5

       采用每一行一个布局,手动一行一行进行添加:


public class Typography5Activity extends BaseActivity {
  public static void start(Context context) {
    Intent intent = new Intent();
    intent.setClass(context, Typography5Activity.class);
    context.startActivity(intent);
  }
  private LinearLayout root;
  private Paint leftPaint = new Paint();
  private float textSize;
  private float maxLeftWidth;
  private int middlePadding = 0;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    root = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.activity_typography5, null);
    setContentView(root);
    initPaint();
    loadData();
  }
  private void initPaint() {
    textSize = getResources().getDimensionPixelSize(R.dimen.text_size_13);
    leftPaint.setAntiAlias(true);
    leftPaint.setTextSize(textSize);
    leftPaint.setColor(getResources().getColor(R.color.color_black_999999));
    middlePadding = getResources().getDimensionPixelSize(R.dimen.padding_value);
  }
  private void loadData() {
    JSONArray array = DataSource.getArray();
    calculateLeftMaxWidth(array);
    if (array != null) {
      try {
        int size = array.length();
        for (int i = 0; i < size; ++i) {
          JSONArray o = (JSONArray) array.get(i);
          String key = o.getString(0);
          String value = o.getString(1);
          addItem(key, value);
        }
      } catch (Exception e) {
      }
    }
  }
  private void calculateLeftMaxWidth(JSONArray data) {
    try {
      int size = data.length();
      for (int i = 0; i < size; ++i) {
        JSONArray o = (JSONArray) data.get(i);
        String key = o.getString(0);
        String value = o.getString(1);
        if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) {
          continue;
        }
        float curWidth = leftPaint.measureText(key);
        if (curWidth > maxLeftWidth) {
          maxLeftWidth = curWidth;
        }
      }
      maxLeftWidth = maxLeftWidth + middlePadding;
    } catch (Exception e) {
    }
  }
  private void addItem(String key, String value) {
    LinearLayout layout = getItemLayout();
    TextView left = (TextView) layout.findViewById(R.id.left);
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
        ViewGroup.LayoutParams.WRAP_CONTENT);
    params.width = (int) maxLeftWidth;
    left.setLayoutParams(params);
    left.setText(key);
    TextView right = (TextView) layout.findViewById(R.id.right);
    right.setText(value);
    root.addView(layout);
  }
  private LinearLayout getItemLayout() {
    LinearLayout layout = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.compose_item_layout, null);
    return layout;
  }
}

       改方案也需要先计算左边的最大占用宽度,来设置右边占用的大小,每一项的布局如下:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:Android="Http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="horizontal"
  android:paddingTop="@dimen/text_padding_10"
  tools:context=".activity.Typography1Activity">
  <TextView
    android:id="@+id/left"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginRight="@dimen/text_padding_10"
    android:textColor="@color/color_black_999999"
    android:textSize="@dimen/text_size_13"/>
  <TextView
    android:id="@+id/right"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:textColor="@color/black"
    android:textSize="@dimen/text_size_13"/>
</LinearLayout>

       每一行有两个TextView,左边宽度为自适应,右边占据剩下左右的位置,在计算出左边最大宽度后,重新设置左边每一个TextView占用的宽度。

方案6

       方式与1差不多,但是不在继承TextView,而是直接继承View:


public class TypographyView4 extends View {
  private Paint leftPaint = new Paint();
  private Paint rightPaint = new Paint();
  private int fullWidth;
  private float textSize;
  private JSONArray array;
  private int middlePadding = 0;
  float maxLeftWidth = 0;
  int itemSize = 0;
  public TypographyView4(Context context) {
    super(context);
    init();
  }
  public TypographyView4(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  }
  public TypographyView4(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
  }
  private void init() {
    textSize = getResources().getDimensionPixelSize(R.dimen.text_size_13);
    leftPaint.setAntiAlias(true);
    leftPaint.setTextSize(textSize);
    leftPaint.setColor(getResources().getColor(R.color.color_black_999999));
    rightPaint.setAntiAlias(true);
    rightPaint.setTextSize(textSize);
    rightPaint.setColor(getResources().getColor(R.color.color_black));
    middlePadding = getResources().getDimensionPixelSize(R.dimen.padding_value);
  }
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    fullWidth = getWidth();// 整个textView的宽度
  }
  public void setText(JSONArray array) {
    this.array = array;
    if (array != null) {
      try {
        int size = itemSize = array.length();
        for (int i = 0; i < size; ++i) {
          JSONArray o = (JSONArray) array.get(i);
          String key = o.getString(0);
          String value = o.getString(1);
          if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) {
            itemSize--;
            continue;
          }
          float curWidth = leftPaint.measureText(key);
          if (curWidth > maxLeftWidth) {
            maxLeftWidth = curWidth;
          }
        }
        maxLeftWidth = maxLeftWidth + middlePadding;
        invalidate();
      } catch (Exception e) {
      }
    }
  }
  @Override
  protected void onDraw(Canvas canvas) {
    if (array == null) {
      return;
    }
    int lineCount = 0;
    try {
      JSONArray item;
      float offsetY;
      for (int i = 0; i < itemSize; ++i) {
        item = (JSONArray) array.get(i);
        offsetY = (lineCount + 1) * textSize;
        canvas.drawText(item.getString(0), 0, offsetY, leftPaint);
        String value = item.getString(1);
        float valueWidth = rightPaint.measureText(value);
        if (valueWidth > fullWidth - maxLeftWidth) {// 一行显示不完
          char[] textCharArray = value.toCharArray();
          float charWidth;
          float drawWidth = maxLeftWidth;
          for (int j = 0; j < textCharArray.length; j++) {
            charWidth = rightPaint.measureText(textCharArray, j, 1);
            if (fullWidth - drawWidth < charWidth) {
              lineCount++;
              drawWidth = maxLeftWidth;
              offsetY += textSize;
            }
            canvas.drawText(textCharArray, j, 1, drawWidth, offsetY, rightPaint);
            drawWidth += charWidth;
          }
        } else {
          canvas.drawText(value, maxLeftWidth, offsetY, rightPaint);
        }
        lineCount += 2;
      }
    } catch (JSONException e) {
      e.printStackTrace();
    }
  }
}

       该方案主要继承自View,不再继承TextView,由于在在上述方案中不在调用super,因此TextView已经退化为一个View,因此直接继承View。

总结

       因为左边的宽度不确定,因此所有的方案都进行了同样的一个操作,就是测量了左边显示的最大宽度,后续的操作再根据该宽度进行调整。上述的方案中1,2,3,6都只需用一个View来进行显示,4,5都需要多个View进行显示。

 完整的代码可以在查看链接上进行查看。

您可能感兴趣的文章:Android 解决TextView排版参差不齐的问题Android AutoWrapTextView中英文排版问题的解决方法


--结束END--

本文标题: Android实现文本排版

本文链接: https://www.lsjlt.com/news/25217.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android中怎么仿instagram实现文字自动排版功能
    这篇文章主要介绍“Android中怎么仿instagram实现文字自动排版功能”,在日常操作中,相信很多人在Android中怎么仿instagram实现文字自动排版功能问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家...
    99+
    2023-06-04
  • css如何实现文字排版
    这篇文章给大家分享的是有关css如何实现文字排版的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。文字排版字体我们可以使用css样式为网页中的文字设置字体、字号、颜色等样式属性。body{font-family:&q...
    99+
    2023-06-27
  • Android下Button实现图文混排效果
    Button实现图文混排效果,具体内容如下一、简介本文介绍两种图文混排方式android:drawableTop="@drawable/star"实现文字上有图片当然有上下左右等等SpannableString的ImageSpan实现图文混...
    99+
    2023-05-30
    android button 图文混排
  • 如何实现文本文件乱序排列bat
    这篇文章主要介绍了如何实现文本文件乱序排列bat,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。代码如下:@echo off :: by ...
    99+
    2023-06-08
  • Android实现EditText的富文本编辑
    前言本文是我之前写的这篇文章《Android图文混排-实现EditText图文混合插入上传》的升级版,除了在EditText实现了图片上传之外,还包含了视频上传、云盘文件上传、录音上传以及显示上传进度。目前应用于蜜蜂-集结号-任务模块。首先...
    99+
    2023-05-30
    android edittext 富文本编辑
  • Android TextView实现图文混合编排的方法
    本文实例为大家分享了Android TextView图文混合编排的具体代码,供大家参考,具体内容如下实现技术细节不难,两个要点:html代码的混合编写。2、重写ImageGetter。例如:布局:<?xml version="...
    99+
    2023-05-30
    android textview 图文
  • Android 版本 对应的 API版本
    Android 14(开发者预览版) 如需详细了解平台变更,请参阅 Android 14 文档。 Android 13(API 级别 33) 如需详细了解平台变更,请参阅 Android 13 文档。 Android 12(API 级别 3...
    99+
    2023-08-31
    android
  • 如何实现bootstrap3.0的排版
    本篇内容主要讲解“如何实现bootstrap3.0的排版”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何实现bootstrap3.0的排版”吧!Html中的所...
    99+
    2024-04-02
  • android怎么实现文本代码高亮
    要在Android中实现文本代码高亮,可以使用Spannable类和ForegroundColorSpan类来实现。下面是一个简单的...
    99+
    2023-08-16
    android
  • 怎么在CSS3中实现文本垂直排列
    本篇文章给大家分享的是有关怎么在CSS3中实现文本垂直排列,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1.0 CSS3标准writing-mode:horizontal-tb...
    99+
    2023-06-08
  • css如何实现段落排版
    这篇文章将为大家详细讲解有关css如何实现段落排版,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。段落排版缩进中文文字中的段前习惯空两个文字的空白,这个特殊的样式可以用下面代码来实现:p{text-inde...
    99+
    2023-06-27
  • Android SDK对应版本
    前言 很多时候看到某个版本都无法对应起来,需要去网上查找,这里做个记录,方便查找对应版本。 平台版本SDK版本版本名称13.0T(33)Android 13 (Android Tiramisu)12L...
    99+
    2023-09-08
    android android studio ide
  • 在Android中使用AutoWrapTextView时出现中英文排版问题如何解决
    这篇文章将为大家详细讲解有关在Android中使用AutoWrapTextView时出现中英文排版问题如何解决,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。实现首先创建一个继承自View的A...
    99+
    2023-05-31
    android autowraptextview roi
  • CSS 文本排版属性详解:text-overflow 和 white-space
    在网页设计中,文本排版是一个非常重要的环节,通过合理的排版可以使文本更易读、更美观。CSS 提供了一些属性来控制文本的显示方式,其中包括 text-overflow 和 white-space。本文将详细介绍这两个属性的用法和示例代码。一、...
    99+
    2023-10-21
    padding margin align
  • Android TextView实现多文本折叠、展开效果
    背景在开发过程中,当我们的需求中包含说说或者评论等内容的展示时,我们都会考虑当内容太多时该如何显示。当内容的字数太多,如果全部展示出来可能会影响体验效果,但是又不能只截取一部分内容进行展示,此时就需要考虑使用多行显示折叠的效果来实现。效果图...
    99+
    2023-05-31
    android textview roi
  • Android富文本实现的几种方式汇总
    目录Android富文本的实现的几种方式一,Html的方式实现1.1 占位符的处理1.2 Html的占位符1.3 自定义Html标签二,Span的几种实现方式2.1 java - S...
    99+
    2024-04-02
  • Android文本视图TextView实现跑马灯效果
    本文实例为大家分享了Android文本视图TextView实现跑马灯效果的具体代码,供大家参考,具体内容如下 MainActivity package com.example.j...
    99+
    2024-04-02
  • Android文本视图TextView实现聊天室效果
    本文实例为大家分享了Android文本视图TextView实现聊天室的具体代码,供大家参考,具体内容如下 Math.random()生成随机数的范围是 0 到 1 之间的 日期时间格...
    99+
    2024-04-02
  • Android入门之读写本地文件的实现
    目录简介课程目标UI端后端代码运行效果简介 为了这个系列,我的代码已经准备到了第150天了。接下来的内容会越来越精彩,我们也越来越开始进入Android的一些高级功能上的编程了。今天...
    99+
    2022-12-20
    Android读写本地文件 Android 本地文件 Android读写文件
  • Android Studio 3.5版本JNI生成SO文件详解
    学习在于记录,把自己不懂得容易忘记得记录下,才是最好得选择。 废话不多说,想要在Android开发中嵌入c/c++代码,直接开始如下步骤 1、创建需要调用的Java类 在你某个指定的...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作