Skip to content

Instantly share code, notes, and snippets.

@solohsu
Created September 9, 2016 07:42
Show Gist options
  • Save solohsu/5ef585718bf04546d01ec065532ba16c to your computer and use it in GitHub Desktop.
Save solohsu/5ef585718bf04546d01ec065532ba16c to your computer and use it in GitHub Desktop.
WidthAutoAdjustLinearLayout
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
/**
* 根据可以完整显示的所有子view的总宽度自动调整自身的宽度.
* <p/>
* 当第n个childView可以完整显示,第n+1个childView无法完整显示时,不显示n+1及其以后的childView,
* 并将宽度调整为n个childView的总宽度.
* <p/>
* Created by soloslxu on 2015/12/21.
*/
public class WidthAutoAdjustLinearLayout extends LinearLayout {
public WidthAutoAdjustLinearLayout(Context context) {
this(context, null);
}
public WidthAutoAdjustLinearLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public WidthAutoAdjustLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOrientation(HORIZONTAL);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 减左右padding后得到children可用的宽度
int availableWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
int totalWidth = 0;
int maxTotalWidth = -1;
boolean maxChildIndexFound = false;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (child == null || child.getVisibility() == GONE) {
continue;
}
if (maxChildIndexFound) {
// 已找到最多可容纳的child,后面的child都设为GONE,直接跳过layout
child.setVisibility(GONE);
} else {
LayoutParams lp = (LayoutParams) child.getLayoutParams();
// 获取childView不被截断时的完整宽度,不要重新measure height,
// 否则会使child的height的match_parent属性无效
child.measure(0, heightMeasureSpec);
int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
totalWidth += childWidth;
if (totalWidth > availableWidth) {
// 记录可完整显示的children的总长度
maxChildIndexFound = true;
if (i == 0) {
// 如果第一个长度就超了,对第一个进行截断处理,不要GONE掉
maxTotalWidth = availableWidth;
child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), MeasureSpec.EXACTLY));
} else {
// 后面的如果超了,GONE掉
maxTotalWidth = totalWidth - childWidth;
child.setVisibility(GONE);
}
} else if (totalWidth == availableWidth) {
// 如果前0~i正好达到最大宽度,第i个child的宽度不需要减掉,也不需要隐藏,
// 仅需记录标志位,让后面的child隐藏。
maxChildIndexFound = true;
maxTotalWidth = totalWidth;
}
}
}
// 重设宽度
if (maxChildIndexFound) {
// 不能完整显示所有child,设为计算出的最大宽度maxTotalWidth
setMeasuredDimension(maxTotalWidth, getMeasuredHeight());
} else {
// 可以完整显示所有child,设为所有child的总宽度之和
setMeasuredDimension(totalWidth, getMeasuredHeight());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment