Android LinearLayout中TextView标签项自动换行的一种解决方案

本文介绍了在Android中使用LinearLayout和TextView实现标签项自动换行的解决方案,适用于搜索、广告热门关键词等场景。通过示例代码展示了一种不依赖自定义ViewGroup的简单方法。

在一些项目中,比如搜索,广告热门关键词等等都会用到下面这种效果的排版,如下图:


其实最通用的实现方案是自定义一个ViewGroup,然后自己计算布局。但是这种方式对于一些对自定义控件不太熟悉的人来说,有些难度,这里有一个通过拼凑的方法实现这种效果,下面是源代码,偷懒了一下,不想封装了,直接就写在一个Activity里面,谁有需要,自己去优化:

import android.app.Activity;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;

public class TextViewItemActivity extends Activity {

	private boolean isFristTime = true;

	/** 标签之间的间距 px */
	final int itemMargins = 50;

	/** 标签的行间距 px */
	final int lineMargins = 50;

	private ViewGroup container = null;

	private String[] tags = { "大约在冬季", "漂洋过海的来看你", "天下有情人", "我很认真", "夜夜夜夜", "想你的夜", "背叛", "趁早", "旧情绵绵", "谁明浪子心", "安妮",
			"说谎的爱人", "不浪漫的罪名", "不愿一个人", "风吹麦浪" };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.textview_layout);
		container = (ViewGroup) findViewById(R.id.container);
	}

	@Override
	public void onWindowFocusChanged(boolean hasFocus) {
		super.onWindowFocusChanged(hasFocus);
		if (hasFocus && isFristTime) {
			isFristTime = false;
			final int containerWidth = container.getMeasuredWidth() - container.getPaddingRight()
					- container.getPaddingLeft();

			final LayoutInflater inflater = getLayoutInflater();

			/** 用来测量字符的宽度 */
			final Paint paint = new Paint();
			final TextView textView = (TextView) inflater.inflate(R.layout.item_textview, null);
			final int itemPadding = textView.getCompoundPaddingLeft() + textView.getCompoundPaddingRight();
			final LinearLayout.LayoutParams tvParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
					LayoutParams.WRAP_CONTENT);
			tvParams.setMargins(0, 0, itemMargins, 0);

			paint.setTextSize(textView.getTextSize());

			LinearLayout layout = new LinearLayout(this);
			layout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
			layout.setOrientation(LinearLayout.HORIZONTAL);
			container.addView(layout);

			final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
					LayoutParams.WRAP_CONTENT);
			params.setMargins(0, lineMargins, 0, 0);

			/** 一行剩下的空间 **/
			int remainWidth = containerWidth;

			for (int i = 0; i < tags.length; ++i) {
				final String text = tags[i];
				final float itemWidth = paint.measureText(text) + itemPadding;
				if (remainWidth > itemWidth) {
					addItemView(inflater, layout, tvParams, text);
				} else {
					resetTextViewMarginsRight(layout);
					layout = new LinearLayout(this);
					layout.setLayoutParams(params);
					layout.setOrientation(LinearLayout.HORIZONTAL);

					/** 将前面那一个textview加入新的一行 */
					addItemView(inflater, layout, tvParams, text);
					container.addView(layout);
					remainWidth = containerWidth;
				}
				remainWidth = (int) (remainWidth - itemWidth + 0.5f) - itemMargins;
			}
			resetTextViewMarginsRight(layout);
		}
	}

	/***************** 将每行最后一个textview的MarginsRight去掉 *********************************/
	private void resetTextViewMarginsRight(ViewGroup viewGroup) {
		final TextView tempTextView = (TextView) viewGroup.getChildAt(viewGroup.getChildCount() - 1);
		tempTextView
				.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
	}

	private void addItemView(LayoutInflater inflater, ViewGroup viewGroup, LayoutParams params, String text) {
		final TextView tvItem = (TextView) inflater.inflate(R.layout.item_textview, null);
		tvItem.setText(text);
		viewGroup.addView(tvItem, params);
	}
}

Activity的Layout文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray"
        android:gravity="center_horizontal"
        android:paddingBottom="5dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="5dp"
        android:text="这只是一个demo而已"
        android:textSize="16sp" >
    </TextView>

    <LinearLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:background="#8864dd"
        android:orientation="vertical"
        android:paddingBottom="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="10dp" >
    </LinearLayout>

</LinearLayout>

TextView的Layout文件:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/darker_gray"
    android:paddingBottom="10dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="10dp"
    android:text="测试的"
    android:textSize="16sp" >

</TextView>

嗯,就这样,谁需要用到的就用,其实好像网上有一个开源的控件,我忘记叫啥名字了,自己去找找。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值