# LineBreakLayout--自动换行的标签容器
__讲解博客 :__ [http://blog.csdn.net/xmxkf/article/details/52336144](http://blog.csdn.net/xmxkf/article/details/52336144)
__效果图:__
![LineBreakLayout.gif](LineBreakLayout.gif)
```Java
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class LineBreakLayout extends ViewGroup {
private final static String TAG = "LineBreakLayout";
/**
* 所有标签
*/
private List<String> lables;
/**
* 选中标签
*/
private List<String> lableSelected = new ArrayList<>();
//自定义属性
private int LEFT_RIGHT_SPACE; //dip
private int ROW_SPACE;
public LineBreakLayout(Context context) {
this(context, null);
}
public LineBreakLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LineBreakLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LineBreakLayout);
LEFT_RIGHT_SPACE = ta.getDimensionPixelSize(R.styleable.LineBreakLayout_leftAndRightSpace, 10);
ROW_SPACE = ta.getDimensionPixelSize(R.styleable.LineBreakLayout_rowSpace, 10);
ta.recycle(); //回收
// ROW_SPACE=20 LEFT_RIGHT_SPACE=40
Log.v(TAG, "ROW_SPACE="+ROW_SPACE+" LEFT_RIGHT_SPACE="+LEFT_RIGHT_SPACE);
}
/**
* 添加标签
* @param lables 标签集合
* @param add 是否追加
*/
public void setLables(List<String> lables, boolean add){
if(this.lables == null){
this.lables = new ArrayList<>();
}
if(add){
this.lables.addAll(lables);
}else{
this.lables.clear();
this.lables = lables;
}
if(lables!=null && lables.size()>0){
LayoutInflater inflater = LayoutInflater.from(getContext());
for (final String lable : lables) {
//获取标签布局
final TextView tv = (TextView) inflater.inflate(R.layout.item_lable, null);
tv.setText(lable);
//设置选中效果
if (lableSelected.contains(lable)) {
//选中
tv.setSelected(true);
tv.setTextColor(getResources().getColor(R.color.tv_blue));
} else {
//未选中
tv.setSelected(false);
tv.setTextColor(getResources().getColor(R.color.tv_gray));
}
//点击标签后,重置选中效果
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tv.setSelected(tv.isSelected() ? false : true);
if (tv.isSelected()) {
tv.setTextColor(getResources().getColor(R.color.tv_blue));
//将选中的标签加入到lableSelected中
lableSelected.add(lable);
} else {
tv.setTextColor(getResources().getColor(R.color.tv_gray));
lableSelected.remove(lable);
}
}
});
//将标签添加到容器中
addView(tv);
}
}
}
/**
* 获取选中标签
*/
public List<String> getSelectedLables(){
return lableSelected;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//为所有的标签childView计算宽和高
measureChildren(widthMeasureSpec, heightMeasureSpec);
//获取高的模式
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//建议的高度
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//布局的宽度采用建议宽度(match_parent或者size),如果设置wrap_content也是match_parent的效果
int width = MeasureSpec.getSize(widthMeasureSpec);
int height ;
if (heightMode == MeasureSpec.EXACTLY) {
//如果高度模式为EXACTLY(match_perent或者size),则使用建议高度
height = heightSize;
} else {
//其他情况下(AT_MOST、UNSPECIFIED)需要计算计算高度
int childCount = getChildCount();
if(childCount<=0){
height = 0; //没有标签时,高度为0
}else{
int row = 1; // 标签行数
int widthSpace = width;// 当前行右侧剩余的宽度
for(int i = 0;i<childCount; i++){
View view = getChildAt(i);
//获取标签宽度
int childW = view.getMeasuredWidth();
Log.v(TAG , "标签宽度:"+childW +" 行数:"+row+" 剩余宽度:"+widthSpace);
if(widthSpace >= childW ){
//如果剩余的宽度大于此标签的宽度,那就将此标签放到本行
widthSpace -= childW;
}else{
row ++; //增加一行
//如果剩余的宽度不能摆放此标签,那就将此标签放入一行
widthSpace = width-childW;
}
//减去标签左右间距
widthSpace -= LEFT_RIGHT_SPACE;
}
//由于每个标签的高度是相同的,所以直接获取第一个标签的高度即可
int childH = getChildAt(0).getMeasuredHeight();
//最终布局的高度=标签高度*行数+行距*(行数-1)
height = (childH * row) + ROW_SPACE * (row-1);
Log.v(TAG , "总高度:"+height +" 行数:"+row+" 标签高度:"+childH);
}
}
//设置测量宽度和测量高度
setMeasuredDimension(width, height);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int row = 0;
int right = 0; // 标签相对于布局的右侧位置
int botom; // 标签相对于布局的底部位置
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
int childW = childView.getMeasuredWidth();
int childH = childView.getMeasuredHeight();
//右侧位置=本行已经占有的位置+当前标签的宽度
right += childW;
//底部位置=已经摆放的行数*(标签高度+行距)+当前标签高度
botom = row * (childH + ROW_SPACE) + childH;
// 如果右侧位置已经超出布局右边缘,跳到下一行
// if it can't drawing on a same line , skip to next line
if (right > (r - LEFT_RIGHT_SPACE)){
row++;
right = childW;
botom = row * (childH + ROW_SPACE) + childH;
}
Log.d(TAG, "left = " + (right - childW) +" top = " + (botom - childH)+
" right = " + right + " botom = " + botom);
childView.layout(right - childW, botom - childH,right,botom);
right += LEFT_RIGHT_SPACE;
}
}
}
```
没有合适的资源?快使用搜索试试~ 我知道了~
Android自动换行标签控件LineBreakLayout
共41个文件
xml:18个
png:5个
java:4个
5星 · 超过95%的资源 需积分: 18 85 下载量 180 浏览量
2016-12-01
14:39:29
上传
评论
收藏 658KB ZIP 举报
温馨提示
Android自动换行的标签容器LineBreakLayout 。效果请参考:http://blog.csdn.net/xmxkf/article/details/52336144
资源推荐
资源详情
资源评论
收起资源包目录
LineBreakLayout-master.zip (41个子文件)
LineBreakLayout-master
gradlew 5KB
settings.gradle 15B
.idea
runConfigurations.xml 564B
misc.xml 3KB
compiler.xml 686B
gradle.xml 739B
.name 15B
encodings.xml 159B
modules.xml 367B
copyright
profiles_settings.xml 74B
vcs.xml 180B
LineBreakLayout.gif 728KB
gradle
wrapper
gradle-wrapper.properties 231B
gradle-wrapper.jar 52KB
README.md 6KB
gradlew.bat 2KB
gradle.properties 855B
.gitignore 97B
app
src
androidTest
java
com
openxu
lbl
ApplicationTest.java 345B
test
java
com
openxu
lbl
ExampleUnitTest.java 307B
main
AndroidManifest.xml 654B
res
mipmap-hdpi
ic_launcher.png 3KB
mipmap-xxxhdpi
ic_launcher.png 10KB
mipmap-xhdpi
ic_launcher.png 5KB
mipmap-mdpi
ic_launcher.png 2KB
drawable
shape_item_lable_bg.xml 615B
layout
item_lable.xml 427B
activity_main.xml 549B
values-w820dp
dimens.xml 358B
values
colors.xml 375B
attrs.xml 317B
strings.xml 78B
styles.xml 383B
dimens.xml 211B
mipmap-xxhdpi
ic_launcher.png 8KB
java
com
openxu
lbl
LineBreakLayout.java 6KB
MainActivity.java 919B
.gitignore 7B
build.gradle 615B
proguard-rules.pro 641B
build.gradle 498B
共 41 条
- 1
资源评论
- skyflycn2017-07-19还不错,能用
open-Xu
- 粉丝: 1172
- 资源: 15
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功