欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實(shí)現(xiàn)文本排版

 更新時(shí)間:2016年04月18日 17:23:48   作者:xueshanhaizi  
這篇文章主要介紹了Android實(shí)現(xiàn)文本排版,對(duì)多行文本進(jìn)行排版布局,每一行的內(nèi)容又分為兩部分,左邊為標(biāo)題,右邊為描述,左邊內(nèi)容長(zhǎng)度不確定,右邊的內(nèi)容需要對(duì)齊,需要的朋友可以參考下

  在項(xiàng)目中有一個(gè)小功能需要實(shí)現(xiàn),就是對(duì)多行文本進(jìn)行排版布局,每一行的內(nèi)容又分為兩部分,左邊為標(biāo)題,右邊為描述,左邊內(nèi)容長(zhǎng)度不確定,右邊的內(nèi)容需要對(duì)齊,如有換行也需要對(duì)齊右邊的文本。

一、效果圖

       

可以看到內(nèi)容分成了兩部分,左邊的顏色與右邊不一致,右邊的描述文案統(tǒng)一對(duì)齊。

二、實(shí)現(xiàn)方案

       以上功能,由于輸入內(nèi)容輸入行數(shù)不確定,并且左邊的文案長(zhǎng)度也不確定,因此不能直接在布局中實(shí)現(xiàn),基于此這里主要實(shí)現(xiàn)了以下6種方式

方案1

       采用自定義控件的方式,繼承TextView,重新onDraw函數(shù),實(shí)現(xiàn)如下:

/**
 * 計(jì)算出左邊最長(zhǎng)的顯示字符串maxLeftWidth,之后draw每一行字符,右邊的描述從maxLeftWidth開(kāi)始draw
 * 當(dāng)一行顯示不完全時(shí),折行并且空出maxLeftWidth的空格長(zhǎng)度
 */
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();// 整個(gè)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)作為數(shù)據(jù)輸入,并且在這里面測(cè)量了左邊title的最大寬度,之后調(diào)用invalidate觸發(fā)重繪,在onSizeChanged獲取整個(gè)控件的寬度,重繪會(huì)調(diào)用onDraw函數(shù),這里不需要調(diào)用super函數(shù),TextView的onDraw函數(shù)做了非常多的操作,解析傳入的數(shù)據(jù),分別一行一行調(diào)用canvas來(lái)進(jìn)行drawText操作,當(dāng)繪制描述時(shí),先計(jì)算寬度,如果超過(guò)剩余控件說(shuō)明需要換行,最后調(diào)用setHeight設(shè)置高度,這個(gè)加一個(gè)判斷條件,因?yàn)闀?huì)觸發(fā)requestLayout()進(jìn)行重新布局和invalidate()進(jìn)行重繪,如果不加判斷會(huì)一直重繪。

方案2

       方式2與方式1差不多,不同為所有計(jì)算都在onDraw函數(shù)中:

/**
 * 該方式與方式1很類似,只是所有的計(jì)算都放在了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();// 整個(gè)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();
    }
  }
}

       該方案的實(shí)現(xiàn)是不太好的,方案1也是在此基礎(chǔ)上進(jìn)行調(diào)整的,在這里放出來(lái)只是為了說(shuō)明,所有的計(jì)算不要全部放在onDraw里面,因?yàn)樵摲椒赡軙?huì)反復(fù)調(diào)用多次,這樣就降低了性能。

方案3

       將數(shù)據(jù)源拼接成SpannableString,重寫onDraw函數(shù),根據(jù)內(nèi)容draw每一個(gè)字符:

/**
 * 該方法,是需要顯示的內(nèi)容先拼接成SpannableString,在onDraw方法中獲取所有的char字符,一個(gè)一個(gè)比較
 * 當(dāng)為分號(hào)是,表示為key與value的分隔符。
 */
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();// 整個(gè)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);
  }
}

       這里先計(jì)算左邊title的最大寬度,同時(shí)將所有的數(shù)據(jù)拼接成一個(gè)SpannableStringBuilder,調(diào)用setText函數(shù)會(huì)觸發(fā)重繪,在onDraw函數(shù)中進(jìn)行處理,由于未重新super函數(shù),因此SpannableString的setSpan函數(shù)失效,該方案主要根據(jù)分隔符來(lái)進(jìn)行分割,因此分隔符需要唯一。

方案4

       采用GridLayout方式實(shí)現(xiàn),但是原始控件有展示問(wèn)題,因此對(duì)此進(jìn)行了修改:

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("修改后的實(shí)現(xiàn)");
    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);// 這個(gè)可以在應(yīng)用程序起來(lái)的時(shí)候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;
  }
}

       如果直接創(chuàng)建一個(gè)GridLayout,里面添加每一項(xiàng),如果描述過(guò)長(zhǎng)都導(dǎo)致顯示不全,這個(gè)是系統(tǒng)的一個(gè)bug,計(jì)算的寬度有問(wèn)題,因此需要對(duì)此方案進(jìn)行更改。
       更改方式為先計(jì)算左邊占用的最大寬度,在添加右邊的項(xiàng)時(shí),設(shè)置布局參數(shù)控制最大的長(zhǎng)度。

方案5

       采用每一行一個(gè)布局,手動(dòng)一行一行進(jìn)行添加:

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;
  }
}

       改方案也需要先計(jì)算左邊的最大占用寬度,來(lái)設(shè)置右邊占用的大小,每一項(xiàng)的布局如下:

<?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>

       每一行有兩個(gè)TextView,左邊寬度為自適應(yīng),右邊占據(jù)剩下左右的位置,在計(jì)算出左邊最大寬度后,重新設(shè)置左邊每一個(gè)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();// 整個(gè)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,由于在在上述方案中不在調(diào)用super,因此TextView已經(jīng)退化為一個(gè)View,因此直接繼承View。

總結(jié)

       因?yàn)樽筮叺膶挾炔淮_定,因此所有的方案都進(jìn)行了同樣的一個(gè)操作,就是測(cè)量了左邊顯示的最大寬度,后續(xù)的操作再根據(jù)該寬度進(jìn)行調(diào)整。上述的方案中1,2,3,6都只需用一個(gè)View來(lái)進(jìn)行顯示,4,5都需要多個(gè)View進(jìn)行顯示。

 完整的代碼可以在查看鏈接上進(jìn)行查看。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • Android AutoValue使用和擴(kuò)展庫(kù)

    Android AutoValue使用和擴(kuò)展庫(kù)

    今天小編就為大家分享一篇關(guān)于Android AutoValue使用和擴(kuò)展庫(kù)的文章,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-10-10
  • Android實(shí)現(xiàn)簡(jiǎn)單的照相功能

    Android實(shí)現(xiàn)簡(jiǎn)單的照相功能

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)簡(jiǎn)單的照相功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Kotlin Jetpack組件ViewModel使用詳解

    Kotlin Jetpack組件ViewModel使用詳解

    作為Jetpack組件之一的ViewModel,也是框架MVVM中的一部分,其功能主要用于屏幕反轉(zhuǎn)后的數(shù)據(jù)保存;因?yàn)锳ctivity翻轉(zhuǎn)屏幕后或?qū)崿F(xiàn)onCreat()方法,也就是說(shuō)會(huì)重新創(chuàng)建頁(yè)面,之前頁(yè)面的臨時(shí)數(shù)據(jù)都會(huì)清除
    2022-12-12
  • 使用RecyclerView添加Header和Footer的方法

    使用RecyclerView添加Header和Footer的方法

    RecyclerView雖然作為L(zhǎng)istView的替代者有著較好的性能提升,但是ListView的一些常用功能卻沒(méi)有提供,比如我們平時(shí)會(huì)經(jīng)常用到的addHeaderView,addFooterView,既然RecyclerView沒(méi)有提供這個(gè)方法,我們應(yīng)該如何為列表添加頭部和底部呢,接下來(lái)通過(guò)本文給大家介紹
    2016-03-03
  • Android實(shí)現(xiàn)記事本功能(26)

    Android實(shí)現(xiàn)記事本功能(26)

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)記事本功能的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • Android仿zaker用手向上推動(dòng)的特效開(kāi)發(fā)【推動(dòng)門效果】(附demo源碼下載)

    Android仿zaker用手向上推動(dòng)的特效開(kāi)發(fā)【推動(dòng)門效果】(附demo源碼下載)

    這篇文章主要介紹了Android仿zaker用手向上推動(dòng)的特效,結(jié)合完整實(shí)例形式分析了Android滑動(dòng)切換效果的實(shí)現(xiàn)步驟與相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-07-07
  • Android使用EventBus多次接收消息

    Android使用EventBus多次接收消息

    這篇文章主要為大家詳細(xì)介紹了Android使用EventBus多次接收消息,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 淺談Android中Service的注冊(cè)方式及使用

    淺談Android中Service的注冊(cè)方式及使用

    下面小編就為大家分享一篇淺談Android中Service的注冊(cè)方式及使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • Flutter實(shí)現(xiàn)自定義下拉選擇框的示例詳解

    Flutter實(shí)現(xiàn)自定義下拉選擇框的示例詳解

    在一些列表頁(yè)面中,我們經(jīng)常會(huì)有上方篩選項(xiàng)的的需求,點(diǎn)擊出現(xiàn)一個(gè)下拉菜單,而在Flutter中,并沒(méi)有現(xiàn)成的這樣的組件,所以最好我們可以自己做一個(gè)。本文將利用Flutter實(shí)現(xiàn)自定義下拉選擇框,需要的可以參考一下
    2022-04-04
  • 詳解Android 在 ViewPager 中使用 Fragment 的懶加載

    詳解Android 在 ViewPager 中使用 Fragment 的懶加載

    本篇文章主要介紹了Android 在 ViewPager 中使用 Fragment 的懶加載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06

最新評(píng)論