package_flutter_env 0.0.8+1 copy "package_flutter_env: ^0.0.8+1" to clipboard
package_flutter_env: ^0.0.8+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:

  1. 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';
import 'package:scoped_model/scoped_model.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Filter Dialog Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ScopedModel<FilterModel>(
        model: FilterModel(),
        child: FilterScreen(),
      ),
    );
  }
}

class FilterModel extends Model {
  List<String> _tags = [
    'Technology',
    'Design', 
    'Business',
    'Marketing',
    'Development',
    'Science',
    'Art',
    'Music',
    'Sports',
    'Travel'
  ];

  Set<String> _selectedTags = {};
  Set<String> _tempSelectedTags = {};
  bool _isDialogVisible = false;

  List<String> get tags => _tags;
  Set<String> get selectedTags => _selectedTags;
  Set<String> get tempSelectedTags => _tempSelectedTags;
  bool get isDialogVisible => _isDialogVisible;

  void toggleTag(String tag) {
    if (_selectedTags.contains(tag)) {
      _selectedTags.remove(tag);
    } else {
      _selectedTags.add(tag);
    }
    notifyListeners();
  }

  void toggleTempTag(String tag) {
    if (_tempSelectedTags.contains(tag)) {
      _tempSelectedTags.remove(tag);
    } else {
      _tempSelectedTags.add(tag);
    }
    notifyListeners();
  }

  void showDialog() {
    _tempSelectedTags = Set.from(_selectedTags);
    _isDialogVisible = true;
    notifyListeners();
  }

  void hideDialog() {
    _isDialogVisible = false;
    notifyListeners();
  }

  void applySelection() {
    _selectedTags = Set.from(_tempSelectedTags);
    hideDialog();
  }

  void resetSelection() {
    _selectedTags.clear();
    _tempSelectedTags.clear();
    notifyListeners();
  }
}

class FilterScreen extends StatefulWidget {
  @override
  _FilterScreenState createState() => _FilterScreenState();
}

class _FilterScreenState extends State<FilterScreen>
    with TickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _slideAnimation;
  late Animation<double> _fadeAnimation;
  
  final GlobalKey _rowKey = GlobalKey();
  double _dialogTop = 0;
  double _dialogHeight = 0;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      duration: Duration(milliseconds: 350),
      vsync: this,
    );
    
    _slideAnimation = Tween<double>(
      begin: 0.0,
      end: 1.0,
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Curves.easeInOut,
    ));
    
    _fadeAnimation = Tween<double>(
      begin: 0.0,
      end: 0.4,
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Curves.easeInOut,
    ));

    // Listen to model changes for dialog visibility
    WidgetsBinding.instance.addPostFrameCallback((_) {
      ScopedModel.of<FilterModel>(context).addListener(_onModelChanged);
    });
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  void _onModelChanged() {
    final model = ScopedModel.of<FilterModel>(context);
    if (model.isDialogVisible && _animationController.isDismissed) {
      _calculateDialogPosition();
      _animationController.forward();
    } else if (!model.isDialogVisible && _animationController.isCompleted) {
      _animationController.reverse();
    }
  }

  void _calculateDialogPosition() {
    final RenderBox? renderBox = _rowKey.currentContext?.findRenderObject() as RenderBox?;
    if (renderBox != null) {
      final position = renderBox.localToGlobal(Offset.zero);
      final screenHeight = MediaQuery.of(context).size.height;
      _dialogTop = position.dy + renderBox.size.height;
      _dialogHeight = screenHeight - _dialogTop - 30; // 30px bottom space
    }
  }

  Widget _buildTagButton(String tag, bool isSelected, VoidCallback onTap) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        margin: EdgeInsets.symmetric(horizontal: 4),
        padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
        decoration: BoxDecoration(
          color: isSelected ? Colors.blue : Colors.grey[200],
          borderRadius: BorderRadius.circular(20),
          border: Border.all(
            color: isSelected ? Colors.blue : Colors.grey[400]!,
          ),
        ),
        child: Text(
          tag,
          style: TextStyle(
            color: isSelected ? Colors.white : Colors.black87,
            fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Filter Dialog Demo'),
        backgroundColor: Colors.white,
        foregroundColor: Colors.black,
        elevation: 1,
      ),
      body: ScopedModelBuilder<FilterModel>(
        builder: (context, child, model) {
          return Stack(
            children: [
              Column(
                children: [
                  // Main Row with scrollable tags and filter button
                  Container(
                    key: _rowKey,
                    height: 60,
                    padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                    decoration: BoxDecoration(
                      color: Colors.white,
                      boxShadow: [
                        BoxShadow(
                          color: Colors.grey.withOpacity(0.2),
                          spreadRadius: 1,
                          blurRadius: 3,
                          offset: Offset(0, 2),
                        ),
                      ],
                    ),
                    child: Row(
                      children: [
                        // Scrollable tag buttons
                        Expanded(
                          child: ListView.builder(
                            scrollDirection: Axis.horizontal,
                            itemCount: model.tags.length,
                            itemBuilder: (context, index) {
                              final tag = model.tags[index];
                              return _buildTagButton(
                                tag,
                                model.selectedTags.contains(tag),
                                () => model.toggleTag(tag),
                              );
                            },
                          ),
                        ),
                        
                        // Filter button
                        SizedBox(width: 8),
                        GestureDetector(
                          onTap: model.showDialog,
                          child: Container(
                            padding: EdgeInsets.all(8),
                            decoration: BoxDecoration(
                              color: Colors.grey[100],
                              borderRadius: BorderRadius.circular(8),
                            ),
                            child: Icon(
                              Icons.filter_list,
                              color: Colors.grey[600],
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  
                  // Rest of the content
                  Expanded(
                    child: Container(
                      color: Colors.grey[50],
                      child: Center(
                        child: Text(
                          'Selected: ${model.selectedTags.join(', ')}',
                          style: TextStyle(fontSize: 16),
                          textAlign: TextAlign.center,
                        ),
                      ),
                    ),
                  ),
                ],
              ),
              
              // Overlay and Dialog
              if (model.isDialogVisible)
                AnimatedBuilder(
                  animation: _animationController,
                  builder: (context, child) {
                    return Stack(
                      children: [
                        // Semi-transparent overlay
                        Positioned.fill(
                          child: GestureDetector(
                            onTap: model.hideDialog,
                            child: Container(
                              color: Colors.black.withOpacity(_fadeAnimation.value),
                            ),
                          ),
                        ),
                        
                        // Pull-down dialog - entire dialog slides from Row
                        Positioned(
                          top: _dialogTop,
                          left: 16,
                          right: 16,
                          child: Transform.translate(
                            offset: Offset(0, -_dialogHeight * (1 - _slideAnimation.value)),
                            child: Container(
                              height: _dialogHeight,
                              decoration: BoxDecoration(
                                color: Colors.white,
                                borderRadius: BorderRadius.only(
                                  bottomLeft: Radius.circular(12),
                                  bottomRight: Radius.circular(12),
                                ),
                                boxShadow: [
                                  BoxShadow(
                                    color: Colors.black26,
                                    blurRadius: 10,
                                    offset: Offset(0, 4),
                                  ),
                                ],
                              ),
                              child: Column(
                                children: [
                                  // Dialog content
                                  Expanded(
                                    child: Padding(
                                      padding: EdgeInsets.all(16),
                                      child: Column(
                                        crossAxisAlignment: CrossAxisAlignment.start,
                                        children: [
                                          Text(
                                            'Filter Tags',
                                            style: TextStyle(
                                              fontSize: 18,
                                              fontWeight: FontWeight.bold,
                                            ),
                                          ),
                                          SizedBox(height: 16),
                                          
                                          // Two-column tag grid
                                          Expanded(
                                            child: GridView.builder(
                                              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                                                crossAxisCount: 2,
                                                childAspectRatio: 3,
                                                crossAxisSpacing: 8,
                                                mainAxisSpacing: 8,
                                              ),
                                              itemCount: model.tags.length,
                                              itemBuilder: (context, index) {
                                                final tag = model.tags[index];
                                                return _buildTagButton(
                                                  tag,
                                                  model.tempSelectedTags.contains(tag),
                                                  () => model.toggleTempTag(tag),
                                                );
                                              },
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                  ),
                                  
                                  // Bottom buttons
                                  Container(
                                    padding: EdgeInsets.all(16),
                                    decoration: BoxDecoration(
                                      border: Border(
                                        top: BorderSide(color: Colors.grey[300]!),
                                      ),
                                    ),
                                    child: Row(
                                      children: [
                                        Expanded(
                                          child: OutlinedButton(
                                            onPressed: () {
                                              model.resetSelection();
                                              model.hideDialog();
                                            },
                                            style: OutlinedButton.styleFrom(
                                              padding: EdgeInsets.symmetric(vertical: 12),
                                            ),
                                            child: Text('Reset'),
                                          ),
                                        ),
                                        SizedBox(width: 16),
                                        Expanded(
                                          child: ElevatedButton(
                                            onPressed: model.applySelection,
                                            style: ElevatedButton.styleFrom(
                                              padding: EdgeInsets.symmetric(vertical: 12),
                                            ),
                                            child: Text('Done'),
                                          ),
                                        ),
                                      ],
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ),
                      ],
                    );
                  },
                ),
              
              // Clickable space at bottom (when dialog is visible)
              if (model.isDialogVisible)
                Positioned(
                  bottom: 0,
                  left: 0,
                  right: 0,
                  height: 30,
                  child: GestureDetector(
                    onTap: model.hideDialog,
                    child: Container(
                      color: Colors.transparent,
                    ),
                  ),
                ),
            ],
          );
        },
      ),
    );
  }
}

1
likes
0
points
27
downloads

Publisher

unverified uploader

Weekly Downloads

Using MIAppBarWidget to create a custom app bar.

Homepage

License

unknown (license)

Dependencies

flutter, path

More

Packages that depend on package_flutter_env