Text为什么可以从父节点Material获取textStyle

为什么 下面代码Text 能够从 Material获取textStyle

less 复制代码
Material(
  textStyle: TextStyle(fontSize: 31, color: Colors.red),
  child: Text('materical 中的style'),
),

1、 先看下Text 获取 textStyle:

scala 复制代码
class Text extends StatelessWidget { 
	
	Widget build(BuildContext context) {
    	final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context); //
  		TextStyle? effectiveTextStyle = style;

		 if (style == null || style!.inherit) {
		      effectiveTextStyle = defaultTextStyle.style.merge(style);
		    }
   	}
}

这里使用 DefaultTextStyle

DefaultTextStyle.of(context);实现:

DefaultTextStyle 是一个 InheritedWidget

scala 复制代码
class DefaultTextStyle extends InheritedTheme {
   static DefaultTextStyle of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<DefaultTextStyle>() ?? const DefaultTextStyle.fallback();
  }


}

InheritedTheme 就是一个 InheritedWidget:

abstract class InheritedTheme extends InheritedWidget

context.dependOnInheritedWidgetOfExactType() 方法的实现为 Element中,因为 context就是一个 Element,dependOnInheritedWidgetOfExactType实现如下:

scala 复制代码
abstract class Element extends DiagnosticableTree implements BuildContext {


  @override
  T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect}) {
    assert(_debugCheckStateIsActiveForAncestorLookup());
    final InheritedElement? ancestor = _inheritedWidgets == null ? null : _inheritedWidgets![T];
    if (ancestor != null) {
      return dependOnInheritedElement(ancestor, aspect: aspect) as T;
    }
    _hadUnsatisfiedDependencies = true;
    return null;
  }



}

2、在看下Material

Material

scala 复制代码
class Material extends StatefulWidget {

  State<Material> createState() => _MaterialState();
}


class _MaterialState extends State<Material> with TickerProviderStateMixin {

		Widget build(BuildContext context) {
		    final ThemeData theme = Theme.of(context);
		   
		    ///...

		    Widget? contents = widget.child;
		    if (contents != null) {
		    	//
		      contents = AnimatedDefaultTextStyle(
		        style: widget.textStyle ?? Theme.of(context).textTheme.bodyText2!,
		        duration: widget.animationDuration,
		        child: contents,
		      );
		    }

		    //....
 			if (widget.type == MaterialType.canvas && widget.shape == null && widget.borderRadius == null) {
	      		return AnimatedPhysicalModel(
	        	//...
	        		child: contents,
	      		);
    		}

		    final ShapeBorder shape = _getShape();

		    if (widget.type == MaterialType.transparency) {
		      return _transparentInterior(
		  			////..
		        contents: contents,
		      );
		    }

		    return _MaterialInterior(
			       //...
		      child: contents,
		    );

	}
}

AnimatedDefaultTextStyle

scala 复制代码
class AnimatedDefaultTextStyle extends ImplicitlyAnimatedWidget  { 



	AnimatedWidgetBaseState<AnimatedDefaultTextStyle> createState() => _AnimatedDefaultTextStyleState();

}


abstract class ImplicitlyAnimatedWidget extends StatefulWidget

class _AnimatedDefaultTextStyleState extends AnimatedWidgetBaseState<AnimatedDefaultTextStyle> {

  @override
  Widget build(BuildContext context) {
    return DefaultTextStyle(
      style: _style!.evaluate(animation),
      
      child: widget.child,
    );
  }
}

DefaultTextStyle

Material 是由 一个DefaultTextStyle 包裹了child子widget的 小组件。

Material( textStyle: TextStyle(fontSize: 31, color: Colors.red), child: Text('materical 中的style'), ),

这样在Text的构建时,就可以通过 DefaultTextStyle.of(context);拿到父节点中的style数据了

3、扩展TextButton的child获取textStyle

可以扩展一下,Text也是可以获取TextButton的 style,下面原理也是相同的:

less 复制代码
    TextButton(
      onPressed: () {},
      style: TextButton.styleFrom(
          textStyle: TextStyle(color: Colors.red, fontSize: 30)),
      child:
          Text('TextButton---text style'), //为什么能够获取到style中的text style
    )
    
    
    TextButton(
  onPressed: () {},
  style: TextButton.styleFrom(
      textStyle: TextStyle(color: Colors.red, fontSize: 30)),
  child: Column(
    children: [
      Text('123text style--随便套多少个子widget,都能够从父节点获取到style'),
      Text('123---所有子Text都能获取父节点相同style值,并且不论套了多少层')
    ],
  )),

TextButton源码部分实现为:

scala 复制代码
  class TextButton extends ButtonStyleButton 



abstract class ButtonStyleButton extends StatefulWidget {
  State<ButtonStyleButton> createState() => _ButtonStyleState();
}



class _ButtonStyleState extends State<ButtonStyleButton> with TickerProviderStateMixin {

  final Widget result = ConstrainedBox(
      constraints: effectiveConstraints,
      child: Material(
        //..
        textStyle: resolvedTextStyle?.copyWith(color: resolvedForegroundColor),
        //...
    );
 
    return Semantics(
    //...
      child: _InputPadding(
    //....
        child: result,
      ),
    );
  }

}

总结:

在Flutter中,Text小部件是会从其上层的DefaultTextStyle中继承样式的,而Material小部件本身就包含一个DefaultTextStyle。这就是为什么Text能够获取到Material的样式信息的原因。

具体来说,DefaultTextStyle是一个InheritedWidget,它在widget树中传递默认文本样式。当Text小部件没有显式指定样式时,它会查找其父级上的DefaultTextStyle,并应用那里设置的默认样式。

在文章开头的例子中,Material小部件设置了textStyle,它实际上是在DefaultTextStyle中设置的默认样式。因此,Text小部件能够通过继承来获取Material的默认文本样式。

这是Flutter中一种方便的方式,允许您在widget树中的某个位置设置默认样式,而不必手动为每个Text小部件设置样式。

从这个DefaultTextStyle 我们又重新看到了 InheritedWidget 的作用。

相关推荐
小蜜蜂嗡嗡1 小时前
flutter更改第三方库pub get的缓存目录;更改.gradle文件夹存放目录
flutter
某非著名程序员2 小时前
Flutter 新手绕不过的坑:ListView 为啥顶部老有空白?
flutter·客户端
恋猫de小郭3 小时前
Google I/O Extended :2025 Flutter 的现状与未来
android·前端·flutter
aiprtem1 天前
基于Flutter的智能设备web前端设计
物联网·flutter·web
九丝城主1 天前
2025使用VM虚拟机安装配置Macos苹果系统下Flutter开发环境保姆级教程--上篇
服务器·flutter·macos·vmware
瓜子三百克1 天前
七、性能优化
flutter·性能优化
恋猫de小郭2 天前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
小蜜蜂嗡嗡2 天前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
瓜子三百克2 天前
十、高级概念
flutter