Android仿拼多多实现图片叠加部分覆盖效果
需要实现的效果如下:
代码部分:
AppIconStackView:
public class AppIconStackView extends ViewGroup {
private Context context;
private List<String> allUrls = new ArrayList<>();
private boolean flag = true;//false表示右边增加,true表示左边增加
private static final int SPWIDTH = 50;
//在new的时候会调用此方法
public AppIconStackView(Context context) {
super(context);
this.context = context;
}
public AppIconStackView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public AppIconStackView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
//wrap_content
int width = 0;
int height = 0;
//每一行的,宽,高
int lineWidth = 0;
int lineHeight = 0;
//获取所有的子view
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
//测量子view
measureChild(child, widthMeasureSpec, heightMeasureSpec);
//得到layoutparams
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
if (lineWidth + childWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) {
//换行判断
height += lineHeight;
//新的行高
lineHeight = childHeight;
width = Math.max(width, lineWidth);
lineWidth = childWidth;
} else {
lineWidth += childWidth;
lineHeight = Math.max(lineHeight, childHeight);
}
if (i == count - 1) {
width = Math.max(lineWidth, width);
height += lineHeight;
}
}
setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width,
modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height);
}
/**
* 存储所有的View.
*/
private List<List<View>> mAllViews = new ArrayList<List<View>>();
/**
* 每一行的高度.
*/
private List<Integer> mLineHeight = new ArrayList<Integer>();
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
mAllViews.clear();
mLineHeight.clear();
int width = getWidth();
int lineWidth = 0;
int lineHeight = 0;
List<View> lineViews = new ArrayList<View>();
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin
> width - getPaddingRight() - getPaddingLeft()) {
mLineHeight.add(lineHeight);
mAllViews.add(lineViews);
lineViews = new ArrayList<>();
lineWidth = 0;
lineHeight = childHeight + lp.topMargin + lp.bottomMargin;
}
lineWidth += childWidth + lp.leftMargin + lp.rightMargin - SPWIDTH;
lineHeight = Math.max(lineHeight, childHeight + lp.topMargin
+ lp.bottomMargin);
lineViews.add(child);
}
// 处理最后一行
mLineHeight.add(lineHeight);
mAllViews.add(lineViews);
// 设置子View的位置
int left = getPaddingLeft();
int top = getPaddingTop();
// 行数
int lineNum = mAllViews.size();
for (int i = 0; i < lineNum; i++) {
lineViews = mAllViews.get(i);
lineHeight = mLineHeight.get(i);
//反序显示
if (flag) {
Collections.reverse(lineViews);
}
for (int j = 0; j < lineViews.size(); j++) {
View child = lineViews.get(j);
if (child.getVisibility() == View.GONE) {
continue;
}
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int lc = left + lp.leftMargin;
int tc = top + lp.topMargin;
int rc = lc + child.getMeasuredWidth();
int bc = tc + child.getMeasuredHeight();
child.layout(lc, tc, rc, bc);
left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin - SPWIDTH;
}
left = getPaddingLeft();
top += lineHeight;
}
}
/**
* 设置图片链接.
*
* @param listVals .
*/
public void setUrls(List<String> listVals) {
allUrls.clear();
allUrls.addAll(listVals);
//开始绘制view
setViews();
}
private void setViews() {
//清空,重新绘制
removeAllViews();
for (int i = 0; i < allUrls.size(); i++) {
//清空重新绘制
ImageView imageView = (ImageView) LayoutInflater.from(context).inflate(
R.layout.item_stack, this, false);
Glide.with(context).load(allUrls.get(i))
.error(R.drawable.ic_launcher)
.apply(RequestOptions.bitmapTransform(new CircleCrop()))
.into(imageView);
this.addView(imageView);
}
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
}
item_stack:
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="60px"
android:layout_height="60px">
</ImageView>
使用方法:
在xml文件中使用此自定义view:
<com.ford.hmi.appstore.view.custom.AppIconStackView
android:id="@+id/update_topThree_appIcon"
android:layout_width="wrap_content"
android:layout_height="64px"
android:layout_centerVertical="true" />
为此view设置数据:
调用 setUrls 将图片链接设置进去即可。