诡异的Android TextView排版布局问题

本文探讨了Android TextView在布局中遇到的两个问题:文字与图片半包围的实现和文字显示不满一行换行的问题。针对后者,作者分析了问题原因,并提供了三种解决方案,包括全角半角转换、计算行字符数加 和自定义TextView。推荐的自定义TextView通过计算字符宽度和行间距来避免不必要换行,保证显示效果。

  

  俗话说,蛋疼问题天天有,今天她妹的特别多。以上是我做的一个内容,问题有如下几点。

1、如果想做出这种文字与图版半包围的形势,应该如何下手。

2、Android当中textview布局问题,有的时候显示不满一行就回跳到下一行。

  本片文章主要阐述第二个问题,第一个问题还在研究中。

  通过百度,了解网上各位大神的一些想法(不过大多数都是复制粘贴原文貌似只有一两篇),在通过自己的一些实践,简单总结了一下。

  产生问题的原因在于:

1、TextView在显示中文的时候 标点符号不能显示在一行的行首和行尾,如果一个标点符号刚好在一行的行尾,该标点符号就会连同前一个字符跳到下一行显示;

2、一个英文单词或者数字不能被显示在两行中( TextView在显示英文时,标点符号是可以放在行尾的,但英文单词也不能分开 );

  解决的办法网上可是五花八门,因为解决的具体问题不同,在下不好妄自菲薄,只能说适合解决我这种问题的方法。

   方法一:进行全角半角,特殊字符的转换。

   评论:此方法可以用到一些标题类的短文本进行处理,对于像这种内容介绍类型的长文本还是无能为力。

   方法二:计算各个行的字符数量,之后再后面加上”\n”。

   评论:此类方法适合处理写死的文本,而对于动态生成的文本来讲乏力很多,样式会超级难看。

   笔者推荐方法:构建自己的textview

   构建自己的textview并不是很麻烦,实现的思路如下。

1、 将要显示的文本转换为字符数组

2 、利用canvas.drawText(char[] text, index, count, x, y, paint)一个个绘出字符

1) 在绘制字符的时候要计算出每个字符的宽度(中文字符、阿拉伯数字以及英文字母的宽度都不相同),绘制下一个字符时在横向上的偏移量就是前面所有字符的宽度之和

2)判断某一行剩余空间能否放到下当前的字符,如果放不下,则另起一行,横向上的偏移量重置,纵向偏移量增加一个字体的高度

  以下是部分代码以及显示效果,如果有所赐教,欢迎讨论。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:dxh="http://blog.youkuaiyun.com/Justin_Dong1122"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="@color/write"
     >


<com.bj.bjmobile.android.dxh.view.MyTextView
                android:id="@+id/choose_info_content1"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_weight="40.0"
                dxh:textSize="18"
                dxh:paddingRight="170"
                dxh:textColor="@color/black"
                android:text=""
/>

package com.bj.bjmobile.android.dxh.view;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.TextView;

public class MyTextView extends TextView {
	private final String namespace = "http://blog.youkuaiyun.com/Justin_Dong1122";
	private String text;
	private float textSize;
	private Paint paint1 = new Paint();
	private float paddingLeft;
	private float paddingRight;
	private float textShowWidth;
	private int textColor;

	public MyTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		text = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "text");
		textSize = attrs.getAttributeIntValue(namespace, "textSize", 18);
		textColor = attrs.getAttributeIntValue(namespace, "textColor",Color.BLACK);
		paddingLeft = attrs.getAttributeIntValue(namespace, "paddingLeft", 0);
		paddingRight = attrs.getAttributeIntValue(namespace, "paddingRight", 0);
		paint1.setTextSize(textSize);
		paint1.setColor(textColor);
		paint1.setAntiAlias(true);
		textShowWidth = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth() - paddingLeft - paddingRight;
	}

	@Override
	protected void onDraw(Canvas canvas) {
		int lineCount = 0;
		if(text != null)
		{
			char[] textCharArray = text.toCharArray();
			// 已绘的宽度
			float drawedWidth = 0;
			float charWidth;
			for (int i = 0; i < textCharArray.length; i++) {
				charWidth = paint1.measureText(textCharArray, i, 1);
				if(textCharArray[i] == '\n' || textCharArray[i] == '\r')
				{
					lineCount++;
					drawedWidth = 0;
				}
				if (textShowWidth - drawedWidth < charWidth) {
					lineCount++;
					drawedWidth = 0;
				}
				canvas.drawText(textCharArray, i, 1, paddingLeft + drawedWidth,(lineCount + 1) * textSize, paint1);
				drawedWidth += charWidth;
			}
			setHeight((lineCount + 1) * (int) textSize + 5);
		}		
	}
	
	public String getText() {
		return text;
	}
	public void setText(String text) {
		this.text = text;
	}
	
}

  

  (168元那个位置是另一个问题引起的bug)

  凌晨1点19,晚安,My  World!



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值