網(wǎng)上有很多的自動換行的layout了,但看了一圈蓬网,感覺很多人都把問題想復(fù)雜了窒所,這也就導(dǎo)致了代碼的復(fù)雜。有些時(shí)候你想要的只是一個(gè)可以自動換行的layout帆锋,可以設(shè)置橫豎間距吵取,不需要其他一些奇奇怪怪的功能和設(shè)置一些奇奇怪怪的屬性。那么你可以考慮我寫的這個(gè)
public class AutoLineLayout extends ViewGroup {
private int horizontalSpace;
private int verticalSpace;
private int theRealWidth;
public AutoLineLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray array=context.obtainStyledAttributes(attrs, R.styleable.AutoLineLayout);
horizontalSpace= (int) Math.ceil(array.getDimension(R.styleable.AutoLineLayout_horizontalSpace,0));
verticalSpace=(int) Math.ceil(array.getDimension(R.styleable.AutoLineLayout_verticalSpace,0));
array.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//不測算寬度模式锯厢,因?yàn)椴还苁莣rap_content還是match_parent都按match_parent來算
int widthSize=MeasureSpec.getSize(widthMeasureSpec);
int heightMode=MeasureSpec.getMode(heightMeasureSpec);
int heightSize=MeasureSpec.getSize(heightMeasureSpec);
int lineWidth=0;
int lineHeight=0;
int height=0;
int paddingStart=getPaddingStart();
int paddingEnd=getPaddingEnd();
int size=widthSize-paddingStart-paddingEnd;
theRealWidth=size;
measureChildren(widthMeasureSpec,heightMeasureSpec);
for (int i=0;i<getChildCount();i++){
View view=getChildAt(i);
int childHeight=view.getMeasuredHeight();
int childWidth=view.getMeasuredWidth();
int nowWidth=childWidth+lineWidth;
boolean changeLine=nowWidth>size;
changeLine=changeLine||(nowWidth-horizontalSpace>size);
if (changeLine){
lineWidth=childWidth+horizontalSpace;
height+=lineHeight+verticalSpace;//這里的lineHeight其實(shí)是上一行的所有view的高度的最大值
lineHeight=childHeight;
}else {
lineHeight=Math.max(lineHeight,childHeight);
lineWidth+=childWidth+horizontalSpace;
if (i==0)
height+=lineHeight;
}
}
height+=getPaddingTop()+getPaddingBottom();
setMeasuredDimension(widthSize,heightMode==MeasureSpec.EXACTLY?heightSize:height);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int paddingStart=getPaddingStart();
int leftOffset = paddingStart;
int topOffset = getPaddingTop();
int lineHeight=0;
for (int i=0;i<getChildCount();i++){
View childView=getChildAt(i);
int childWidth=childView.getMeasuredWidth();
int childHeight=childView.getMeasuredHeight();
int nowWidth=childWidth+leftOffset;
boolean changeLine=nowWidth>theRealWidth;
changeLine=changeLine||(nowWidth-horizontalSpace>theRealWidth);
if (changeLine){
leftOffset=paddingStart;
topOffset+=lineHeight+verticalSpace;
childView.layout(leftOffset,topOffset,childWidth+leftOffset,topOffset+childHeight);
leftOffset+=childWidth+horizontalSpace;
lineHeight=childHeight;
}else {
childView.layout(leftOffset,topOffset,childWidth+leftOffset,topOffset+childHeight);
leftOffset+=childWidth+horizontalSpace;
lineHeight=Math.max(lineHeight,childHeight);
}
}
}
}
下面是attr里的屬性皮官,用來控制當(dāng)前每個(gè)View之間的橫向間距和每行之間的縱向間距
//這個(gè)是之前在有個(gè)地方看到的,他的自動換行增加了這兩個(gè)屬性实辑,我覺得很方便捺氢。 就拿過來用了
<declare-styleable name="AutoLineLayout">
<attr name="horizontalSpace" format="dimension"/>
<attr name="verticalSpace" format="dimension"/>
</declare-styleable>
網(wǎng)上的很多自動換行的View泥彤,都喜歡重寫generateLayoutParams信不,返回一個(gè)帶margin的lp实昨。我感覺是沒有必要的耀鸦。因?yàn)橐呀?jīng)有horizontalSpace和verticalSpace兩個(gè)屬性可以控制間距粟瞬,同時(shí)也支持padding了俗孝,個(gè)人感覺是夠用了条舔。同時(shí)叙赚,像這樣的自動換行的layout梨水,一般是從網(wǎng)絡(luò)獲取數(shù)據(jù)之后動態(tài)填充挤茄,也沒有必要考慮margin。 下面是動態(tài)添加的效果圖
以及在xml文件中寫死的情況下的效果圖
補(bǔ)充冰木,關(guān)于點(diǎn)擊事件
關(guān)于點(diǎn)擊事件穷劈,我的想法是由添加進(jìn)來的控件本身來處理笼恰,和這個(gè)layout無關(guān),你可以這樣完成點(diǎn)擊事件:
歡迎提出意見和改進(jìn)