首先我们会先自定义个控件PileView
public class PileView extends ViewGroup {
protected float vertivalSpace;//垂直间隙
protected float pileWidth=0;//重叠宽度
public PileView(Context context) {
this(context, null, 0);
}
public PileView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PileView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttr(context, attrs);
}
private void initAttr(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PileLayout);
vertivalSpace = ta.getDimension(R.styleable.PileLayout_PileLayout_vertivalSpace, dp2px(4));
pileWidth = ta.getDimension(R.styleable.PileLayout_PileLayout_pileWidth, dp2px(10));
ta.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
//AT_MOST
int width = 0;
int height = 0;
int rawWidth = 0;//当前行总宽度
int rawHeight = 0;// 当前行高
int rowIndex = 0;//当前行位置
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if(child.getVisibility() == GONE){
if(i == count - 1){
//最后一个child
height += rawHeight;
width = Math.max(width, rawWidth);
}
continue;
}
//调用measureChildWithMargins 而不是measureChild
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
if(rawWidth + childWidth - (rowIndex > 0 ? pileWidth : 0)> widthSpecSize - getPaddingLeft() - getPaddingRight()){
//换行
width = Math.max(width, rawWidth);
rawWidth = childWidth;
height += rawHeight + vertivalSpace;
rawHeight = childHeight;
rowIndex = 0;
} else {
rawWidth += childWidth;
if(rowIndex > 0){
rawWidth -= pileWidth;
}
rawHeight = Math.max(rawHeight, childHeight);
}
if(i == count - 1){
width = Math.max(rawWidth, width);
height += rawHeight;
}
rowIndex++;
}
setMeasuredDimension(
widthSpecMode == MeasureSpec.EXACTLY ? widthSpecSize : width + getPaddingLeft() + getPaddingRight(),
heightSpecMode == MeasureSpec.EXACTLY ? heightSpecSize : height + getPaddingTop() + getPaddingBottom()
);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int viewWidth = r - l;
int leftOffset = getPaddingLeft();
int topOffset = getPaddingTop();
int rowMaxHeight = 0;
int rowIndex = 0;//当前行位置
View childView;
for( int w = 0, count = getChildCount(); w < count; w++ ){
childView = getChildAt(w);
if(childView.getVisibility() == GONE) continue;
MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams();
// 如果加上当前子View的宽度后超过了ViewGroup的宽度,就换行
int occupyWidth = lp.leftMargin + childView.getMeasuredWidth() + lp.rightMargin;
if(leftOffset + occupyWidth + getPaddingRight() > viewWidth){
leftOffset = getPaddingLeft(); // 回到最左边
topOffset += rowMaxHeight + vertivalSpace; // 换行
rowMaxHeight = 0;
rowIndex = 0;
}
int left = leftOffset + lp.leftMargin;
int top = topOffset + lp.topMargin;
int right = leftOffset+ lp.leftMargin + childView.getMeasuredWidth();
int bottom = topOffset + lp.topMargin + childView.getMeasuredHeight();
childView.layout(left, top, right, bottom);
// 横向偏移
leftOffset += occupyWidth;
// 试图更新本行最高View的高度
int occupyHeight = lp.topMargin + childView.getMeasuredHeight() + lp.bottomMargin;
if(rowIndex != count - 1){
leftOffset -= pileWidth;
}
rowMaxHeight = Math.max(rowMaxHeight, occupyHeight);
rowIndex++;
}
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
@Override
protected LayoutParams generateLayoutParams(LayoutParams p) {
return new MarginLayoutParams(p);
}
public float dp2px(float dpValue) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, getResources().getDisplayMetrics());
}
}
//控件中的自定义属性PileLayout
<declare-styleable name="PileLayout">
<attr name="PileLayout_vertivalSpace" format="dimension"/>
<attr name="PileLayout_pileWidth" format="dimension"/>
</declare-styleable>
可以直接放到styles中
2.我们在这个控件的基础上再次封装一下 PileAvertView
public class PileAvertView extends LinearLayout {
@BindView(R.id.pile_view)
PileView pileView;
private Context context = null;
public static final int VISIBLE_COUNT = 3;//默认显示个数
public PileAvertView(Context context) {
this(context, null);
this.context = context;
}
public PileAvertView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initView();
}
private void initView() {
View view = LayoutInflater.from(context).inflate(R.layout.layout_group_pile_avert, this);
ButterKnife.bind(view);
}
public void setAvertImages(List<String> imageList) {
setAvertImages(imageList,VISIBLE_COUNT);
}
//如果imageList>visiableCount,显示List最上面的几个
public void setAvertImages(List<String> imageList, int visibleCount) {
List<String> visibleList = null;
if (imageList.size() > visibleCount) {
visibleList = imageList.subList(imageList.size() - 1 - visibleCount, imageList.size() - 1);
}
pileView.removeAllViews();
for (int i = 0; i < visibleList.size(); i++) {
NiceImageView image= (NiceImageView) LayoutInflater.from(context).inflate(R.layout.item_group_round_avert, pileView, false);
Utils.loadImage(context,visibleList.get(i), image);
pileView.addView(image);
}
}
}
里面包含的两个布局
layout_group_pile_avert
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:gravity="center">
<social.milin.tech.loaddown.fugai.PileView
android:id="@+id/pile_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:PileLayout_pileWidth="10dp"/>
</LinearLayout>
item_group_round_avert布局
<social.milin.tech.loaddown.cireview.NiceImageView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/circle_iamge"
android:layout_width="60dp"
android:layout_height="60dp"
android:orientation="vertical"
android:src="@drawable/ic_launcher_background"
app:corner_radius="30dp">
</social.milin.tech.loaddown.cireview.NiceImageView>
这里说明一下,第二个这个布局也是一个自定义控件,他是自定义圆角图片
我会在另一个博客里单独写,当然,你用自己的也可以
这样的话,我们都整理好了,直接可以用这个控件
<social.milin.tech.loaddown.fugai.PileAvertView
android:id="@+id/pv"
android:layout_width="match_parent"
android:background="#cccccc"
android:gravity="center"
android:layout_height="80dp">
</social.milin.tech.loaddown.fugai.PileAvertView>
最后一步
pv.setAvertImages(list,3);
public static void loadImage(Context context,String str,NiceImageView img){
Glide.with(context).load(str).into(img);
}
list为所有图片的一个集合,第二个参数不写的话,默认显示前3个,写的话,写几就显示几个
就这些内容,拜~