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的主要内容,如果未能解决你的问题,请参考以下文章

自定义控件三部曲视图篇——瀑布流容器WaterFallLayout实现

android炫酷动画源码,QQ菜单瀑布流二维码源码

vue-waterfall2 基于Vue.js 瀑布流组件

Flutter最酷炫瀑布流实现

Flutter最酷炫瀑布流实现

自定义UICollectinviewFlowLayout,即实现瀑布流