欢迎光临散文网 会员登陆 & 注册

自定义ViewGroup实现类似B站历史记录布局

2023-06-15 18:33 作者:便宜酒  | 我要投稿

需求:为用户提供ai画图的咒语标签,这些标签长短不一,既要类似瀑布流紧密排列,又能根据屏幕宽度自适应换行。

基本思路:将这块区域的布局定义为MyFlowLayout作为父布局,并且自定义一个MyFlowLayout类作为父布局类。在java中定义一个LinearLayout类alternationLayout对应标签item文件,获取到标签的数据源后,使用alternationLayout.addview()方法,将标签item作为childView向父布局中动态添加。

自定义ViewGroup的基本步骤:

1.重写onMeasure方法:

先测量子布局,后确定父布局。子布局一个个传入,测量的宽度和高度随之增加,装填完成时,父布局大小随之确定。

换行的逻辑:

该行宽度lineWidth再加一个子控件宽度childWidth,若超过父控件宽度sizeWidth(即1080px)则换行。换行之前,记下这一行的宽度lineWidth,并且判断这行是否是目前最宽的,最宽的要作为父布局宽度width。而对于高度heigth,未换行时,每传入一个都会判断该child是否是最高的,最高的作为lineHeight。(本例每个条目高度一样,而该方法可以复用在子控件高度不同的场景。)

最后一个childView:将最大宽传给width,高度叠加本行后传给height(因为最后一个有可能不用换行,循环中可以看到不换行时是不会刷新height值的)。这两个值会由onLayout调用。

日志

2.重写onLayout方法:

第一步是用集合存放每一行的高度和每一行的子控件集合,绘制的时候要使用。第二部用它们来布局,因为layout方法的四个参数确定的是左上角和右下角的位置。

子控件布局逻辑:左上角的位置,在不换行时,top不变,left按子控件宽度自增,right是left+控件宽。换行时,top位置加一个行高,left归零。

3.绑定视图

alternation_card_item


【知识补充】

`ViewGroup` 是 Android 中一个用于容纳和管理其他 View 的视图类,它继承自 `View` 类。下面是 `ViewGroup` 类中一些常用的方法:

1. `addView(View child)`:向 ViewGroup 中添加一个子视图。

2. `removeView(View view)`:从 ViewGroup 中移除指定的子视图。

3. `getChildAt(int index)`:获取 ViewGroup 中指定位置的子视图。

4. `getChildCount()`:获取 ViewGroup 中子视图的数量。

5. `onLayout(boolean changed, int l, int t, int r, int b)`:为 ViewGroup 中的子视图设置布局参数。

6. `setLayoutParams(ViewGroup.LayoutParams params)`:设置 ViewGroup 的布局参数。

7. `setOrientation(int orientation)`:设置 ViewGroup 的方向,可以是水平或垂直。

8. `generateLayoutParams(AttributeSet attrs)`:根据给定的属性集生成一个布局参数对象。


此外,还有一些方法用于重载视图的绘制过程:


9. `dispatchDraw(Canvas canvas)`:在绘制 ViewGroup 时调用其所有子视图的 `draw()` 方法。

10. `drawChild(Canvas canvas, View child, long drawingTime)`:在绘制 ViewGroup 时调用其某个子视图的 `draw()` 方法。


还有一些其他方法,比如:


11. `requestLayout()`:请求 ViewGroup 重新进行测量和布局。

12. `onMeasure(int widthMeasureSpec, int heightMeasureSpec)`:测量 ViewGroup 及其所有子视图的尺寸。

13. `onInterceptTouchEvent(MotionEvent ev)`:拦截触摸事件,用于在 ViewGroup 内部处理事件。

14. `dispatchTouchEvent(MotionEvent ev)`:分发触摸事件,将其传递给所有子视图进行处理。


以下是一些常用的回调方法:

onMeasure(int widthMeasureSpec, int heightMeasureSpec):测量子视图的尺寸大小。

onLayout(boolean changed, int left, int top, int right, int bottom):对子视图进行布局。

dispatchDraw(Canvas canvas):绘制子视图及其自身的内容。

onInterceptTouchEvent(MotionEvent ev):拦截子视图的触摸事件。

onDetachedFromWindow():当 ViewGroup 从窗口中移除时会被调用,用于清理资源。



自定义ViewGroup实现类似B站历史记录布局的评论 (共 条)

分享到微博请遵守国家法律