上传图片控件自定义,流式布局
程序员文章站
2022-05-30 22:11:53
...
控件模仿微信的,点击“+”上传图片,封装为一个控件,实现流式布局,超过一行自动换行排布。
这个流式布局的作用只是,排布,摆放,具体展示的图片是通过将xml布局inflate然后添加到该流式布局中来实现的。
package com.family.fw.view;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
/**
* 流式布局。可根据子View的宽度实现自动换行。
*
*/
public class FlowLayout extends ViewGroup {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FlowLayout(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int[] size = measure(this, widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(size[0], size[1]);
}
static int[] measure(ViewGroup group, int widthMeasureSpec, int heightMeasureSpec) {
int width = resolveSize(0, widthMeasureSpec);
int pl = group.getPaddingLeft();
int pt = group.getPaddingTop();
int pr = group.getPaddingRight();
int pb = group.getPaddingBottom();
int left = pl;
int top = pt;
int right = width - pr;
int lineHeight = 0;
// 通过计算每一个子控件的高度,得到自己的高度
for (int i = 0, childCount = group.getChildCount(); i < childCount; ++i) {
View child = group.getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
}
MarginLayoutParams layout = (MarginLayoutParams) child.getLayoutParams();
child.measure(getChildMeasureSpec(widthMeasureSpec, pl + pr, layout.width),
getChildMeasureSpec(heightMeasureSpec, pt + pb, layout.height));
int cow = child.getMeasuredWidth() + layout.leftMargin;
int coh = child.getMeasuredHeight() + layout.topMargin + layout.bottomMargin;
left += cow;
if (left > right) {
left = pl + cow;
top += lineHeight;
lineHeight = coh;
} else if (coh > lineHeight) {
lineHeight = coh;
}
left += layout.rightMargin;
}
return new int[] { width, resolveSize(top + lineHeight + pb, heightMeasureSpec) };
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
layout(this, changed, l, t, r, b);
}
static void layout(ViewGroup group, boolean changed, int l, int t, int r, int b) {
int pl = group.getPaddingLeft();
int left = pl;
int top = group.getPaddingTop();
int right = r - l - group.getPaddingRight();
int lineHeight = 0;
// 根据子控件的宽高,计算子控件应该出现的位置。
for (int i = 0, childCount = group.getChildCount(); i < childCount; ++i) {
View child = group.getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
}
MarginLayoutParams layout = (MarginLayoutParams) child.getLayoutParams();
int cw = child.getMeasuredWidth();
int ch = child.getMeasuredHeight();
int ml = layout.leftMargin;
int mt = layout.topMargin;
int thisH = ch + mt + layout.bottomMargin;
left += ml;
if (left + cw > right) {
left = pl + ml;
top += lineHeight;
lineHeight = thisH;
} else {
lineHeight = Math.max(thisH, lineHeight);
}
child.layout(left, top + mt, left + cw, top + mt + ch);
left += cw + layout.rightMargin;
}
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
}
在xml布局中:
<com.family.fw.view.FlowLayout
android:id="@+id/evaluationImgs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:paddingRight="20dp" >
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@drawable/advice_image"
android:contentDescription="@string/desc"
android:scaleType="centerCrop"
round:radius="5dp" />
</com.family.fw.view.FlowLayout>
效果图:
推荐阅读