项目优化
2019-10-10
1、有人提出经常new ImageView耗内存, 我现在直接new 9个ImageView,可重复使用这几个ImageView
2、修复图片数量为4/7个的时候,高度没计算正确问题
使用方式
holder.pengYouQuanFlagLayout.setImgList(findBean);
<!--朋友圈-->
<com.tpshop.mall.widget.PengYouQuanFlagLayout
android:id="@+id/find_fragment_pengyouquan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_9" />
注意
addView,removeView,都会重新调用onMeasure,onLayout
优化点
onMeasure地方只用来测量高度,onLayout地方只用来布局位置信息
<!--朋友圈-->
<declare-styleable name="PengYouQuanFlagView">
<attr name="pengInterval" format="dimension" />
<attr name="muiPengWidth" format="dimension" />
<attr name="muiPengHeight" format="dimension" />
<attr name="sinPengWidth" format="dimension" />
<attr name="sinPengHeight" format="dimension" />
</declare-styleable>
public abstract class PengYouQuanFlagView extends ViewGroup {
protected abstract void displayImage(int position, ImageView imageView, String url);
protected abstract void onClickImage(int position, String url, ImageView imageView, List<String> imgList);
private int customInterval = 15;//默认的间距
private int muiHeight, muiWidth = 0, sinHeight = 0, sinWidth = 0;//多图的时候高度,宽度,单图时候宽高
private List<String> imgList = new ArrayList<>();//图片的集合
private Context mContext = null;
private List<ImageView> imageViewList;
public PengYouQuanFlagView(Context context) {
this(context, null);
}
public PengYouQuanFlagView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PengYouQuanFlagView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
//初始化自定义属性
initAttrs(context, attrs);
}
private void initAttrs(Context context, AttributeSet attributeSet) {
TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.PengYouQuanFlagView);
customInterval = (int) typedArray.getDimension(R.styleable.PengYouQuanFlagView_pengInterval, getResources().getDimensionPixelSize(R.dimen.dp_7));//默认的边距
muiHeight = (int) typedArray.getDimension(R.styleable.PengYouQuanFlagView_muiPengHeight, getResources().getDimensionPixelSize(R.dimen.dp_93));//多图的时候高度
muiWidth = (int) typedArray.getDimension(R.styleable.PengYouQuanFlagView_muiPengWidth, getResources().getDimensionPixelSize(R.dimen.dp_93));//多图的时候高度
sinWidth = (int) typedArray.getDimension(R.styleable.PengYouQuanFlagView_muiPengHeight, getResources().getDimensionPixelSize(R.dimen.dp_230));//单图的时候宽度
sinHeight = (int) typedArray.getDimension(R.styleable.PengYouQuanFlagView_muiPengHeight, getResources().getDimensionPixelSize(R.dimen.dp_193));//单图的时候高度
imageViewList = new ArrayList<>();
for (int i = 0; i < 9; i++) {
imageViewList.add(creatImageView(i));
}
typedArray.recycle();
}
/**
* @date: 2019/5/21 0021
* @author: gaoxiaoxiong
* @description:设置图片地址链接
**/
public void setImgList(FindBean findBean) {
imgList.clear();
imgList.addAll(findBean.getImgs());
resetLayout();
}
/**
* @date: 2019/5/21 0021
* @author: gaoxiaoxiong
* @description: 重新添加布局
**/
protected void resetLayout() {
removeAllViews();
for (int i = 0; i < imgList.size(); i++) {
ImageView imageView = imageViewList.get(i);
addView(imageView);
displayImage(i, imageView, imgList.get(i));
}
}
/**
* @date: 2019/5/21 0021
* @author: gaoxiaoxiong
* @description:创建图片
**/
public ImageView creatImageView(int position) {
int childCount = imgList.size();
ImageView imageView = new ImageView(mContext);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
if (childCount == 1) {
params.width = sinWidth;
params.height = sinHeight;
} else {
params.width = muiWidth;
params.height = muiHeight;
}
imageView.setLayoutParams(params);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
onClickImage(position, imgList.get(position), (ImageView) view, imgList);
}
});
return imageView;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int mParentMearWidht = MeasureSpec.getSize(widthMeasureSpec);
int line = 1;
int currentWidth = 0, childHeight = 0;//子view的宽度;,子view的高度
int childCount = getChildCount();
if (childCount<=0){
return;
}
for (int i = 0; i < childCount; i++) {
View imageView = getChildAt(i);
measureChild(imageView, widthMeasureSpec, heightMeasureSpec);
int imageWidth = 0;
//中间的图片
if (i == 1 || i == 4 || i == 7) {
imageWidth = imageView.getMeasuredWidth() + customInterval * 2;
} else {//不是中间的图片
imageWidth = imageView.getMeasuredWidth();
}
childHeight = imageView.getMeasuredHeight() + customInterval * 2;
if (mParentMearWidht - currentWidth >= imageWidth) {
currentWidth = currentWidth + imageWidth;
} else {//需要换行
line = line + 1;
currentWidth = 0;
}
}
//再次校验高度是否正确
View imageView = getChildAt(0);
int liYingHeight = 0;
if (childCount >= 0 && childCount <= 3) {
liYingHeight = (imageView.getMeasuredHeight() + customInterval * 2) * 1;
} else if (childCount >= 4 && childCount <= 6) {
//理应高度
liYingHeight = (imageView.getMeasuredHeight() + customInterval * 2) * 2;
} else if (childCount >= 7) {
//理应高度
liYingHeight = (imageView.getMeasuredHeight() + customInterval * 2) * 3;
}
//代码计算高度
int jisuanHeight = childHeight * line;
if (liYingHeight != jisuanHeight) {
if (childCount >= 0 && childCount <= 3) {
line = 1;
} else if (childCount >= 4 && childCount <= 6) {
line = 2;
} else if (childCount >= 7) {
line = 3;
}
}
setMeasuredDimension(mParentMearWidht, childHeight * line);
}
@Override
protected void onLayout(boolean b, int i0, int i1, int i2, int i3) {
int childCount = getChildCount();
//整个View的宽度
int mParentWidth = this.getMeasuredWidth();
int left = 0, top = 0;
for (int i = 0; i < childCount; i++) {
View imageView = getChildAt(i);
//获取子View的宽高,判断一行是否可以放的下,如果放不下,需要换行
int childHeight = imageView.getMeasuredHeight();
int childWidth = imageView.getMeasuredWidth();
if (mParentWidth - left >= childWidth) {
imageView.layout(left, top, left + childWidth, top + childHeight);
left = left + childWidth + customInterval;
} else {
left = 0;
top = top + childHeight + customInterval;
imageView.layout(left, top, left + childWidth, top + childHeight);
left = childWidth + customInterval;
}
}
}
}
这里将显示图片的方式移到这里处理
public class PengYouQuanFlagLayout extends PengYouQuanFlagView{
private String TAG = PengYouQuanFlagLayout.class.getSimpleName();
private Context mContext;
public PengYouQuanFlagLayout(Context context) {
this(context,null);
}
public PengYouQuanFlagLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
}
@Override
protected void displayImage(int position, ImageView imageView, String url) {
if (mContext!=null){
Glide.with(mContext).load(url).into(imageView);
}
}
@Override
protected void onClickImage(int position, String url, ImageView imageView, List<String> imgList) {
//处理图片地方
}
}
感悟
1、需要先addView,增加childCount个数,addView完后,不需要requestLayout(),因为addView已经帮你操作了
2、为啥每次addView都要重新onMeasure,onLayout,只测量一次不好么?
因为每次新增一个图片进来后,我们布局的位置和宽度都会发生变化,所以每次addView一次进来,都需要重新测量。
3、假如我将ImageView动态设置的宽高是198px,当我在onLayout布局的时候,即调用imageView.layout(left, top,right, bottom);方法,如果我right - left < 198 或 bottom - top < 198 都会导致界面显示不完全。我们可以想象一下,我们的画的imageView是在一个盒子里面,如果盒子太小了,就会导致界面变小。