Android仿淘宝搜索历史界面功能
一 关于自定义viewGroup
二 关于MeasureSpec
三 关于流式布局Measure流程
LayoutParams childLP = childView.getLayoutParams();int childWidthMesureSpec =getChildMeasureSpec(widthMeasureSpec,paddingLeft+paddingRight,childLP.width);int childHeightMesureSpec =getChildMeasureSpec(heightMeasureSpec,paddingBottom+paddingTop,childLP.height);childView.measure(childWidthMesureSpec,childHeightMesureSpec);
if (childMesuredWidth + lineWidthUsed +mHorizontalSpacing > selfWidth){allLines.add(lineViews);lineHeights.add(lineHeight);//一旦换行,可以判断当前所需的宽高了parentNeededWidth = Math.max(parentNeededWidth,lineWidthUsed+mHorizontalSpacing);parentNeededHeight = parentNeededHeight + lineHeight +mVerticalSpacing;lineViews =new ArrayList<>();lineWidthUsed =0;lineHeight =0;}
int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int realWidth = (widthMode == MeasureSpec.EXACTLY)? selfWidth:parentNeededWidth;int realHeight = (heightMode == MeasureSpec.EXACTLY)?selfHeight:parentNeededHeight;setMeasuredDimension(realWidth,realHeight);
四 关于layout流程
int lineCount =allLines.size();int curL =0;int curT =0;for (int i =0;iList lineViews =allLines.get(i);int lineHeight =lineHeights.get(i);for (int j =0;jView view = lineViews.get(j);int left = curL;int top = curT;int bottom = top + view.getMeasuredHeight();int right = left + view.getMeasuredWidth();view.layout(left,top,right,bottom);curL = right +mHorizontalSpacing;}curL =0;curT = curT + lineHeight +mVerticalSpacing;
public class FlowLayoutextends ViewGroup {private int mHorizontalSpacing =dp2px(16); //每个item横向间距private int mVerticalSpacing =dp2px(8); //每个item横向间距private List>allLines ; // 记录所有的行,一行一行的存储private ListlineHeights =new ArrayList<>(); // 记录每一行的行高boolean isMeasuredOver =false;public FlowLayout(Context context) {super(context);}public FlowLayout(Context context, AttributeSet attrs) {super(context, attrs);}public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {initMeasureParams();int childCount = getChildCount();int paddingLeft = getPaddingLeft();int paddingRight = getPaddingRight();int paddingTop = getPaddingTop();int paddingBottom = getPaddingBottom();int selfWidth = MeasureSpec.getSize(widthMeasureSpec); //ViewGroup解析的宽度int selfHeight = MeasureSpec.getSize(heightMeasureSpec); // ViewGroup解析的高度List lineViews =new ArrayList<>(); //保存一行中的所有的viewint lineWidthUsed =0; //记录这行已经使用了多宽的sizeint lineHeight =0; // 一行的行高int parentNeededWidth =0; // measure过程中,子View要求的父ViewGroup的宽int parentNeededHeight =0; // measure过程中,子View要求的父ViewGroup的高for (int i =0;iView childView = getChildAt(i);LayoutParams childLP = childView.getLayoutParams();int childWidthMesureSpec =getChildMeasureSpec(widthMeasureSpec,paddingLeft+paddingRight,childLP.width);int childHeightMesureSpec =getChildMeasureSpec(heightMeasureSpec,paddingBottom+paddingTop,childLP.height);childView.measure(childWidthMesureSpec,childHeightMesureSpec);//获取子view的宽高int childMesuredWidth = childView.getMeasuredWidth();int childMesuredHeight = childView.getMeasuredHeight();//通过宽度来判断是否需要换行,通过换行后的每行的行高来获取整个viewGroup的行高//如果宽度不够,则需换行if (childMesuredWidth + lineWidthUsed +mHorizontalSpacing > selfWidth){allLines.add(lineViews);lineHeights.add(lineHeight);//一旦换行,可以判断当前所需的宽高了parentNeededWidth = Math.max(parentNeededWidth,lineWidthUsed+mHorizontalSpacing);parentNeededHeight = parentNeededHeight + lineHeight +mVerticalSpacing;lineViews =new ArrayList<>();lineWidthUsed =0;lineHeight =0;}// view 是分行layout的,所以要记录每一行有哪些view,这样可以方便layout布局lineViews.add(childView);lineWidthUsed = lineWidthUsed + childMesuredWidth +mHorizontalSpacing;lineHeight = Math.max(lineHeight,childMesuredHeight);//childview 最后一行if (i == childCount -1){lineHeights.add(lineHeight);allLines.add(lineViews);parentNeededWidth = Math.max(parentNeededWidth,lineWidthUsed );parentNeededHeight += lineHeight;}//根据子View的度量结果,来重新度量自己ViewGroup// 作为一个ViewGroup,它自己也是一个View,它的大小也需要根据它的父亲给它提供的宽高来度量int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int realWidth = (widthMode == MeasureSpec.EXACTLY)? selfWidth:parentNeededWidth;int realHeight = (heightMode == MeasureSpec.EXACTLY)?selfHeight:parentNeededHeight;setMeasuredDimension(realWidth,realHeight);isMeasuredOver =true;}}private void initMeasureParams() {allLines =new ArrayList<>();lineHeights =new ArrayList<>();}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int lineCount =allLines.size();int curL =0;int curT =0;for (int i =0;iList lineViews =allLines.get(i);int lineHeight =lineHeights.get(i);for (int j =0;jView view = lineViews.get(j);int left = curL;int top = curT;int bottom = top + view.getMeasuredHeight();int right = left + view.getMeasuredWidth();view.layout(left,top,right,bottom);curL = right +mHorizontalSpacing;}curL =0;curT = curT + lineHeight +mVerticalSpacing;}}public static int dp2px(int dp) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().getDisplayMetrics());}}
六 项目运行截图

评论
