学习笔记,整理中
摘要
面
1、layoutparams:xml的属性转换为java用的格式
2、面必问:measurespec
------------------------------------
主要讲 自定义viewgroup,viewpager
1、所有的xml解析 都在 layoutinflater里面
2、自定义view至少3个构造函数,java new view调用;xml 反射调用;不同主题调用;自定义属性用(这个很少用)
4、source insite
5、jianshu.com/p/0723ff4123e1 flexboxlayout 流式布局
----------------------------------
实现UI: 自定义VIew
java 语言
自定义View android 基础
自定义View 包含什么?
布局: onlayout onmeausre/ Layout:viewGroup
显示: onDraw :view: canvas paint matrix clip rect animation path(贝塞尔) line text绘制
frameWork:
交互: onTouchEvent :组合的viewGroup
大量的实战,实践/
jett:xml解析原理,view层次结构,插件化换肤
2000平
序列化
自定义序列化: IOT
协议
物联网:蓝牙:传递的数据 串口 协议:
子
自己 ;viewPager
都可以:算法
先孩子再自己
android:layout_width="wrap_content" -》xxx dp dip
android:layout_height="wrap_content"
很多知识:算法
MeasureSpec :
size 值
0~10000
int 32:
30
int 11000000000000000000000
mode:高两位:UNSPECIFIED, EXACTLY, AT_MOST
01 00 11
算法是怎样的?
SDK一个包:严谨性,可拓展性
内容
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
public class FlowLayoutextends ViewGroup {
private static final StringTAG ="FlowLayout";
private int mHorizontalSpacing =dp2px(16); //每个item横向间距
private int mVerticalSpacing =dp2px(8); //每个item横向间距
private List>allLines =new ArrayList<>(); // 记录所有的行,一行一行的存储,用于layout
ListlineHeights =new ArrayList<>(); // 记录每一行的行高,用于layout
public FlowLayout(Context context) {
super(context);
// initMeasureParams();
}
//反射
public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// initMeasureParams();
}
//主题style
public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// initMeasureParams();
}
//四个参数 自定义属性
private void clearMeasureParams() {
allLines.clear();
lineHeights.clear();
}
//度量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
clearMeasureParams();//内存 抖动
//先度量孩子
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<>(); //保存一行中的所有的view
int lineWidthUsed =0; //记录这行已经使用了多宽的size
int lineHeight =0; // 一行的行高
int parentNeededWidth =0; // measure过程中,子View要求的父ViewGroup的宽
int parentNeededHeight =0; // measure过程中,子View要求的父ViewGroup的高
for (int i =0; i < childCount; i++) {
View childView = getChildAt(i);
LayoutParams childLP = childView.getLayoutParams();
if (childView.getVisibility() != View.GONE) {
//将layoutParams转变成为measureSpec
int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight,
childLP.width);
int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom,
childLP.height);
childView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
//获取子view的度量宽高
int childMesauredWidth = childView.getMeasuredWidth();
int childMeasuredHeight = childView.getMeasuredHeight();
//如果需要换行
if (childMesauredWidth + lineWidthUsed +mHorizontalSpacing > selfWidth) {
//一旦换行,我们就可以判断当前行需要的宽和高了,所以此时要记录下来
allLines.add(lineViews);
lineHeights.add(lineHeight);
parentNeededHeight = parentNeededHeight + lineHeight +mVerticalSpacing;
parentNeededWidth = Math.max(parentNeededWidth, lineWidthUsed +mHorizontalSpacing);
lineViews =new ArrayList<>();
lineWidthUsed =0;
lineHeight =0;
}
// view 是分行layout的,所以要记录每一行有哪些view,这样可以方便layout布局
lineViews.add(childView);
//每行都会有自己的宽和高
lineWidthUsed = lineWidthUsed + childMesauredWidth +mHorizontalSpacing;
lineHeight = Math.max(lineHeight, childMeasuredHeight);
//处理最后一行数据
if (i == childCount -1) {
allLines.add(lineViews);
lineHeights.add(lineHeight);
parentNeededHeight = parentNeededHeight + lineHeight +mVerticalSpacing;
parentNeededWidth = Math.max(parentNeededWidth, lineWidthUsed +mHorizontalSpacing);
}
}
}
//再度量自己,保存
//根据子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);
}
//布局
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int lineCount =allLines.size();
int curL = getPaddingLeft();
int curT = getPaddingTop();
for (int i =0; i < lineCount; i++){
List lineViews =allLines.get(i);
int lineHeight =lineHeights.get(i);
for (int j =0; j < lineViews.size(); j++){
View view = lineViews.get(j);
int left = curL;
int top = curT;
// int right = left + view.getWidth();
// int bottom = top + view.getHeight();
int right = left + view.getMeasuredWidth();
int bottom = top + view.getMeasuredHeight();
view.layout(left,top,right,bottom);
curL = right +mHorizontalSpacing;
}
curT = curT + lineHeight +mVerticalSpacing;
curL = getPaddingLeft();
}
}
// @Override
// protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
// }
public static int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().getDisplayMetrics());
}
}