Android 自定义View 手写瀑布流组件FlowLayout
Posted 安卓开发-顺
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 自定义View 手写瀑布流组件FlowLayout相关的知识,希望对你有一定的参考价值。
纸上得来终觉浅,绝知此事要躬行。
动手实践是学习的最好的方式,对于自定义View来说,听和看只能是过一遍流程,能掌握个30%、40%就不错了,而且很快就会遗忘,想变成自己的东西必须动手来写几遍,细细体会其中的细节和系统API的奥秘、真谛。
进入主题,今天来手写一个瀑布流组件FlowLayout,温习下自定义view的流程和关键点,先来张效果图
FlowLayout实现关键步骤:
1、创建一个view继承自ViewGroup
class ZSFlowLayout : ViewGroup
constructor(context: Context) : super(context)
/**
* 必须的构造函数,系统会通过反射来调用此构造方法完成view的创建
*/
constructor(context: Context, attr: AttributeSet) : super(context, attr)
constructor (context: Context, attr: AttributeSet, defZStyle: Int) : super(
context,
attr,
defZStyle
)
这里注意两个参数的构造函数是必须的构造函数,系统会通过反射来调用此构造方法完成view的创建,具体调用位置在LayoutInflater 的 createView方法中,如下(基于android-31):
省略了若干不相关代码,并写了重要的注释信息,请留意
public final View createView(@NonNull Context viewContext, @NonNull String name,
@Nullable String prefix, @Nullable AttributeSet attrs)
throws ClassNotFoundException, InflateException
Objects.requireNonNull(viewContext);
Objects.requireNonNull(name);
//从缓存中取对应的构造函数
Constructor<? extends View> constructor = sConstructorMap.get(name);
Class<? extends View> clazz = null;
try
if (constructor == null)
// 通过反射创建class对象
clazz = Class.forName(prefix != null ? (prefix + name) : name, false,
mContext.getClassLoader()).asSubclass(View.class);
//创建构造函数 这里的mConstructorSignature 长这个样子
//static final Class<?>[] mConstructorSignature = new Class[]
// Context.class, AttributeSet.class;
//看到了没 就是我们第二个构造方法
constructor = clazz.getConstructor(mConstructorSignature);
constructor.setAccessible(true);
//缓存构造方法
sConstructorMap.put(name, constructor);
else
...
try
//执行构造函数 创建出view
final View view = constructor.newInstance(args);
...
return view;
finally
mConstructorArgs[0] = lastContext;
catch (Exception e)
...
finally
...
2、重写并实现onMeasure方法
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int)
这里要重点解释下 widthMeasureSpec 和 heightMeasureSpec是怎么来的
3、重写并实现onLayout方法
以上是关于Android 自定义View 手写瀑布流组件FlowLayout的主要内容,如果未能解决你的问题,请参考以下文章