package_flutter_env 0.0.10+1
package_flutter_env: ^0.0.10+1 copied to clipboard
Using MIAppBarWidget to create a custom app bar.
Custom script for generating environment-specific code for different platforms #
Features #
The flutter_env.dart file appears to be a custom script for generating environment-specific code for different platforms (Dart, Objective-C, and Gradle for Android). It reads from an environment file (.env by default), and generates code based on the key-value pairs in the environment file.
Here's a basic usage guide:
- Create an environment file: Create a .env file in your project root (or specify a different file using the envfile argument). This file should contain key-value pairs, one per line, like this:
API_KEY=123456
BASE_URL=https://api.example.com
2.Run the script: You can run the DotENV class with the command-line arguments. For example:
void main(List<String> args) {
DotENV(args);
}
You can pass arguments to specify the platform (platform), the environment file (envfile), and the directory name (dirname). If not specified, it will use default values.
3.Generated code: The script will generate a Dart file (lib/env.dart by default) with a class ENV that contains static string properties for each key-value pair in the environment file. For example:
class ENV {
static String API_KEY = "123456";
static String BASE_URL = "https://api.example.com";
}
You can then import this file in your Flutter code and access the environment variables like this: ENV.API_KEY.
Please note that this is a basic guide and the actual usage may vary depending on your project setup and requirements. Also, remember to exclude your environment files from version control to avoid committing sensitive data.
Unit Test Command #
At the root of the project, run the following command:
flutter test test/dotenv_test.dart
Generate the env.dart file #
At the root of the example project, run the following command:
like: /Users/danli/Desktop/2024/packages/package_flutter_env/example
Because test is the development environment, the generated file is in the lib folder.
flutter test test/env_test.dart
import os
native_extensions = (".c", ".cpp", ".cc", ".cxx", ".h", ".hpp")
build_files = ("CMakeLists.txt", "Android.mk")
def has_native_code(root_dir):
native_files = []
for root, dirs, files in os.walk(root_dir):
for file in files:
if file.endswith(native_extensions) or file in build_files:
native_files.append(os.path.join(root, file))
return native_files
if __name__ == "__main__":
project_root = os.getcwd()
android_dir = os.path.join(project_root, "android")
plugins_dir = os.path.join(project_root, "plugins")
results = []
if os.path.exists(android_dir):
results.extend(has_native_code(android_dir))
if os.path.exists(plugins_dir):
results.extend(has_native_code(plugins_dir))
if results:
print("⚠️ 检测到以下原生代码/构建文件:")
for f in results:
print(" -", f)
print("\n👉 升级 NDK 可能会影响这些代码或依赖的插件,请重点测试。")
else:
print("✅ 未检测到原生代码文件,NDK 升级影响较小。")
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Row Bottom Dialog',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
// Top spacing (20px)
SizedBox(height: 20),
// The Row at top (30px height)
Container(
height: 30,
width: double.infinity,
color: Colors.blue.withOpacity(0.3),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Top Row (30px height)'),
SizedBox(width: 20),
ElevatedButton(
onPressed: () => _showRowBottomDialog(context),
style: ElevatedButton.styleFrom(
minimumSize: Size(80, 25),
padding: EdgeInsets.symmetric(horizontal: 8),
),
child: Text('Show Dialog', style: TextStyle(fontSize: 12)),
),
],
),
),
// Rest of the screen
Expanded(
child: Container(
color: Colors.grey.withOpacity(0.1),
child: Center(
child: Text('Rest of the screen content'),
),
),
),
],
),
);
}
void _showRowBottomDialog(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
final rowBottomPosition = 20 + 30; // topSpacing + rowHeight = 50px
final dialogEndPosition = screenHeight - 30; // screen bottom - 30px
showGeneralDialog(
context: context,
barrierDismissible: true,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: Colors.black54,
transitionDuration: Duration(milliseconds: 400),
pageBuilder: (BuildContext buildContext, Animation<double> animation,
Animation<double> secondaryAnimation) {
return AnimatedBuilder(
animation: animation,
builder: (context, child) {
// Calculate current position based on animation progress
final currentTop = rowBottomPosition +
(dialogEndPosition - rowBottomPosition - 200) * animation.value;
return Positioned(
top: currentTop,
left: 20,
right: 20,
child: Material(
color: Colors.transparent,
child: Container(
height: 200, // Fixed dialog height
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 10,
offset: Offset(0, 5),
),
],
),
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Row Bottom Dialog',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 20),
Text(
'This dialog slides from the Row bottom (50px from top) to 30px from screen bottom.',
textAlign: TextAlign.center,
),
SizedBox(height: 30),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('Close'),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Action performed!')),
);
},
child: Text('Action'),
),
],
),
],
),
),
),
),
);
},
);
},
);
}
}
// Alternative approach with custom Tween for more control
class CustomPositionTween extends Tween<double> {
CustomPositionTween({
required double rowBottom,
required double screenBottom,
required double dialogHeight,
}) : super(
begin: rowBottom,
end: screenBottom - 30 - dialogHeight,
);
}
// Another example with SlideTransition approach
class AlternativeRowDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
SizedBox(height: 20),
Container(
height: 30,
color: Colors.green.withOpacity(0.3),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Alternative Row'),
SizedBox(width: 20),
ElevatedButton(
onPressed: () => _showSlideDialog(context),
style: ElevatedButton.styleFrom(
minimumSize: Size(80, 25),
padding: EdgeInsets.symmetric(horizontal: 8),
),
child: Text('Show', style: TextStyle(fontSize: 12)),
),
],
),
),
Expanded(child: Container()),
],
),
);
}
void _showSlideDialog(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
showGeneralDialog(
context: context,
barrierDismissible: true,
barrierLabel: '',
barrierColor: Colors.black54,
transitionDuration: Duration(milliseconds: 400),
pageBuilder: (context, animation, secondaryAnimation) {
return SlideTransition(
position: Tween<Offset>(
begin: Offset(0.0, -0.8), // Start near top (adjust based on your needs)
end: Offset(0.0, 0.2), // End near bottom (adjust based on your needs)
).animate(CurvedAnimation(
parent: animation,
curve: Curves.easeInOut,
)),
child: Align(
alignment: Alignment.center,
child: Container(
margin: EdgeInsets.symmetric(horizontal: 20),
height: 200,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 10,
offset: Offset(0, 5),
),
],
),
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Alternative Dialog'),
SizedBox(height: 20),
ElevatedButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('Close'),
),
],
),
),
),
),
);
},
);
}
}