android实现选标签,Android中标签TagLayout支持单选多选
Android中标签TagLayout支持单选多选,首先给出主要类继承了ViewGroup。public class TagLayout extends ViewGroup {private static final int DEFAULT_TAG_RES_ID = R.layout.item_tag;private static final int SELECT_MODE_NONE = 0;pr
Android中标签TagLayout支持单选多选,首先给出主要类继承了ViewGroup。
public class TagLayout extends ViewGroup {
private static final int DEFAULT_TAG_RES_ID = R.layout.item_tag;
private static final int SELECT_MODE_NONE = 0;
private static final int SELECT_MODE_SINGLE = 1;
private static final int SELECT_MODE_MULTIPLE = 2;
private int mTagSelectMode = SELECT_MODE_NONE;
private Integer mTagTextSize;
private int mTagResId = DEFAULT_TAG_RES_ID;
private List mTagLines = new ArrayList<>();
private int mHorizontalSpace = 0;
private int mVerticalSpace = 0;
private int maxLines = Integer.MAX_VALUE;
private List mTags;
private LayoutInflater mInflater;
private Integer mTagBackground;
private Integer mTagMinWidth;
private ColorStateList mTagTextColor;
private Integer mTagTextHorizontalPadding;
private Integer mTagTextVerticalPadding;
private static final int DEFAULT_CACHE_LINES = 3;
private TextView mCurrentSelected;
private boolean mHasMeasured = false;
private int mLastWidthMeasureSpec;
private int mLastHeightMeasureSpec;
private int mLastMeasureWidth;
private int mLstMeasureHeight;
public interface OnSelectChangeListener {
void onSelectChange(TextView child, int index, boolean isSelected);
}
public interface OnItemClickListener {
void onItemClick(TextView child, int index);
}
private OnSelectChangeListener onSelectChangeListener;
private OnItemClickListener onItemClickListener;
public void setOnSelectChangeListener(OnSelectChangeListener onSelectChangeListener) {
this.onSelectChangeListener = onSelectChangeListener;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public TagLayout(Context context) {
super(context);
mInflater = LayoutInflater.from(context);
}
public TagLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mInflater = LayoutInflater.from(context);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TagLayout);
if (a != null) {
mHorizontalSpace = a.getDimensionPixelOffset(R.styleable.TagLayout_horizontalSpace, 0);
mVerticalSpace = a.getDimensionPixelOffset(R.styleable.TagLayout_verticalSpace, 0);
maxLines = a.getInteger(R.styleable.TagLayout_maxLines, Integer.MAX_VALUE);
mTagResId = a.getResourceId(R.styleable.TagLayout_tagResId, DEFAULT_TAG_RES_ID);
if (a.hasValue(R.styleable.TagLayout_tagTextSize)) {
mTagTextSize = a.getDimensionPixelSize(R.styleable.TagLayout_tagTextSize, 0);
}
if (a.hasValue(R.styleable.TagLayout_tagBackground)) {
mTagBackground = a.getResourceId(R.styleable.TagLayout_tagBackground, -1);
}
if (a.hasValue(R.styleable.TagLayout_tagTextColor)) {
mTagTextColor = a.getColorStateList(R.styleable.TagLayout_tagTextColor);
}
if (a.hasValue(R.styleable.TagLayout_tagTextHorizontalPadding)) {
mTagTextHorizontalPadding = a.getDimensionPixelOffset(R.styleable.TagLayout_tagTextHorizontalPadding, 0);
}
if (a.hasValue(R.styleable.TagLayout_tagTextVerticalPadding)) {
mTagTextVerticalPadding = a.getDimensionPixelOffset(R.styleable.TagLayout_tagTextVerticalPadding, 0);
}
if (a.hasValue(R.styleable.TagLayout_tagSelectMode)) {
mTagSelectMode = a.getInt(R.styleable.TagLayout_tagSelectMode, SELECT_MODE_NONE);
}
if (a.hasValue(R.styleable.TagLayout_tagMinWidth)) {
mTagMinWidth = a.getDimensionPixelOffset(R.styleable.TagLayout_tagMinWidth, 0);
}
a.recycle();
}
if (maxLines <= DEFAULT_CACHE_LINES) {
int maxWidth = ViewUtils.getDisplayWidth();
for (int i = 0; i < maxLines; i++) {
int totalChildSizeWidth = 0;
while (totalChildSizeWidth < maxLines) {
TextView tagView = addTag(" ");
tagView.measure(MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST));
tagView.setVisibility(View.INVISIBLE);
totalChildSizeWidth += tagView.getMeasuredWidth() + mHorizontalSpace;
}
}
}
}
private TextView addTag(final String tagText) {
final TextView tagView = (TextView) mInflater.inflate(mTagResId, null);
if (hasValue(mTagBackground)) {
tagView.setBackgroundResource(mTagBackground);
}
if (hasValue(mTagTextSize)) {
tagView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTagTextSize);
}
if (hasValue(mTagTextColor)) {
tagView.setTextColor(mTagTextColor);
}
if (hasValue(mTagMinWidth)) {
tagView.setMinWidth(mTagMinWidth);
}
int paddingLeft = tagView.getPaddingLeft();
int paddingRight = tagView.getPaddingRight();
int paddingTop = tagView.getPaddingTop();
int paddingBottom = tagView.getPaddingBottom();
if (hasValue(mTagTextHorizontalPadding)) {
paddingLeft = mTagTextHorizontalPadding;
paddingRight = mTagTextHorizontalPadding;
}
if (hasValue(mTagTextVerticalPadding)) {
paddingTop = mTagTextVerticalPadding;
paddingBottom = mTagTextVerticalPadding;
}
tagView.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
tagView.setText(tagText);
final int position = getChildCount();
tagView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (tagView.getVisibility() != View.VISIBLE)
return;
if (onItemClickListener != null) {
onItemClickListener.onItemClick(tagView, position);
}
if (mTagSelectMode == SELECT_MODE_MULTIPLE) {
tagView.setSelected(!tagView.isSelected());
if (onSelectChangeListener != null) {
onSelectChangeListener.onSelectChange(tagView, position, tagView.isSelected());
}
} else if (mTagSelectMode == SELECT_MODE_SINGLE) {
if (mCurrentSelected != null) {
mCurrentSelected.setSelected(false);
}
tagView.setSelected(true);
mCurrentSelected = tagView;
if (onSelectChangeListener != null) {
onSelectChangeListener.onSelectChange(tagView, position, tagView.isSelected());
}
}
}
});
addView(tagView);
return tagView;
}
private boolean hasValue(Object value) {
return value != null;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentSuggestWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
if (mHasMeasured && mLastWidthMeasureSpec == widthMeasureSpec && mLastHeightMeasureSpec == heightMeasureSpec) {
setMeasuredDimension(mLastMeasureWidth, mLstMeasureHeight);
return;
}
mTagLines.clear();
TagLine tagLine = null;
int maxWidth = parentSuggestWidth - getPaddingLeft() - getPaddingRight();
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
}
measureChild(child, widthMeasureSpec, heightMeasureSpec);
if (tagLine == null) {
tagLine = newTagLine(maxWidth);
tagLine.addView(child);
} else {
if (tagLine.accept(child)) {
tagLine.addView(child);
} else {
if (mTagLines.size() == maxLines) {
for (int hiddenIndex = i; hiddenIndex < getChildCount(); hiddenIndex++) {
getChildAt(hiddenIndex).setVisibility(View.GONE);
}
break;
}
tagLine = newTagLine(maxWidth);
tagLine.addView(child);
}
}
}
int measureHeight = getPaddingTop() + getPaddingBottom();
for (int i = 0; i < mTagLines.size(); i++) {
measureHeight += mTagLines.get(i).height;
if (i != mTagLines.size() - 1) {
measureHeight += mVerticalSpace;
}
}
setMeasuredDimension(mLastMeasureWidth = parentSuggestWidth, mLstMeasureHeight = resolveSize(measureHeight, heightMeasureSpec));
mLastWidthMeasureSpec = widthMeasureSpec;
mLastHeightMeasureSpec = heightMeasureSpec;
mHasMeasured = true;
}
public void setTags(List tagsList) {
mHasMeasured = false;
if (this.mTags == tagsList) {
return;
}
if (maxLines <= DEFAULT_CACHE_LINES || tagsList.size() <= getChildCount()) {//使用缓存
for (int i = 0; i < getChildCount(); i++) {
TextView tagView = (TextView) getChildAt(i);
tagView.setVisibility(View.GONE);
}
if (tagsList != null && tagsList.size() > 0) {
int visibleChildCount = Math.min(tagsList.size(), getChildCount());
for (int i = 0; i < visibleChildCount; i++) {
TextView tagView = (TextView) getChildAt(i);
tagView.setVisibility(View.VISIBLE);
final String tagText = tagsList.get(i);
tagView.setText(tagText);
}
}
} else {//删除 再添加
if (mTags != null && mTags.size() > 0) {
mTags.clear();
}
removeAllViews();
if (tagsList != null && tagsList.size() > 0) {
for (int i = 0; i < tagsList.size(); i++) {
addTag(tagsList.get(i));
}
}
}
}
public List getSelectedTagPositions() {
List selectedList = new ArrayList<>();
if (mTagSelectMode == SELECT_MODE_SINGLE && mCurrentSelected != null) {
selectedList.add(indexOfChild(mCurrentSelected));
} else {
for (int i = 0; i < getChildCount(); i++) {
if (getChildAt(i).getVisibility() == View.VISIBLE && getChildAt(i).isSelected()) {
selectedList.add(i);
}
}
}
return selectedList;
}
private TagLine newTagLine(int maxWidth) {
TagLine tagLine = new TagLine(maxWidth, mHorizontalSpace);
mTagLines.add(tagLine);
return tagLine;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int marginTop = getPaddingTop();
int marginLeft = getPaddingLeft();
for (int i = 0; i < mTagLines.size(); i++) {
TagLine line = mTagLines.get(i);
line.layout(marginLeft, marginTop);
marginTop += mVerticalSpace + line.height;
}
}
public class TagLine {
private List mTagViews = new ArrayList<>();
private int totalWidth;
private int space;
private int usedWidth;
private int height;
public TagLine(int totalWidth, int horizontalSpace) {
this.totalWidth = totalWidth;
this.space = horizontalSpace;
}
public void addView(View child) {
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
if (mTagViews.size() == 0) {
if (childWidth > totalWidth) {
usedWidth = totalWidth;
height = childHeight;
} else {
usedWidth = childWidth;
height = childHeight;
}
} else {
usedWidth = usedWidth + space + childWidth;
height = (childHeight > height) ? childHeight : height;
}
mTagViews.add(child);
}
public boolean accept(View child) {
int width = child.getMeasuredWidth();
if (mTagViews.size() == 0) {
return true;
}
if (usedWidth + width + space > totalWidth) {
return false;
}
return true;
}
public void layout(int marginLeft, int marginTop) {
for (int i = 0; i < mTagViews.size(); i++) {
View child = mTagViews.get(i);
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
int extraTop = (int) ((height - childHeight) / 2f + 0.5f);
int left = marginLeft;
int top = marginTop + extraTop;
int right = left + childWidth;
int bottom = top + childHeight;
child.layout(left, top, right, bottom);
marginLeft += childWidth + space;
}
}
}
}
List tags = new ArrayList<>();
for (GDCommonItem item : items) {
tags.add(item.getRealValue());
}
sexualTags.setTags(tags);
更多推荐
所有评论(0)