第五十四回:BoxDecoration Widget

Flutter教程:BoxDecorationWidget详解
BoxDecorationWidget是Flutter中的修饰类组件,用于给其他组件添加边框、颜色、圆角和阴影效果。它可以设置color、border、borderRadius、shape和boxShadow等属性,常用于创建具有视觉吸引力的UI元素,如按钮。文章提供示例代码并提醒注意边框设置和圆形修饰框的限制。


我们在上一章回中介绍了DrawerHeader Widget相关的内容,本章回中将介绍 BoxDecoration Widget.闲话休提,让我们一起Talk Flutter吧。

概念介绍

我们在这里介绍的BoxDecoration Widget是一种修饰类组件,它不能单独使用,需要赋值给其它组件的decoration属性才有效果,赋值后会在其它组件外层嵌套一个边框,名字中Box来源于此。我们可以修改边框的颜色,形状,线条进而达到装饰的效果。其实,我们在上一章回中创建用户头像时使用过它,只是没有详细介绍而已,本章回中将详细介绍它的使用方法。

使用方法

和其它的Widget一样,BoxDecoration Widget提供了相关的属性来控制自己,下面是常用的属性:

  • color属性:用来控制边框中间的填充颜色;
  • border属性:用来添加边框,可以只添加部分,或者添加全部,可以修改边框的粗细,颜色;
  • borderRadius属性:用来给边框添加圆角;
  • shape属性:用来控制边框的形状,比如圆形或者矩形;
  • boxShadow属性:用来给装饰框添加阴影效果,可以添加多个阴影;

这些属性都是可选属性,我们可以依据项目需求来使用相关的属性,最常用的是修改圆角,比如把该属性用来修饰Button组件,就可以实现圆角按钮。

示例代码

BoxDecoration(
  color: Colors.greenAccent,
  //添加边框,可以只添加部分,或者全添加
  border: Border(
    top: BorderSide(
        color: Colors.red, width: 5, style: BorderStyle.solid),
    bottom: BorderSide(color: Colors.yellow, width: 5),
  ),
  // border: Border.all(
  //   color: Colors.yellow,
  //   width: 3,
  // ),

  //设置圆角边框,角度超过35就变成了圆形
  // borderRadius: BorderRadius.circular(20),
  //上面是所有边框都设置圆角,也可能在某一侧设置圆角边框
  // borderRadius: BorderRadius.only(topRight: Radius.circular(30)),

  //调整box的形状,形状是圆形时不能使用圆角属性,否则报错
  shape: BoxShape.rectangle,
  // shape: BoxShape.circle,

  //给Box添加阴影,可以添加多个阴影
  boxShadow: [
    BoxShadow(
      //阴影偏移距离,第一个是x,第二个是y
      offset: Offset(30, 20),
      color: Colors.purpleAccent,
      //值越小越模糊
      blurRadius: 10,
      //模糊范围
      spreadRadius: 2,
    )
  ],
),

我们在上面的代码中添加了详细的注释,这些注释可以很好地解释一些小的细节。此外,还有一些注意事项需要说明:

  • 给修饰框添加边框时,除非有特殊的需求,否则建议在四个方向上都添加边框;
  • 如果把修饰框设置为圆形,那么不能再给它设置圆角,否则会报错;

把上面的代码赋值给容器类组件(比如Container)的decoration属性就可以看到漂亮的装饰效果。我在这里就不演示程序的运行效果了,建议大家自己动手去实践。

看官们,关于BoxDecoration Widget的内容就介绍到这里,欢迎大家在评论区交流与讨论!

import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class SecondPage extends StatefulWidget { const SecondPage({Key? key}) : super(key: key); @override State<SecondPage> createState() => _SecondPageState(); } class _SecondPageState extends State<SecondPage> { @override Widget build(BuildContext context) { // ️ 页面UI构建入口 return Scaffold( appBar: AppBar( title: const Text("积极日记", textDirection: TextDirection.ltr, textAlign: TextAlign.center, style: TextStyle( color: Colors.black, fontFamily: 'Comic Sans MS', fontSize: 20.0, fontWeight: FontWeight.w500, )), centerTitle: true, backgroundColor: Colors.transparent, elevation: 0, surfaceTintColor: Colors.transparent, // 避免表面色调影响 flexibleSpace: Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/background.jpg'), // 图片路径 fit: BoxFit.cover, // 覆盖整个区域 ), ), ), // 返回按钮实现 leading: IconButton( icon: const Icon(Icons.arrow_back, color: Colors.black), onPressed: () => Navigator.pop(context), ), ), body: Container( width: 430, height: 900, decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/background.jpg'), // 图片路径 fit: BoxFit.cover, // 覆盖整个区域 ), ), child: InputSaverContainer(), ), ); } } class InputSaverContainer extends StatefulWidget { const InputSaverContainer({super.key}); @override _InputSaverContainerState createState() => _InputSaverContainerState(); } class _InputSaverContainerState extends State<InputSaverContainer> { final TextEditingController _controller = TextEditingController(); List<String> _savedTexts = []; // 改为列表存储多个内容 Future<void> _saveInput() async { if (_controller.text.isEmpty) return; final prefs = await SharedPreferences.getInstance(); // 获取已有列表并添加新内容 //final List<String> existingList = prefs.getStringList(_storageKey) ?? []; //existingList.add(_controller.text); _savedTexts.insert(0, _controller.text); // 保存更新后的列表 //await prefs.setStringList(_storageKey, existingList); await prefs.setStringList('saved_items', _savedTexts); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("保存成功!"), duration: Duration(seconds: 1))); _controller.clear(); // 清空输入框 setState(() {}); } Future<void> _loadInputs() async { final prefs = await SharedPreferences.getInstance(); setState(() { _savedTexts = prefs.getStringList('saved_items') ?? []; }); } // 删除指定项 Future<void> _deleteItem(int index) async { final prefs = await SharedPreferences.getInstance(); setState(() { _savedTexts.removeAt(index); prefs.setStringList('saved_items', _savedTexts); }); } @override void initState() { super.initState(); _loadInputs(); } @override Widget build(BuildContext context) { return SizedBox( height: 620, width: 500, child: Container( height: 20, width: 500, padding: const EdgeInsets.all(16), decoration: const BoxDecoration( color: Colors.transparent, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( controller: _controller, maxLines: null, // 关键参数:允许无限多行(自动扩展) minLines: 15, // 初始最小显示行数 keyboardType: TextInputType.multiline, // 启用多行键盘 textInputAction: TextInputAction.newline, // 回车键换行 decoration: const InputDecoration( labelText: null, hintText: '请记录今天做得很好的三件事和值得感恩的三件事 !', /*decoration: InputDecoration( labelText: "输入内容", prefixIcon: Icon(Icons.edit), border: OutlineInputBorder(), filled: true, fillColor: Colors.white, ),*/ ), ), const SizedBox(height: 16), SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: _saveInput, icon: const Icon(Icons.save), label: const Text("保存内容"), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 14), backgroundColor: Colors.black45, foregroundColor: Colors.white, elevation: 0, ), ), ), const SizedBox(height: 20), // 滑动列表区域 Container( height: 390, // 固定高度 padding: const EdgeInsets.all(12), decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/background.jpg'), // 图片路径 fit: BoxFit.cover, // 覆盖整个区域 ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Row(children: [ Icon( Icons.book, color: Colors.grey, ), Text("日记列表:", style: TextStyle(fontSize: 15)), SizedBox(height: 8) ]), Expanded( child: _savedTexts.isEmpty ? const Center(child: Text("暂无保存内容")) : ListView.builder( itemCount: _savedTexts.length, itemBuilder: (context, index) { return ListTile( /*leading: CircleAvatar( child: Text("${index + 1}"), backgroundColor: Colors.transparent, ),*/ title: Text(_savedTexts[index], textDirection: TextDirection.ltr, style: const TextStyle( color: Colors.black54, fontSize: 13.0, fontWeight: FontWeight.w400)), trailing: IconButton( // 添加删除按钮 icon: const Icon(Icons.delete, color: Colors.black), onPressed: () => _deleteItem(index), ), ); }, scrollDirection: Axis.vertical, ), ), ], ), ), ], ), ), ); } }请在这段代码中加入一段代码,实现点击Textfield先检测是否登录,如果没有登陆,弹出弹窗提醒用户登录,如果登录则可以正常使用textfield。
最新发布
11-24
`Widget::Widget` 通常是 C++ 中类的构造函数定义方式,它是 `Widget` 类的构造函数。在使用 Qt 框架开发桌面应用程序时会经常出现这样的构造函数。 ### 代码示例及含义解释 ```cpp Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); } ``` - **函数声明部分**: - `Widget::Widget`:在 C++ 中,类的构造函数名与类名相同,`Widget::` 明确这是 `Widget` 类的构造函数。 - `(QWidget *parent)`:构造函数的参数列表,接受一个指向 `QWidget` 类型对象的指针 `parent`。在 Qt 里,很多窗口部件类的构造函数都会有一个 `parent` 参数,其作用是指定该窗口部件的父对象。当父对象被销毁时,它的所有子对象也会被自动销毁,有助于管理内存和窗口层次结构 [^2]。 - **初始化列表部分**: - `QWidget(parent)`:调用基类 `QWidget` 的构造函数,并把 `parent` 指针传递给它,在初始化 `Widget` 对象时先对其基类部分进行初始化。 - `ui(new Ui::Widget)`:初始化成员变量 `ui`,使用 `new` 运算符动态分配一个 `Ui::Widget` 类型的对象,并将其地址赋值给 `ui`。在 Qt 中,`Ui::Widget` 通常是使用 Qt Designer 设计界面后自动生成的类,包含了界面上各个控件的定义和布局信息 [^2]。 - **构造函数体部分**: - `ui->setupUi(this)`:调用 `ui` 对象的 `setupUi` 方法,并将当前 `Widget` 对象的指针 `this` 作为参数传入。该方法会根据 `Ui::Widget` 类中定义的界面信息,将各个控件添加到当前 `Widget` 上,完成界面的初始化工作 [^2]。 ### 使用方法 以下是一个简单的使用示例: ```cpp #include <QApplication> #include <QWidget> #include "ui_widget.h" class Widget : public QWidget { public: Widget(QWidget *parent = nullptr) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); } ~Widget() { delete ui; } private: Ui::Widget *ui; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); } ``` 在上述示例中,首先定义了一个 `Widget` 类,在其构造函数中调用了 `ui->setupUi(this)` 完成界面初始化。在 `main` 函数中创建了 `Widget` 对象并显示出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

talk_8

真诚赞赏,手有余香

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值