2024-08-24



import 'package:json_annotation/json_annotation.dart';
import 'package:flutter/material.dart';
 
// 示例模型,使用json_serializable自动生成序列化代码
part 'example_model.g.dart';
 
@JsonSerializable()
class ExampleModel {
  String name;
  int age;
 
  ExampleModel(this.name, this.age);
 
  // json_serializable生成的序列化方法
  factory ExampleModel.fromJson(Map<String, dynamic> json) => _$ExampleModelFromJson(json);
  Map<String, dynamic> toJson() => _$ExampleModelToJson(this);
}
 
// 页面跳转时使用的路由
final routeName = '/example';
 
// 使用InheritedWidget在页面间传递数据
class ExampleModelProvider extends InheritedWidget {
  final ExampleModel data;
 
  ExampleModelProvider({Key key, @required this.data, Widget child})
      : super(key: key, child: child);
 
  @override
  bool updateShouldNotify(ExampleModelProvider oldWidget) => data != oldWidget.data;
 
  static ExampleModel of(BuildContext context) {
    final ExampleModelProvider provider = context.dependOnInheritedWidgetOfExactType<ExampleModelProvider>();
    return provider.data;
  }
}
 
// 跳转到新页面并传递数据
Navigator.push(
  context,
  MaterialPageRoute(
    settings: RouteSettings(name: routeName),
    builder: (context) => ExamplePage(exampleModel: exampleModel),
  ),
);
 
// 接收数据的页面
class ExamplePage extends StatelessWidget {
  final ExampleModel exampleModel;
 
  ExamplePage({Key key, @required this.exampleModel}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return ExampleModelProvider(
      data: exampleModel,
      child: Scaffold(
        appBar: AppBar(
          title: Text('Example Page'),
        ),
        body: Center(
          child: Text('Received data: ${ExampleModelProvider.of(context).name}'),
        ),
      ),
    );
  }
}

在这个代码示例中,我们首先定义了一个名为ExampleModel的模型类,并使用json_serializable包为其生成了序列化方法。然后,我们创建了一个名为ExampleModelProviderInheritedWidget,用于在页面间传递数据。在页面跳转时,我们使用Navigator将数据通过新页面的构造函数传递,并在新页面中通过ExampleModelProvider获取和显示数据。

2024-08-24

在Flutter中,Card 是一个非常常用的小部件,它可以创建一个有着圆角和阴影的框体效果。Card 小部件通常用于包装并呈现相关的数据或操作,例如包含图片、列表、图表或者其他内容的用户卡片。

以下是一个简单的Card小部件的示例代码:




import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Card Example'),
        ),
        body: Center(
          child: Card(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                ListTile(
                  leading: Icon(Icons.album),
                  title: Text('The Enchanted Nightingale'),
                  subtitle: Text('Maria De Filippi'),
                ),
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Text('The Enchanted Nightingale is a 2019 Italian language soundtrack album.'),
                    SizedBox(height: 8.0),
                    Text('By Maria De Filippi'),
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

在这个例子中,我们创建了一个Card小部件,它包含了一个列表题和两行文本。列表题用于展示专辑的标题和艺术家名称。接下来的两行文本提供了更详细的描述和艺术家的其他信息。Card 小部件为这些信息提供了一个整洁的包装,使得应用看起来更加整洁并增加了用户体验。

2024-08-24



import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
 
class VideoPlayerScreen extends StatefulWidget {
  final VideoPlayerController controller;
 
  VideoPlayerScreen(this.controller);
 
  @override
  _VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}
 
class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  bool _isFullScreen = false;
  VideoPlayerController get _controller => widget.controller;
 
  @override
  void initState() {
    super.initState();
    _controller.initialize().then((_) => setState(() {}));
    _controller.setLooping(true);
    _controller.setVolume(1.0);
    _controller.play();
  }
 
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
 
  // 全屏切换逻辑
  void _toggleFullScreen() {
    setState(() {
      _isFullScreen = !_isFullScreen;
    });
  }
 
  // 全屏视图
  Widget _buildFullScreenVideo() {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Center(
        child: VideoPlayer(_controller),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _toggleFullScreen,
        child: Icon(Icons.fullscreen_exit),
      ),
    );
  }
 
  // 普通视图
  Widget _buildNormalVideo() {
    return Scaffold(
      appBar: AppBar(
        title: Text('视频播放'),
      ),
      body: Center(
        child: VideoPlayer(_controller),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _toggleFullScreen,
        child: Icon(Icons.fullscreen),
      ),
    );
  }
 
  @override
  Widget build(BuildContext context) {
    return _isFullScreen ? _buildFullScreenVideo() : _buildNormalVideo();
  }
}

这段代码实现了一个视频播放器屏幕,它可以在全屏和非全屏模式之间切换。视频播放器控件是使用VideoPlayer插件创建的,而全屏切换是通过setState来更新当前是否是全屏状态的变量来控制的。这个例子展示了如何在Flutter中管理状态和构建响应式用户界面。

2024-08-24



import 'package:flutter/material.dart';
import 'package:flutter_picker/flutter_picker.dart';
 
class PickerExample extends StatefulWidget {
  @override
  _PickerExampleState createState() => _PickerExampleState();
}
 
class _PickerExampleState extends State<PickerExample> {
  // 选择器的数据
  List<String> fruits = ['Apple', 'Banana', 'Cherry'];
  List<String> colors = ['Red', 'Yellow', 'Purple'];
 
  // 选择器当前选中的值
  String selectedFruit;
  String selectedColor;
 
  // 选择器的显示与隐藏状态
  bool isFruitPickerShown = false;
  bool isColorPickerShown = false;
 
  void showPicker(List<String> items, String currentValue, bool isShown, ValueChanged<String> onChanged) {
    Picker(
      adapter: PickerAdapter(pickerData: items),
      selecteds: items.indexOf(currentValue),
      onConfirm: (Picker picker, List<int> selecteds) {
        onChanged(items[selecteds[0]]);
        Navigator.of(context).pop(); // 关闭选择器
      },
    ).showModal(context);
  }
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Picker Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Selected Fruit: $selectedFruit'),
            SizedBox(height: 20.0),
            Text('Selected Color: $selectedColor'),
            SizedBox(height: 20.0),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                FlatButton(
                  child: Text('Select Fruit'),
                  onPressed: () {
                    showPicker(fruits, selectedFruit ?? fruits.first, isFruitPickerShown, (newValue) {
                      setState(() {
                        selectedFruit = newValue;
                      });
                    });
                  },
                ),
                SizedBox(width: 20.0),
                FlatButton(
                  child: Text('Select Color'),
                  onPressed: () {
                    showPicker(colors, selectedColor ?? colors.first, isColorPickerShown, (newValue) {
                      setState(() {
                        selectedColor = newValue;
                      });
                    });
                  },
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

这段代码使用了\`f

2024-08-24

报错原因可能是因为flutter doctor --android-licenses命令需要在终端中执行,而不是在Android Studio的终端中执行,或者是因为Android SDK的环境变量没有配置正确。

解决方法:

  1. 确保你是在终端中运行这个命令,而不是在Android Studio的内置终端中。你可以尝试打开系统的终端(在Windows上是命令提示符或PowerShell,在macOS或Linux上是Terminal),然后再次运行该命令。
  2. 确保你的Android SDK的路径已经添加到了系统的环境变量中。你可以通过以下步骤来检查和配置环境变量:

    • 打开终端。
    • 输入echo $PATH来查看环境变量。
    • 如果你的Android SDK的路径不在列出的路径中,你需要将其添加到环境变量中。你可以通过修改~/.bash_profile~/.bashrc~/.zshrc或者~/.profile文件来添加路径(取决于你使用的shell)。

    例如,如果你的Android SDK位于~/Library/Android/sdk,则可以添加以下行:

    
    
    
    export PATH=$PATH:~/Library/Android/sdk/tools:~/Library/Android/sdk/platform-tools

    保存文件后,你需要运行source ~/.bash_profile(或相应的文件名)来使更改生效。

  3. 配置完成后,重新打开终端,然后再次运行flutter doctor --android-licenses

如果以上步骤仍然无法解决问题,请提供更详细的错误信息,以便进一步诊断问题。

2024-08-24

在Flutter项目实战中,我们通常需要配置一些环境变量来满足项目需求。以下是一个配置环境变量的示例代码:




// 引入flutter的环境配置文件
import 'package:flutter/foundation.dart';
 
// 定义一个类来管理项目的环境变量
class Env {
  // 定义一个静态变量来标记当前的环境
  static const String env = String.fromEnvironment('ENV', defaultValue: 'dev');
 
  // 根据环境变量获取不同的API地址
  static String get apiUrl {
    switch (env) {
      case 'dev':
        return 'https://dev.example.com';
      case 'prod':
        return 'https://prod.example.com';
      default:
        return 'https://dev.example.com';
    }
  }
}
 
void main() {
  // 打印当前环境的API地址
  debugPrint('当前环境API地址: ${Env.apiUrl}');
}

在这个示例中,我们定义了一个名为Env的类,它有一个静态变量env来表示当前的环境(如dev表示开发环境,prod表示生产环境)。我们还定义了一个静态方法get apiUrl,它根据当前环境变量返回对应的API地址。

在实际开发中,你可以根据项目的需要配置不同的环境变量,并在项目中使用这些变量。例如,你可以配置数据库的地址、API服务器的地址、是否启用Debug模式等。通过这种方式,你可以轻松切换不同的开发环境,提高开发效率。

2024-08-24

在Flutter中,Scaffold是一个功能强大且灵活的小部件,它为构建UI提供了许多预制的布局模式和交互式控件。以下是一个简单的Scaffold使用示例:




import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}
 
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Scaffold 示例'),
      ),
      body: Center(
        child: Text('Hello, World!'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: Icon(Icons.add),
      ),
    );
  }
}

这个例子展示了如何创建一个带有AppBarbodyfloatingActionButton的基本ScaffoldAppBar是顶部的一个工具栏,可以用来显示标题、操作按钮等。body是页面的主要内容区域,这里我们使用了Center小部件来居中显示一个文本。floatingActionButton是在内容上方浮动的按钮,用于触发一些主要的操作。

Scaffold提供了许多其他的属性,如drawer(用于侧边栏导航)、bottomNavigationBar(用于底部导航)等,使得它成为构建复杂界面的理想选择。

2024-08-24



import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
 
// 定义数据库版本号
const int _databaseVersion = 1;
// 定义数据库名称
const String _databaseName = 'my_database.db';
 
// 初始化数据库
Future<Database> initializeDatabase() async {
  // 获取数据库路径
  final databasePath = await getDatabasesPath();
  final path = join(databasePath, _databaseName);
 
  // 打开或创建数据库
  return await openDatabase(path, version: _databaseVersion, onCreate: (database, version) {
    // 创建表
    return database.execute('''
      CREATE TABLE $tableName (
        $columnId INTEGER PRIMARY KEY AUTOINCREMENT, 
        $columnName TEXT, 
        $columnAge INTEGER
      )
    ''');
  });
}
 
// 使用示例
void main() async {
  // 初始化数据库
  final Database db = await initializeDatabase();
  
  // 插入数据
  await db.insert(tableName, <String, dynamic>{
    columnName: 'John Doe',
    columnAge: 30,
  });
  
  // 查询数据
  final List<Map<String, dynamic>> maps = await db.query(tableName);
  
  // 输出结果
  print(maps);
  
  // 关闭数据库
  db.close();
}

这个代码示例展示了如何在Flutter应用中使用sqflite包来管理数据库的创建和升级。首先,我们定义了数据库的版本号和名称。然后,我们使用异步函数获取数据库路径并打开或创建数据库,在创建时定义了数据表的结构。最后,我们演示了如何插入、查询数据库中的数据,并在完成操作后关闭数据库。

2024-08-24



import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('智能电视操作系统更新'),
        ),
        body: Center(
          child: Text('LG 正在使用 Flutter 加速 webOS 智能电视操作系统的开发'),
        ),
      ),
    );
  }
}

这段代码展示了如何使用Flutter创建一个简单的应用,其中包含一个AppBar和一个居中显示的Text控件。这个应用可以被视为是智能电视操作系统更新的一个小示例,展示了Flutter在提升用户体验方面的潜力。

2024-08-23

flutter_native_splash 是一个Flutter插件,用于在iOS和Android应用中设置原生启动屏幕。

如何使用

  1. flutter_native_splash 添加到你的 pubspec.yaml 文件的依赖中。



dependencies:
  flutter:
    sdk: flutter
  flutter_native_splash: ^1.0.0
  1. 运行 flutter pub get 来安装新的依赖。
  2. 对于iOS,在 ios/Runner/Info.plist 中设置启动屏幕。



# 在ios/Runner/Info.plist中添加以下内容
<key>UILaunchStoryboardName</key>
<string>Splash Screen</string>
  1. 对于Android,在 android/app/src/main/java/<YourAppFolder>/MainActivity.java 中设置启动屏幕。



// 在MainActivity.java中添加以下内容
public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);
    // 设置启动屏幕
  }
}
  1. 使用 flutter_native_splash 生成所需的图片和XML文件。



flutter pub run flutter_native_splash:create
  1. 更新 android/app/build.gradle 以使用新的启动屏幕。



// 在android/app/build.gradle中添加以下内容
apply plugin: 'com.android.application'
apply from: '../flutter_native_splash.gradle'
  1. 更新 android/app/src/main/AndroidManifest.xml 以使用新的启动屏幕。



<!-- 在AndroidManifest.xml中添加以下内容 -->
<meta-data
    android:name="com.transistorsoft.flutter.backgroundfetch.ACTION_START"
    android:value="host.flutter.splashscreensample.ACTION_START" />
  1. 运行你的应用,确保启动屏幕按预期显示。

注意

  • 确保在使用 flutter_native_splash 之前已经正确安装了Flutter开发环境,并且你的项目可以成功运行。
  • 对于iOS,你可能还需要在Xcode中进一步设置Storyboard或者使用Launch Screen文件。
  • 对于Android,确保你的项目已经设置了正确的启动Activity。
  • 在实际使用时,请根据你的项目具体情况调整上述步骤。