Flutter-->自定义容器Widget(类比Android自定义ViewGroup)

news2024/9/22 13:31:15

上一篇Flutter–>自定义Widget(类比Android自定义View)

介绍了如何自定义一个Widget, 这一篇文章介绍如果自定义容器Widget, 相当于Android中的ViewGroup

Android自定义ViewGroup

先来简单介绍一下Android中自定义的ViewGroup:

class CustomViewGroup(context: Context, attrs: AttributeSet?) : ViewGroup(context, attrs) {
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        //进行测量操作, 确定自身的大小, 已经测量child的大小
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        //进行布局操作, 确定子view的位置
    }

    override fun generateDefaultLayoutParams(): ViewGroup.LayoutParams {
        return LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT
        )
    }

    class LayoutParams(width: Int, height: Int) : ViewGroup.LayoutParams(width, height) {
        //自定义的布局参数
    }
}
  • onMeasure方法: 进行测量操作, 确定自身的大小, 已经测量child的大小
  • onLayout方法: 进行布局操作, 确定子view的位置
  • LayoutParams child的布局参数, 在parent中读取生效

Flutter自定义容器Widget

那么在Flutter中, 怎么自定义容器Widget呢?

自定义只有一个child的容器如下:

class CustomContainerWidget extends SingleChildRenderObjectWidget {
  const CustomContainerWidget({super.key, super.child});

  
  RenderObject createRenderObject(BuildContext context) =>
      CustomContainerRenderObject();
}

/// [RenderObjectWithChildMixin]
class CustomContainerRenderObject extends RenderBox
    with RenderObjectWithChildMixin<RenderBox>, RenderProxyBoxMixin<RenderBox> {
    
  
  void setupParentData(covariant RenderObject child) {
    if (child.parentData is! CustomContainerParentData) {
      child.parentData = CustomContainerParentData();
    }
  }

  
  void performLayout() {
    if (child != null) {
      final parentData = child!.parentData as CustomContainerParentData;
      parentData.offset = const Offset(100, 100); // 确定子元素的位置
    }
  }

  
  void paint(PaintingContext context, Offset offset) {
    final RenderBox? child = this.child;
    if (child == null) {
      return;
    }
    context.paintChild(child, offset);
  }

  
  bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {
    return child?.hitTest(result, position: position) ?? false;
  }
}

Flutter中, 有可能代码都是通过mixin混入的方式实现的, 这一点非常方便.

  • setupParentData方法, 用来设置child的参数, 提供给容器使用的.
  • performLayout方法, 用来确定自身大小child大小, 还有child位置
  • paint方法, 用来自绘和绘制child
  • hitTestChildren方法, 用来实现child的事件支持

自定义一组child的容器如下:

class CustomListContainerWidget extends MultiChildRenderObjectWidget {
  const CustomListContainerWidget({super.key, super.children});

  
  RenderObject createRenderObject(BuildContext context) =>
      CustomListContainerRenderObject();
}

/// [ContainerRenderObjectMixin]
class CustomListContainerRenderObject extends RenderBox
    with
        ContainerRenderObjectMixin<RenderBox, CustomContainerParentData>,
        RenderBoxContainerDefaultsMixin<RenderBox, CustomContainerParentData> {
  
  void setupParentData(covariant RenderObject child) {
    if (child.parentData is! CustomContainerParentData) {
      child.parentData = CustomContainerParentData();
    }
  }

  
  void performLayout() {
    visitChildren((child) {
      final parentData = child.parentData as CustomContainerParentData;
      parentData.offset = const Offset(100, 100); // 确定子元素的位置
    });
  }

  
  void paint(PaintingContext context, Offset offset) {
    defaultPaint(context, offset);
  }

  
  bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {
    return defaultHitTestChildren(result, position: position);
  }
}

一组child的自定义容器, 核心方法和自定义一个child是一样的, 只不会每个方法都要处理一组child.

以上都是BoxConstraints约束模型的自定义, SliverConstraints约束模型, 比较复杂, 之后再谈…

/// [ParentDataWidget]
class CustomContainerParentData extends ContainerBoxParentData<RenderBox> {}

Flutter中有一个Widget专门用来配置ParentData 它就是ParentDataWidget.

所以一般都是自定义一个ParentDataWidget用来传递ParentData:

class CustomContainerParentDataWidget
    extends ParentDataWidget<CustomContainerParentData> {
  const CustomContainerParentDataWidget({super.key, required super.child});

  
  void applyParentData(RenderObject renderObject) {
    if (renderObject.parentData is! CustomContainerParentData) {
      renderObject.parentData = CustomContainerParentData();
    }
  }

  
  Type get debugTypicalAncestorWidgetClass => CustomContainerParentDataWidget;
}

总结

AndroidFlutter
测量入口View.onMeasureRenderObject.performLayout
child位置View.layoutBoxParentData.offset
child参数LayoutParamsParentData
触发重新绘制View.invalidateRenderObject.markNeedsPaint
触发重新布局View.requestLayoutRenderObject.markNeedsLayout

源码地址


群内有各(pian)种(ni)各(jin)样(qun)的大佬,等你来撩.

联系作者

点此QQ对话 该死的空格 点此快速加群
在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2086217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

树上dp+分组背包类问题

今天也是无意间看到了一个树上dp分组背包类的问题&#xff0c;有些难度的&#xff0c;不好想的嘞&#xff0c;终究还是一个蒟蒻罢了&#xff0c;唔无捂误 话不多说直接看题 P1273 有线电视网 在说明这道题之前&#xff0c;还有一个要提醒的地方就是&#xff0c;树上dp&#…

在 DataOps 体系建设中,主动元数据是何角色?

首先&#xff0c;主动元数据是相对静态元数据而言&#xff0c;它是一种动态、智能化的元数据管理技术&#xff0c;能够将传统静态元数据的被动等待变为实时在线、主动触发&#xff0c;推动数据探查、开发、测试、部署、运维和监控等数据治理工作高效运转&#xff0c;为数据的治…

springWeb介绍、以及SpringWeb的搭建

ssm框架 早期 ssm springstrtuts2mybatis 现在 ssm springspringwebmybatis springweb运行流程 1、SpringWeb概述 SpringWeb是spring框架中的一个模块&#xff0c;基于Servlet API构建的web框架&#xff0c;springweb是Spring为web层开发提供的一套完备的解决方案。在we…

Java毕业设计 基于SSM校园心理咨询服务平台

Java毕业设计 基于SSM校园心理咨询服务平台 SSM 校园心理咨询服务平台 功能介绍 学生: 注册 登录 首页 心理测试 心理文章 心理导师 在线交流 关于我们 搜索 学生中心 我的咨询问题 我的测试结果 我的预约 我的发言 我的收藏 账户信息 教师&#xff1a;登录 发布文…

Linux——nginx 负载均衡

常规的web服务器一般提供对于静态资源的访问&#xff0c;比如说&#xff1a;图片、web样式 网站提供的大部分交互功能都需要web编程语言的支持&#xff0c;而web服务对于程序的调用&#xff0c;不管编译型语言还是解释型语言&#xff0c;web服务同将对于应用程序的调用递交给通…

音频变声怎么弄?(实测好用)快来试试这6个AI变声工具

音频变声怎么弄&#xff1f;随着短视频平台和社交平台的发展&#xff0c;很多小伙伴们会自己拍摄视频分享到平台上&#xff0c;还有一些视频创作者会制作有趣的视频吸引观众。而视频配音就是锦上添花&#xff0c;很多人觉得自己的声音不好听&#xff0c;想要实现录音音频变声&a…

结合ollama gemma2:2b大模型来实现数据分析系统的智能交互

在最近的人员风险行为分析系统开发过程中&#xff0c;需要解决一个问题&#xff1a;在缺乏GPU资源的情况下&#xff0c;如何提升智能交互能力。​我们探索并研究了集成gemma2:2b模型的可行性&#xff0c;这一举措旨在在有限的硬件条件下&#xff0c;为我们的系统注入更高级别的…

如何理解进程

一、进程的概念 进程&#xff1a;顾名思义&#xff0c;就是一个完整执行程序的过程。没错&#xff0c;就是这么简单&#xff0c;但是在程序执行的过程之中&#xff0c;系统会为这个执行的程序分配内存资源&#xff0c;这些过程也包含在进程当中。 进程是动态的&#xff0c;是程…

css-50 Projects in 50 Days(2)

html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>步骤条</title><link rel"style…

基于混沌麻雀搜索算法的光伏MPPT控制MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 模型简介 此模型主要研究光伏系统MPPT控制&#xff0c;通过将麻雀搜索算法引入至MPPT控制策略中&#xff0c;在模型中通过改变光照强度&#xff0c;来验证算法引入的有效性。模型中包含麻雀搜索算法MPPT与混…

单链表——随机链表的复制

深拷贝&#xff0c;就是将原链表彻底的拷贝&#xff0c;当我们观察这个链表时我们会发现&#xff0c;val与next都比较好拷贝&#xff0c;难点就是在random的拷贝&#xff0c;因为我们需要知被拷贝的节点的random指向的是哪个&#xff0c;所以我们很容易想到的方法就是从头遍历链…

从开题到答辩:ChatGPT超全提示词分享!(上)【建议收藏】

在浩瀚的知识领域中&#xff0c;提问的艺术是探索真理的钥匙。在这个信息爆炸的时代&#xff0c;深入探索知识的海洋&#xff0c;不仅需要热情和毅力&#xff0c;更需要正确的方法和工具。学术研究是一个复杂而严谨的过程&#xff0c;涉及从选题、文献综述到研究设计、数据收集…

网络层,数据链路层和应用层

1.网络层 网络层最主要的协议就是IP协议。 下图是IP协议的格式&#xff1a; 1.1 IP协议解析 &#xff08;1&#xff09;4位版本&#xff1a; 有两种&#xff1a;IPV4&#xff08;IP地址4个字节大小&#xff09;和IPV6&#xff08;IP地址16个字节大小&#xff09; &#xf…

推荐系统实战(八)-冷启动(上)

一、冷启动基本描述 &#xff08;一&#xff09;冷启动与新用户新物料 冷启动针对的是对缺少消费记录的新用户、新物料的推荐。 新用户不仅包含初次使用应用的用户&#xff0c;还包含安装很久但是处于低活跃状态的用户。 &#xff08;二&#xff09;部分经典算法无法支持新…

2024年【安全员-C证】新版试题及安全员-C证复审模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【安全员-C证】新版试题及安全员-C证复审模拟考试&#xff0c;包含安全员-C证新版试题答案和解析及安全员-C证复审模拟考试练习。安全生产模拟考试一点通结合国家安全员-C证考试最新大纲及安全员-C证考试真题汇…

二叉搜索树进阶之红黑树

前言&#xff1a; 在上文我们已经学习了AVL树的相关知识以及涉及的四种旋转的内容&#xff0c;但是AVL树追求平衡导致旋转操作过多&#xff0c;一些情况下影响性能&#xff0c;由此我们就来了解一下二叉搜索树的另外一个分支&#xff0c;红黑树。 &#xff08;倘若对旋转知识…

詹娜奥尔特加看到自己青少年时期露骨AI照片后删除了推特:“这太恶心了”

詹娜奥尔特加看到自己青少年时期露骨AI照片后删除了推特&#xff1a;“这太恶心了” 2024-08-25 23:07 发布于&#xff1a;河北省 21 岁的奥尔特加承认她仍在学习如何保护自己&#xff0c;一种有帮助的方法是“尽可能避免使用手机”。 这位女演员表示&#xff0c;看到“剪…

算法: 双指针

题目&#xff1a;环形链表 题目讲解&#xff1a; 判断环 要判断链表是否有环&#xff0c;可以使用快慢指针的方法。快指针每次走两步&#xff0c;慢指针每次走一步。如果链表有环&#xff0c;快慢指针最终会相遇&#xff1b;如果没有环&#xff0c;快指针会先到达链表末尾。 …

该部署公钥无权限拉代码

从阿里云云效的代码库中执行git pull时报错如下&#xff1a; git pull该部署公钥无权限拉代码 fatal: Could not read from remote repository.Please make sure you have the correct access rights and the repository exists.原因是该代码库在云效上未启用密钥&#xff0c;…

【Material-UI】Select 组件中的 `Auto width`、`Small Size` 和 `Other Props` 详解

文章目录 一、Select 组件概述1. 组件介绍2. Select 组件的基本结构 二、Auto width 属性详解1. Auto width 的作用2. Auto width 属性的基本用法3. Auto width 的实际应用场景 三、Small Size 属性详解1. Small Size 的作用2. Small Size 属性的基本用法3. Small Size 的实际应…