文件名:TagListView4ReportLineLimited.java
效果图:

当宽度满屏,自动换行。
用法:
private TagListView4ReportLineLimited mTagListView;
private List<Tag> mTags = new ArrayList<Tag>();
private String[][] filesMessagesString = {{"低头族","久坐","久站","吸烟","饮酒","熬夜","鼠标手","喝水少","饭后卧床","强忍大小便","如厕看书报"},
{"bin"},
{"颅脑手术","颈部手术","胸部手术","腹部手术","背部手术","四肢手术","头部外伤","骨折","烧伤","烫伤","扭伤","肌腱损伤","刀砍伤","刀刺伤","皮肤软组织损伤"},
{"高血压","糖尿病","心脏病","脑梗","脑出血","癌症","哮喘","过敏性疾病","癫痫","白癜风","近视","色盲"},
{"青霉素","头孢类抗生素","破伤风抗霉素","普鲁卡因","地卡因","磺胺类药物","维生素b1","泛影葡胺","阿司匹林"},
{"芒果","牛奶","海鲜","笋","香菇","黄瓜","花粉","油漆","皮毛","化妆品 ","菠萝"}};
private void initFilesLayoutData(int position){
mTags.clear();
mTagListView = (TagListView4ReportLineLimited) this.findViewById(R.id.mTagListView2);
mTagListView.setVisibility(View.VISIBLE);
mTagListView.removeAllViews();
ArrayList<String> hotChannelList = new ArrayList<String>();
for(int i =0;i<filesMessagesString[position].length;i++){
hotChannelList.add(filesMessagesString[position][i]);
}
setUpData(hotChannelList);
mTagListView.setTags(mTags);
mTagListView.setOnTagClickListener(new TagListView4ReportLineLimited.OnTagClickListener() {
@Override
public void onTagClick(TagView tagView, Tag tag) {
}
});
}
private void setUpData(ArrayList<String> hotChannelList) {
mTags.clear();
FlowLayout4ReportLineLimited.SHOW_LINE_NUM = 12;
for (int i = 0; i < hotChannelList.size(); i++) {
Tag tag = new Tag();
tag.setId(i);
tag.setChecked(true);
tag.setBackgroundResId(R.drawable.check_details_rounded_rectangle_bg);
tag.setTitle(hotChannelList.get(i));
mTags.add(tag);
}
}
TagListView4ReportLineLimited.java代码如下:
import java.util.ArrayList;
import java.util.List;
import com.jianke.doctor.R;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CompoundButton;
import android.widget.RelativeLayout;
/**
* @author kince
* @category 模仿最美应用底部tagview
*
*/
public class TagListView4ReportLineLimited extends FlowLayout4ReportLineLimited
implements OnClickListener {
private boolean mIsDeleteMode;
private OnTagCheckedChangedListener mOnTagCheckedChangedListener;
private OnTagClickListener mOnTagClickListener;
private int mTagViewBackgroundResId;
private int mTagViewTextColorResId;
private final List<Tag> mTags = new ArrayList<Tag>();
/**
* @param context
*/
public TagListView4ReportLineLimited(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}
/**
* @param context
* @param attributeSet
*/
public TagListView4ReportLineLimited(Context context,
AttributeSet attributeSet) {
super(context, attributeSet);
// TODO Auto-generated constructor stub
init();
}
/**
* @param context
* @param attributeSet
* @param defStyle
*/
public TagListView4ReportLineLimited(Context context,
AttributeSet attributeSet, int defStyle) {
super(context, attributeSet, defStyle);
// TODO Auto-generated constructor stub
init();
}
@Override
public void onClick(View v) {
if ((v instanceof TagView)) {
Tag localTag = (Tag) v.getTag();
if (this.mOnTagClickListener != null) {
this.mOnTagClickListener.onTagClick((TagView) v, localTag);
}
}
}
private void init() {
}
private void inflateTagView(final Tag t, boolean b) {
TagView localTagView = (TagView) View.inflate(getContext(),
R.layout.tag4reportlinelimited, null);
localTagView.setText(t.getTitle());
localTagView.setTag(t);
/*
* if (mTagViewTextColorResId <= 0) { int c =
* getResources().getColor(R.color.blue); localTagView.setTextColor(c);
*
* }
*
* if (mTagViewBackgroundResId <= 0) { mTagViewBackgroundResId =
* R.drawable.tag_bg;
* localTagView.setBackgroundResource(mTagViewBackgroundResId); }
*/
localTagView.setChecked(t.isChecked());
localTagView.setCheckEnable(b);
if (mIsDeleteMode) {
int k = (int) TypedValue.applyDimension(1, 5.0F, getContext()
.getResources().getDisplayMetrics());
localTagView.setPadding(localTagView.getPaddingLeft(),
localTagView.getPaddingTop(), k,
localTagView.getPaddingBottom());
localTagView.setCompoundDrawablesWithIntrinsicBounds(0, 0,
R.drawable.forum_tag_close, 0);
}
if (t.getBackgroundResId() > 0) {
localTagView.setBackgroundResource(t.getBackgroundResId());
}
if ((t.getLeftDrawableResId() > 0) || (t.getRightDrawableResId() > 0)) {
localTagView.setCompoundDrawablesWithIntrinsicBounds(
t.getLeftDrawableResId(), 0, t.getRightDrawableResId(), 0);
}
localTagView.setOnClickListener(this);
/*
* localTagView .setOnCheckedChangeListener(new
* CompoundButton.OnCheckedChangeListener() { public void
* onCheckedChanged( CompoundButton paramAnonymousCompoundButton,
* boolean paramAnonymousBoolean) { t.setChecked(paramAnonymousBoolean);
* if (TagListView.this.mOnTagCheckedChangedListener != null) {
* TagListView.this.mOnTagCheckedChangedListener .onTagCheckedChanged(
* (TagView) paramAnonymousCompoundButton, t); } } });
*/
addView(localTagView);
}
public void addTag(int i, String s) {
addTag(i, s, false);
}
public void addTag(int i, String s, boolean b) {
addTag(new Tag(i, s), b);
}
public void addTag(Tag tag) {
addTag(tag, false);
}
public void addTag(Tag tag, boolean b) {
mTags.add(tag);
inflateTagView(tag, b);
}
public void addTags(List<Tag> lists) {
addTags(lists, false);
}
public void addTags(List<Tag> lists, boolean b) {
for (int i = 0; i < lists.size(); i++) {
addTag((Tag) lists.get(i), b);
}
}
public List<Tag> getTags() {
return mTags;
}
public View getViewByTag(Tag tag) {
return findViewWithTag(tag);
}
public void removeTag(Tag tag) {
mTags.remove(tag);
removeView(getViewByTag(tag));
}
public void setDeleteMode(boolean b) {
mIsDeleteMode = b;
}
public void setOnTagCheckedChangedListener(
OnTagCheckedChangedListener onTagCheckedChangedListener) {
mOnTagCheckedChangedListener = onTagCheckedChangedListener;
}
public void setOnTagClickListener(OnTagClickListener onTagClickListener) {
mOnTagClickListener = onTagClickListener;
}
public void setTagViewBackgroundRes(int res) {
mTagViewBackgroundResId = res;
}
public void setTagViewTextColorRes(int res) {
mTagViewTextColorResId = res;
}
public void setTags(List<? extends Tag> lists) {
setTags(lists, false);
}
public void setTags(List<? extends Tag> lists, boolean b) {
removeAllViews();
mTags.clear();
for (int i = 0; i < lists.size(); i++) {
addTag((Tag) lists.get(i), b);
}
}
public static abstract interface OnTagCheckedChangedListener {
public abstract void onTagCheckedChanged(TagView tagView, Tag tag);
}
public static abstract interface OnTagClickListener {
public abstract void onTagClick(TagView tagView, Tag tag);
}
}
FlowLayout4ReportLineLimited.java
package com.jianke.view.widget;
import java.util.ArrayList;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import com.jianke.doctor.R;
/**
* 在每个页面使用完毕后记得将参数还原
* */
public class FlowLayout4ReportLineLimited extends ViewGroup {
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
private int horizontalSpacing = 0;
private int verticalSpacing = 0;
private int orientation = 0;
private boolean debugDraw = false;
/**
* 设置显示几排,默认为0.0;<br>
* 如若全部显示,则将其赋值为Double.POSITIVE_INFINITY(正无穷)
* */
public static double SHOW_LINE_NUM = 0;
private int num;
private static double lineNum;
private static ArrayList<Double> lineNums = new ArrayList<Double>();
/**
* 是否控制间距(由于加上背景后Tag之间无间距)
* */
public static boolean isControlSpace = false;
// public static int leftControlSpace = 0, upControlSpace = 0,
// rightControlSpace = 0, downControlSpace = 0;
public FlowLayout4ReportLineLimited(Context context) {
super(context);
this.readStyleParameters(context, null);
}
public FlowLayout4ReportLineLimited(Context context,
AttributeSet attributeSet) {
super(context, attributeSet);
this.readStyleParameters(context, attributeSet);
}
public FlowLayout4ReportLineLimited(Context context,
AttributeSet attributeSet, int defStyle) {
super(context, attributeSet, defStyle);
this.readStyleParameters(context, attributeSet);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
lineNum = 1;
double line_num = 1;
setNum(0);
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec)
- this.getPaddingRight() - this.getPaddingLeft();
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec)
- this.getPaddingTop() - this.getPaddingBottom();
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
int size;
int mode;
if (orientation == HORIZONTAL) {
size = sizeWidth;
mode = modeWidth;
} else {
size = sizeHeight;
mode = modeHeight;
}
int lineThicknessWithSpacing = 0;
int lineThickness = 0;
int lineLengthWithSpacing = 0;
int lineLength;
int prevLinePosition = 0;
int controlMaxLength = 0;
int controlMaxThickness = 0;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
if (line_num <= SHOW_LINE_NUM) {
setNum(i + 1);
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
LayoutParams lp = (LayoutParams) child.getLayoutParams();
child.measure(
getChildMeasureSpec(widthMeasureSpec,
this.getPaddingLeft() + this.getPaddingRight(),
lp.width),
getChildMeasureSpec(heightMeasureSpec,
this.getPaddingTop() + this.getPaddingBottom(),
lp.height));
int hSpacing = this.getHorizontalSpacing(lp);
int vSpacing = this.getVerticalSpacing(lp);
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
int childLength;
int childThickness;
int spacingLength;
int spacingThickness;
if (orientation == HORIZONTAL) {
childLength = childWidth;
childThickness = childHeight;
spacingLength = hSpacing;
spacingThickness = vSpacing;
} else {
childLength = childHeight;
childThickness = childWidth;
spacingLength = vSpacing;
spacingThickness = hSpacing;
}
lineLength = lineLengthWithSpacing + childLength + 40;
lineLengthWithSpacing = lineLength + spacingLength;
boolean newLine = lp.newLine
|| (mode != MeasureSpec.UNSPECIFIED && lineLength > size);
if (newLine) {
lineNum++;
line_num++;
if (line_num > SHOW_LINE_NUM) {
setNum(i);
break;
}
prevLinePosition = prevLinePosition
+ lineThicknessWithSpacing;
lineThickness = childThickness;
lineLength = childLength;
lineThicknessWithSpacing = childThickness
+ spacingThickness;
lineLengthWithSpacing = lineLength + spacingLength;
}
lineThicknessWithSpacing = Math.max(lineThicknessWithSpacing,
childThickness + spacingThickness);
lineThickness = Math.max(lineThickness, childThickness);
int posX;
int posY;
if (orientation == HORIZONTAL) {
posX = getPaddingLeft() + lineLength - childLength;
posY = getPaddingTop() + prevLinePosition;
} else {
posX = getPaddingLeft() + prevLinePosition;
posY = getPaddingTop() + lineLength - childHeight;
}
lp.setPosition(posX, posY);
controlMaxLength = Math.max(controlMaxLength, lineLength);
controlMaxThickness = prevLinePosition + lineThickness;
}
}
/* need to take paddings into account */
if (orientation == HORIZONTAL) {
controlMaxLength += getPaddingLeft() + getPaddingRight();
controlMaxThickness += getPaddingBottom() + getPaddingTop();
} else {
controlMaxLength += getPaddingBottom() + getPaddingTop();
controlMaxThickness += getPaddingLeft() + getPaddingRight();
}
if (orientation == HORIZONTAL) {
this.setMeasuredDimension(
resolveSize(controlMaxLength, widthMeasureSpec),
resolveSize(controlMaxThickness, heightMeasureSpec));
} else {
this.setMeasuredDimension(
resolveSize(controlMaxThickness, widthMeasureSpec),
resolveSize(controlMaxLength, heightMeasureSpec));
}
lineNums.add(lineNum);
}
private int getVerticalSpacing(LayoutParams lp) {
int vSpacing;
if (lp.verticalSpacingSpecified()) {
vSpacing = lp.verticalSpacing;
} else {
vSpacing = this.verticalSpacing;
}
return vSpacing;
}
private int getHorizontalSpacing(LayoutParams lp) {
int hSpacing;
if (lp.horizontalSpacingSpecified()) {
hSpacing = lp.horizontalSpacing;
} else {
hSpacing = this.horizontalSpacing;
}
return hSpacing;
}
private int getNum() {
return num;
}
private void setNum(int num) {
this.num = num;
}
public static ArrayList<Double> getLineNums() {
return lineNums;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int pre_x = 0;
for (int i = 0; i < getNum(); i++) {
View child = getChildAt(i);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.x == 0) {
child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y
+ child.getMeasuredHeight());
pre_x = 0;
} else {
child.layout(pre_x, lp.y, pre_x + child.getMeasuredWidth(),
lp.y + child.getMeasuredHeight());
}
pre_x = pre_x + child.getMeasuredWidth() + 40;
}
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
boolean more = super.drawChild(canvas, child, drawingTime);
this.drawDebugInfo(canvas, child);
return more;
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attributeSet) {
return new LayoutParams(getContext(), attributeSet);
}
@Override
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}
private void readStyleParameters(Context context, AttributeSet attributeSet) {
TypedArray a = context.obtainStyledAttributes(attributeSet,
R.styleable.FlowLayout);
try {
horizontalSpacing = a.getDimensionPixelSize(
R.styleable.FlowLayout_horizontalSpacing, 0);
verticalSpacing = a.getDimensionPixelSize(
R.styleable.FlowLayout_verticalSpacing, 0);
orientation = a.getInteger(R.styleable.FlowLayout_orientation,
HORIZONTAL);
debugDraw = a.getBoolean(R.styleable.FlowLayout_debugDraw, false);
} finally {
a.recycle();
}
}
private void drawDebugInfo(Canvas canvas, View child) {
if (!debugDraw) {
return;
}
Paint childPaint = this.createPaint(0xffffff00);
Paint layoutPaint = this.createPaint(0xff00ff00);
Paint newLinePaint = this.createPaint(0xffff0000);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.horizontalSpacing > 0) {
float x = child.getRight();
float y = child.getTop() + child.getHeight() / 2.0f;
canvas.drawLine(x, y, x + lp.horizontalSpacing, y, childPaint);
canvas.drawLine(x + lp.horizontalSpacing - 4.0f, y - 4.0f, x
+ lp.horizontalSpacing, y, childPaint);
canvas.drawLine(x + lp.horizontalSpacing - 4.0f, y + 4.0f, x
+ lp.horizontalSpacing, y, childPaint);
} else if (this.horizontalSpacing > 0) {
float x = child.getRight();
float y = child.getTop() + child.getHeight() / 2.0f;
canvas.drawLine(x, y, x + this.horizontalSpacing, y, layoutPaint);
canvas.drawLine(x + this.horizontalSpacing - 4.0f, y - 4.0f, x
+ this.horizontalSpacing, y, layoutPaint);
canvas.drawLine(x + this.horizontalSpacing - 4.0f, y + 4.0f, x
+ this.horizontalSpacing, y, layoutPaint);
}
if (lp.verticalSpacing > 0) {
float x = child.getLeft() + child.getWidth() / 2.0f;
float y = child.getBottom();
canvas.drawLine(x, y, x, y + lp.verticalSpacing, childPaint);
canvas.drawLine(x - 4.0f, y + lp.verticalSpacing - 4.0f, x, y
+ lp.verticalSpacing, childPaint);
canvas.drawLine(x + 4.0f, y + lp.verticalSpacing - 4.0f, x, y
+ lp.verticalSpacing, childPaint);
} else if (this.verticalSpacing > 0) {
float x = child.getLeft() + child.getWidth() / 2.0f;
float y = child.getBottom();
canvas.drawLine(x, y, x, y + this.verticalSpacing, layoutPaint);
canvas.drawLine(x - 4.0f, y + this.verticalSpacing - 4.0f, x, y
+ this.verticalSpacing, layoutPaint);
canvas.drawLine(x + 4.0f, y + this.verticalSpacing - 4.0f, x, y
+ this.verticalSpacing, layoutPaint);
}
if (lp.newLine) {
if (orientation == HORIZONTAL) {
float x = child.getLeft();
float y = child.getTop() + child.getHeight() / 2.0f;
canvas.drawLine(x, y - 6.0f, x, y + 6.0f, newLinePaint);
} else {
float x = child.getLeft() + child.getWidth() / 2.0f;
float y = child.getTop();
canvas.drawLine(x - 6.0f, y, x + 6.0f, y, newLinePaint);
}
}
}
private Paint createPaint(int color) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(color);
paint.setStrokeWidth(2.0f);
return paint;
}
public static class LayoutParams extends ViewGroup.LayoutParams {
private static int NO_SPACING = -1;
private int x;
private int y;
private int horizontalSpacing = NO_SPACING;
private int verticalSpacing = NO_SPACING;
private boolean newLine = false;
public LayoutParams(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
this.readStyleParameters(context, attributeSet);
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(ViewGroup.LayoutParams layoutParams) {
super(layoutParams);
}
public boolean horizontalSpacingSpecified() {
return horizontalSpacing != NO_SPACING;
}
public boolean verticalSpacingSpecified() {
return verticalSpacing != NO_SPACING;
}
public void setPosition(int x, int y) {
this.x = x;
this.y = y;
}
private void readStyleParameters(Context context,
AttributeSet attributeSet) {
TypedArray a = context.obtainStyledAttributes(attributeSet,
R.styleable.FlowLayout_LayoutParams);
try {
horizontalSpacing = a
.getDimensionPixelSize(
R.styleable.FlowLayout_LayoutParams_layout_horizontalSpacing,
NO_SPACING);
verticalSpacing = a
.getDimensionPixelSize(
R.styleable.FlowLayout_LayoutParams_layout_verticalSpacing,
NO_SPACING);
newLine = a.getBoolean(
R.styleable.FlowLayout_LayoutParams_layout_newLine,
false);
} finally {
a.recycle();
}
}
}
}