Flutter - Keyed Collection in Widgets

These are replacements to BottomNavigationBar, IndexedStack, and TabController that use item keys instead if numeric indexes.

Problem

With traditional widgets, you write something like

const tabFavorites = 0;
const tabSearch = 1;
// ...
if (tabIndex == tabFavorites) {
  // ...
}

If items in your bar can change, you get an error-prone conversion from indexes to meanings. Also with a mature architecture you tend to use enum for your tabs, and even with constant bar items you must write code to convert between enum and int.

Solution

This package provides widgets to be used with any type instead of int. In most cases you will use enum.

Some advantages of enum over indexes:

  • No way for the value to fall out of range.
  • Easier debugging with IDE tools.
  • You will never use magic numbers for indexes.
  • No need to synchronize the order of children between different widgets.

String is also a good type to use with these widgets if you have dynamic or potentially unlimited tabs (like in a browser or a document editor) but still want meaningful keys instead of indexes.

KeyedBottomNavigationBar and KeyedStack

This example uses an enum for selectable navigation items:

KeyedBottomNavigationBar, KeyedStack

This example is runnable. Download the repository and open the example project. Then run nav_stack.dart

enum TabEnum { favorites, search }

class _MyScreenState extends State<MyScreen> {
  TabEnum _tab = TabEnum.favorites;

  @override
  Widget build(BuildContext context) {
    // This is a simplified example: IndexedStack and KeyedStack are only
    // meaningful if they contain stateful widgets to preserve state
    // between switches.
    return Scaffold(
      body: KeyedStack<TabEnum>(
        itemKey: _tab,
        children: const {
          TabEnum.favorites: Center(
            key: ValueKey('favorites_pane'),
            child: Text('Favorites'),
          ),
          TabEnum.search: Center(
            key: ValueKey('search_pane'),
            child: Text('Search'),
          ),
        },
      ),
      bottomNavigationBar: KeyedBottomNavigationBar<TabEnum>(
        currentItemKey: _tab,
        items: const {
          TabEnum.favorites: BottomNavigationBarItem(
            icon: Icon(Icons.star),
            label: 'Favorites',
          ),
          TabEnum.search: BottomNavigationBarItem(
            icon: Icon(Icons.search),
            label: 'Search',
          ),
        },
        onTap: (tab) => setState(() {
          _tab = tab;
        }),
      ),
    );
  }
}

KeyedBottomNavigationBar and KeyedStack support all the arguments of their traditional counterparts. The only difference is that current keys are required and do not default to first element.

KeyedTabController, KeyedTabBar, KeyedTabBarView

Minimal Example

This example uses enum for tabs:

KeyedTabController, KeyedTabBar, KeyedTabBarView

This example is runnable. Download the repository and open the example project. Then run tabs.dart

enum MyTab { one, two, three }

class _MyScreenState extends State<MyScreen> with TickerProviderStateMixin {
  late final _tabController = KeyedTabController<TabEnum>(
    initialKey: TabEnum.three,
    keys: [TabEnum.one, TabEnum.two, TabEnum.three],
    vsync: this,
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('${_tabController.currentKey}'),
        bottom: KeyedTabBar(
          tabs: {
            for (final key in _tabController.keys) key: Tab(text: '$key'),
          },
          controller: _tabController,
        ),
      ),
      body: KeyedTabBarView(
        children: {
          for (final key in _tabController.keys)
            key: Center(child: Text('$key content')),
        },
        controller: _tabController,
      ),
    );
  }
}

Redundant Children

The ordinary TabBar and TabBarView must have exactly as many children as their controller is set to. This means that if you need to hide some tabs, there must be three locations in your code to know that:

  1. The code that updates the controller.
  2. The code that creates TabBar widget with tab headers.
  3. The code that creates TabBarView widget with tab contents.

This is extremely error-prone.

With this package, KeyedTabBar and KeyedTabBarView have maps of children, so they can contain more widgets than the controller wants to show.

This means that you can unconditionally pass all children for all possible tabs to them, and the only location in your code that needs to know what tabs to show is the code that updates the controller.

Using KeyedTabController as TabController

KeyedTabController implements TabController and is immediately usable as one. If you ever need to get the tab index or select a tab by index, do it as you normally would.

UnanimatedKeyedTabController

With ordinary TabController, you need TickerProvider to create it. And this limits the usage. You must create TabController in a widget. If you want your BLoC or other business logic code to be aware of tabs or control them, it may be tricky to pass the controller there.

This package provides UnanimatedKeyedTabController which has the logic core for KeyedTabController, but not its animation. You can create this controller anywhere and then add the animation in your widget.

Create it like this:

final unanimatedController = UnanimatedKeyedTabController<TabEnum>(
  keys: [TabEnum.one, TabEnum.two, TabEnum.three],
  initialKey: TabEnum.three,
);

Then create KeyedTabController in your widget:

class _MyScreenState extends State<MyScreen> with TickerProviderStateMixin {
  late final _tabController = KeyedTabController<TabEnum>.fromUnanimated(
    controller: unanimatedController,
    vsync: this,
  );
  // ...

This binds the two controllers. If you change the tab via UnanimatedKeyedTabController, then KeyedTabController gets updated, and the tab change is animated in the UI.

And if the user changes the tab by interacting with it, both controllers get updated.

Mutable Tabs and Animation Duration

Ordinary TabController has a fixed length and animationDuration. If you need to change them, you must create a new controller and replace it everywhere.

KeyedTabController has these mutable.

You can change the tabs at any time by setting KeyedTabController.keys property. If the currently selected tab also exists in the new set, its selection is preserved, otherwise the first new tab gets selected.

This is possible because KeyedTabController does not extend but contains TabController and so it can re-create its internal TabController with different parameters without disturbing its own listeners.

TickerProviderStateMixin vs SingleTickerProviderStateMixin

In Flutter's tab examples, you often see the widget's State created with SingleTickerProviderStateMixin. This only allows one TabController to be created in it. However, KeyedTabController re-creates its TabController if you change keys or animationDuration, so it will break if created with SingleTickerProviderStateMixin.

You should use TickerProviderStateMixin for your widgets instead. It allows many TabController objects to be created with it.

DefaultKeyedTabController

Flutter provides DefaultTabController widget which accepts the number of tabs, creates a TabController and provides it to all tab-related widgets under it.

It has the following advantages:

  1. It is declarative. You don't have to manage your TabController and dispose it.
  2. It allows to change the number of tabs. You just change the length passed to this widget, and it re-creates the TabController, and all widgets under it are updated for the new number of tabs.

This is matched by DefaultKeyedTabController. Although tabs get mutable with this package, the advantage #1 still stands.

This widget comes in two forms:

fromKeys

DefaultKeyedTabController.fromKeys(
  keys: [TabEnum.one, TabEnum.two],
  child: ...
),

Use this when you know the keys to show in your widget.

fromUnanimated

DefaultKeyedTabController.fromUnanimated(
  controller: unanimatedController,
  child: ...
),

Use this if you use UnanimatedKeyedTabController.

Creating Widgets for DefaultKeyedTabController

In Flutter, both TabBar and TabBarView widgets can be created without the controller argument. In this case, they rely on DefaultTabController widget present in the tree above them and break if it is missing.

This is error-prone because the controller argument may simply be forgotten, and this cannot be detected at compile time.

In this package, the controller argument to KeyedTabBar and KeyedTabBarView is required. To rely on the DefaultKeyedTabController, use .withDefaultController static methods of those widgets instead of their default constructors.

There is still no check at compile time that the default controller is present in the tree, but at least you must explicitly declare that you want it and not just have forgotten to pass the controller.

When to use DefaultKeyedTabController

All things equal, prefer DefaultKeyedTabController over manual KeyedTabController creation. This is because that widget will dispose the controller for you when it is not needed anymore.

Advanced Example

KeyedBottomNavigationBar, KeyedStack, Tabs

This example shows:

  • Changing the set of tabs without re-creating a controller.
  • Programmatically activating a tab by its key.
  • Programmatically activating a tab by its index.
  • Changing the animation duration without re-creating a controller.
  • DefaultKeyedTabController widgets.
  • UnanimatedKeyedTabController.
  • Replacing the UnanimatedKeyedTabController that a KeyedTabController is linked to.

This example is runnable. Download the repository and open the example project. Then run nav_stack_tabs.dart

enum_map

Although enum enhances type safety for tabs, it is still not absolute. In widgets, you may still forget to use all keys in children map and only know that at runtime.

You can make this compile-time safe by using enum_map package that generates maps that are guaranteed to have all keys at compile time (see that package's README for more info):

@unmodifiableEnumMap                                    // CHANGED
enum TabEnum { one, two, three }

class _MyScreenState extends State<MyScreen> with TickerProviderStateMixin {
  late final _tabController = KeyedTabController<TabEnum>(
    initialKey: TabEnum.three,
    keys: [TabEnum.one, TabEnum.two, TabEnum.three],
    vsync: this,
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('${_tabController.currentKey}'),
        bottom: KeyedTabBar(
          controller: _tabController,
          tabs: const UnmodifiableTabEnumMap(           // CHANGED
            one: Tab(text: 'One'),                      // CHANGED
            two: Tab(text: 'Two'),                      // CHANGED
            three: Tab(text: 'Three'),                  // CHANGED
          ),                                            // CHANGED
        ),
      ),
      body: KeyedTabBarView(
        controller: _tabController,
        children: const UnmodifiableTabEnumMap(         // CHANGED
          one: Center(child: Text('One content')),      // CHANGED
          two: Center(child: Text('Two content')),      // CHANGED
          three: Center(child: Text('Three content')),  // CHANGED
        ),                                              // CHANGED
      ),
    );
  }
}

Support Chat

Do you have any questions? Feel free to ask in the Telegram Support Chat.

Or even just join to say 'Hi!'. I like to hear from the users.

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add keyed_collection_widgets

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  keyed_collection_widgets: ^0.4.1

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:keyed_collection_widgets/keyed_collection_widgets.dart'; 

example/README.md

example

All examples here are runnable. Download this repository to your computer and open it in your editor. In Android Studio, you can run examples like this:

Running Examples

1. nav_stack.dart

This example shows KeyedBottomNavigationBar and KeyedStack widgets:

KeyedBottomNavigationBar, KeyedStack

2. tabs.dart

This example shows KeyedTabController and widgets KeyedTabBar and KeyedTabBarView:

KeyedTabController, KeyedTabBar, KeyedTabBarView

3. tabs_enum_map.dart

This is a variation of tabs.dart that uses enum_map for compile-time type safety with tabs.

4. unanimated_keyed_tab_controller.dart

This is a variation of tabs.dart that uses `UnanimatedKeyedTabController.

5. nav_stack_tabs.dart

This is the ultimate advanced example that shows:

  • Changing the set of tabs without re-creating a controller.
  • Programmatically activating a tab by its key.
  • Programmatically activating a tab by its index.
  • Changing the animation duration without re-creating a controller.
  • DefaultKeyedTabController widgets.
  • UnanimatedKeyedTabController.
  • Replacing UnanimatedKeyedTabController that KeyedTabController is linked to.

KeyedBottomNavigationBar, KeyedStack, Tabs

Download Details:

Author: alexeyinkin

Source Code: https://github.com/alexeyinkin/flutter-keyed-collection-widgets

#widget #key 

Flutter - Keyed Collection in Widgets

Handle Changes to A Text Field in Flutter

reactive_code_text_field

Wrapper around code_text_field to use with reactive_forms

Docs in progress. See example folder for sample.

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add reactive_code_text_field

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  reactive_code_text_field: ^0.4.0

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:reactive_code_text_field/reactive_code_text_field.dart'; 

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_highlight/themes/monokai-sublime.dart';
import 'package:highlight/languages/dart.dart';
import 'package:reactive_code_text_field/reactive_code_text_field.dart';
import 'package:reactive_forms/reactive_forms.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  FormGroup buildForm() => fb.group({
        'input': FormControl<String>(
          value: "void main() {\n    print(\"Hello, world!\");\n}",
        ),
      });

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: Scaffold(
        appBar: AppBar(),
        body: SafeArea(
          child: SingleChildScrollView(
            physics: const BouncingScrollPhysics(),
            padding: const EdgeInsets.symmetric(
              horizontal: 20.0,
              vertical: 20.0,
            ),
            child: ReactiveFormBuilder(
              form: buildForm,
              builder: (context, form, child) {
                return Column(
                  children: [
                    ReactiveCodeTextField<String>(
                      formControlName: 'input',
                      controller: CodeController(
                        language: dart,
                        theme: monokaiSublimeTheme,
                      ),
                    ),
                    ElevatedButton(
                      child: const Text('Sign Up'),
                      onPressed: () {
                        if (form.valid) {
                          // ignore: avoid_print
                          print(form.value);
                        } else {
                          form.markAllAsTouched();
                        }
                      },
                    ),
                  ],
                );
              },
            ),
          ),
        ),
      ),
    );
  }
} 

Download Details:

Author: artflutter

Source Code: https://github.com/artflutter/reactive_forms_widgets

#flutter  #widget 

Handle Changes to A Text Field in Flutter
Gordon  Murray

Gordon Murray

1669351082

How to Set The Text Displayed using The TextView Widget

Android - How to set TextView widget text

The Android TextView widget is a UI component used for displaying text in your interface.

The text displayed in the TextView can be set using the android:text attribute in your XML layout file.

Here’s an example of setting the TextView’s text value to “Good Morning!":

<TextView
    android:id="@+id/id_text_view"
    android:text="Good Morning!"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

The text displayed by the TextView will be the same as the value of the android:text attribute.

Set the TextView text programmatically

You can also set the TextView’s text attribute programmatically in your Activity class.

Inside the Activity class where you want to set the text, find the TextView using the findViewById() method.

Then, use the setText() method to set the new text.

Here’s the code example in Java:

TextView myTextView = findViewById(R.id.id_text_view);
myTextView.setText("Good Evening!");

In Kotlin, you can set the text property of the TextView widget directly.

You don’t need to call the setText() method as shown below:

val myTextView = findViewById<TextView>(R.id.textView)
myTextView.text = "Good Evening!"

And that’s how you set the TextView text programmatically.

Next, let’s learn how you can use a string resource to set the TextView text.

Using a resource string to set the TextView text

Generally, you are recommended to use the @string resource value so that the text can be updated from one place.

Android Studio helps you to extract the string resource when you open the context action menu (ALT + ENTER)

Android extract string resource optionAndroid extract string resource option

Suppose you have three text views in different XML files that display the “Good Morning!” text.

When you hard-code the string, then you need to change all occurrences of the “Good Morning!” text manually.

By using a string resource, you only need to change the value of the string in the strings.xml file:

<resources>
    <string name="good_morning">Good Morning!</string>
</resources>

All TextView widgets with the @string/good_morning text attribute will use the resource string above:

<TextView
    android:id="@+id/id_text_view"
    android:text="@string/good_morning"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

You can also use a string resource value when setting the text programmatically.

Here’s the code example in Java:

TextView myTextView = findViewById(R.id.id_text_view);
myTextView.setText(R.string.good_morning);

And here’s the code example in Kotlin:

val myTextView = findViewById<TextView>(R.id.textView)
myTextView.setText(R.string.good_morning)
// or
myTextView.text = getString(R.string.good_morning)

Note that you still need to use the setter method when using the string resource.

Otherwise, you need to use the getString() method to retrieve the string value from the resource.

Now you’ve learned how to set the TextView widget text in Android development. Nice work! 👍

Original article source at: https://sebhastian.com/

#android #widget #text 

How to Set The Text Displayed using The TextView Widget

A Simple Set of Widgets to Demonstrate The Mathmatical Conjecture

Introduction

This is a relatively application and set of libraries that can be used to show Collatz conjecture, which is defined via the following rules:

  1. Take any arbitrary whole number
  2. If that number is odd, multiply it by 3 and add 1.
  3. If that number is even, divide by two.

If you repeat steps 2 and 3 enough times, you will always end up with a end loop of 4, 2, 1. As 1 is odd when you perform the operation (3x + 1) it is an endless loop.

This application and set of libraries are meant to be a fun way to help demonstrate a simple sounding math problems as well provide some examples of working with streaming data.

You are free to download the source and build for any of your own devices, or to play around with the online web based application.

For more information on the 3x + 1 conjecture, see this really awesome video by Veritasium hosted on YouTube.

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add three_x_plus_1

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  three_x_plus_1: ^1.0.0

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:three_x_plus_1/three_x_plus_1.dart'; 

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:three_x_plus_1/three_x_plus_1.dart';

void main() {
  var mathBloc = MathBloc();

  runApp(
    Provider<MathBloc>.value(
      value: mathBloc,
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '3x + 1',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: '3x + 1'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Column(
        children: <Widget>[
          Inputs(),
          Expanded(
            flex: 1,
            child: MathGraph(),
          ),
          SizedBox(
            height: MediaQuery.of(context).padding.bottom + 60.0,
            child: Padding(
              padding: EdgeInsets.only(
                bottom: MediaQuery.of(context).padding.bottom + 16.0,
                left: MediaQuery.of(context).padding.left + 16.0,
                right: MediaQuery.of(context).padding.right + 16.0,
                top: 16.0,
              ),
              child: StepValue(),
            ),
          ),
        ],
      ),
    );
  }
} 

Download Details:

Author: peiffer-innovations

Source Code: https://github.com/peiffer-innovations/three_x_plus_1

#flutter #widget 

A Simple Set of Widgets to Demonstrate The Mathmatical Conjecture

Flutter - Custom Widget Packages Screen Util

entities

Provide utility classes to operate entities in an immutable way.

This Package

The Entity is defined as a class with an Id, as shown below.

abstract class Entity<Id> {
  Id get id;
}

This package provides the Entities class, which is a set of Entity. Entities is an immutable class that has a convenient API.

How to Use

The first step is to define a class that implements Entity.

class Todo implements Entity<String> {
  final String id;
  final String name;

  const Todo(this.id, this.name);
}

Then optionally give an alias to Entities.

typedef Todos = Entities<String, Todo>;

You are now ready to immutably manage a set of Entity. This example makes available the Todos class, which has methods to add and remove Todo immutably.

You can define a todo set from Todos.empty().

final todo1 = Todo("1", "todo1");
final todo2 = Todo("2", "todo2");
final todo3 = Todo("3", "todo3");

final todos = Todos.empty();

You can use the put(Todo todo) method to get a new Todos with todo added.

final putTodos = todos.put(todo1);
print(putTodos);
// Entities<String, Todo>(Todo(1, todo1))

You can add multiple todo at the same time with the putAll(Iterable<Todo> todo) method.

final putAllTodos = todos.putAll([todo1, todo2, todo3]);
print(putAllTodos);
// Entities<String, Todo>(Todo(1, todo1), Todo(2, todo2), Todo(3, todo3))

The remove(Todo todo) method removes the todo, and you get new todos.

final removeTodos = putAllTodos.remove(todo1);
print(removeTodos);
// Entities<String, Todo>(Todo(2, todo2), Todo(3, todo3))

The removeAll(Iterable<Todo> todo) method allows you to remove multiple todo at the same time.

final removeAllTodos = putAllTodos.removeAll([todo1, todo2, todo3]);
print(removeAllTodos);
// Entities<String, Todo>()

Since these methods are immutable, the new todos will be a different object than the original todos.

expect(todos == putTodos, false);
expect(todos == putAllTodos, false);
expect(putAllTodos == removeTodos, false);
expect(removeAllTodos == putAllTodos, false);

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add entities

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  entities: ^0.0.2

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:entities/entities.dart'; 

Download Details:

Author: soraef

Source Code: https://github.com/soraef/flutter_util

#flutter #widget 

Flutter - Custom Widget Packages Screen Util

How To Add a Backdrop in Flutter (Material Design)

backdrop_widget

Backdrop component for Material Components 2.0. Material Components 2.0 Backdrop Widget is implemented behavior and styling backdrop material component. This have two mode behavior:

  • Open page mode
  • Navigation mode

How use

One destination mode

One destination

  @override
  Widget build(BuildContext context) {
    return BackdropScaffold(
    titleAppBar: //Your title
    frontWidgetBuilder: (context){
        //Return your frontPanel widget
    }, backPanelBuilder: (context) {
          //Return your backPanel widget
    });
  }

Navigation mode

Demonstration navigation

  @override
  Widget build(BuildContext context) {
    return BackdropScaffold.navigation(
              titleAppBar: Text('Backdrop example'),
              destinations: [
                NavigationDestination(
                  icon: //Icon page, 
                  title: //Title page
                ),
              ],
              children: [
                //Your pages
              ],
            );
  }

If you needed AppBar actions for page, use this [BackdropPageActionsMixin]

class Page extends StatelessWidget with BackdropPageActionsMixin {
  const Page();

  @override
  List<Widget> get actions => [IconButton(icon: const Icon(Icons.exit_to_app), onPressed: () {})];

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('Page with action'),
    );
  }
}

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add backdrop_material_widget

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  backdrop_material_widget: ^2.0.0

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:backdrop_material_widget/backdrop_material_widget.dart'; 

example/lib/main.dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:backdrop_material_widget/backdrop_material_widget.dart';

import 'one_page_screen.dart';

void main() => runApp(MyApp());

List<String> genList(int length) => List<String>.generate(length, (index) => 'Item $index');

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(primarySwatch: Colors.green, brightness: Brightness.dark),
        home: BackdropScaffold.navigation(
          Text('Backdrop example'),
          const [
            NavigationDestination(Icon(Icons.title), Text('Empty page')),
            NavigationDestination(Icon(Icons.title), Text('Page list'), subHeader: Text('With infinite list length')),
            NavigationDestination(Icon(Icons.title), Text('Page actions'), subHeader: Text('Page with action'))
          ],
          [
            OnePage(),
            FutureBuilder<List<String>>(
              future: compute<int, List<String>>(genList, 1000),
              builder: (context, snapshot) {
                if (!snapshot.hasData)
                  return const Center(
                    child: CircularProgressIndicator(),
                  );
                if (snapshot.data!.isEmpty)
                  return const Center(
                    child: Text('List is empty'),
                  );
                return ListView.builder(
                  itemCount: snapshot.data!.length,
                  itemBuilder: (context, index) => ListTile(
                    title: Text(snapshot.data![index]),
                  ),
                );
              },
            ),
            ThreePage()
          ],
        ),
      );
}

class OnePage extends StatelessWidget {
  const OnePage();

  @override
  Widget build(BuildContext context) => Container(
        child: Center(
          child: TextButton(
              onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (_) => OnePageScreen())),
              child: const Text('Open one page backdrop')),
        ),
      );
}

class ThreePage extends StatelessWidget with BackdropPageActionsMixin {
  @override
  List<Widget> actions(BuildContext context) => [IconButton(icon: const Icon(Icons.exit_to_app), onPressed: () {})];

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.grey,
    );
  }
} 

Download Details:

Author: andreykedo

Source Code: https://gitlab.com/andreykedo/backdrop_widget

#flutter #widget 

How To Add a Backdrop in Flutter (Material Design)

A Flutter Plugin Which Provides using Google Maps Widget

Google Maps Place Picker - MB edition

This README is only slightly changed from its original repo which this repository was forked from. Due to little maintenance by the original author, I want to provide this fork that is not just more maintained, I also add more functionality to it and pick any significant changes and PRs on the original repository, as well.

To install:

flutter pub add agromart_google_maps_place_picker

~ martin-braun


A Flutter plugin which provides 'Picking Place' using Google Maps widget.

The project relies on below packages.

Map using Flutter's official google_maps_flutter
Fetching current location using Baseflow's geolocator
Place and Geocoding API using hadrienlejard's google_maps_webservice
Builder using kevmoo's tuple

Preview

Note: This preview shows a new feature added by me: The ability to restrict the picked selection to the circle area. This can be disabled, obviously.

~ martin-braun

Support

If the package was useful or saved your time, please do not hesitate to buy me the original author a cup of coffee! ;)
The more caffeine I get he gets, the more useful projects I he can make in the future.

Getting Started

Get an API key at https://cloud.google.com/maps-platform/.

Enable Google Map SDK for each platform.

  • Go to Google Developers Console.
  • Choose the project that you want to enable Google Maps on.
  • Select the navigation menu and then select "Google Maps".
  • Select "APIs" under the Google Maps menu.
  • To enable Google Maps for Android, select "Maps SDK for Android" in the "Additional APIs" section, then select "ENABLE".
  • To enable Google Maps for iOS, select "Maps SDK for iOS" in the "Additional APIs" section, then select "ENABLE".
  • Also enable "Geocoding API", "Geolocation API" and "Places API"
  • Make sure the APIs you enabled are under the "Enabled APIs" section.
  • Generate the API key for all APIs

You can also find detailed steps to get started with Google Maps Platform here.

Android

Specify your API key in the application manifest android/app/src/main/AndroidManifest.xml:

<manifest ...
  <application ...
    <meta-data android:name="com.google.android.geo.API_KEY"
               android:value="YOUR KEY HERE"/>

NOTE: As of version 3.0.0 the geolocator plugin switched to the AndroidX version of the Android Support Libraries. This means you need to make sure your Android project is also upgraded to support AndroidX. Detailed instructions can be found here.

The TL;DR version is:

  1. Add the following to your "gradle.properties" file:
android.useAndroidX=true
android.enableJetifier=true
  1. Make sure you set the compileSdkVersion in your "android/app/build.gradle" file to 28:
android {
 compileSdkVersion 28

 ...
}
  1. Make sure you replace all the android. dependencies to their AndroidX counterparts (a full list can be found here: https://developer.android.com/jetpack/androidx/migrate).

iOS

Specify your API key in the application delegate ios/Runner/AppDelegate.m:

#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#import "GoogleMaps/GoogleMaps.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GMSServices provideAPIKey:@"YOUR KEY HERE"];
  [GeneratedPluginRegistrant registerWithRegistry:self];
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end

Or in your swift code, specify your API key in the application delegate ios/Runner/AppDelegate.swift:

import UIKit
import Flutter
import GoogleMaps

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
  ) -> Bool {
    GMSServices.provideAPIKey("YOUR KEY HERE")
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

On iOS you'll need to add the following entries to your Info.plist file (located under ios/Runner) in order to access the device's location.

Simply open your Info.plist file and add the following:

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to location when in the background.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs access to location when open and in the background.</string>

In addition, you need to add the Background Modes capability to your XCode project (Project > Signing and Capabilties > "+ Capability" button) and select Location Updates.g>This app needs access to location when open and in the background.

Opt-in to the embedded views preview by adding a boolean property to the app's Info.plist file with the key io.flutter.embedded_views_preview and the value YES.

<key>io.flutter.embedded_views_preview</key>
<true/>

Usage

Basic usage

You can use PlacePicker by pushing to a new page using Navigator, OR put as a child of any widget.
When the user picks a place on the map, it will return result to 'onPlacePicked' with PickResult type. Alternatively, you can build your own way with 'selectedPlaceWidgetBuilder' and fetch result from it (See the instruction below).

Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => PlacePicker(
          apiKey: APIKeys.apiKey,   // Put YOUR OWN KEY here. Should be the same for android and ios
          onPlacePicked: (result) {
            print(result.address);
            Navigator.of(context).pop();
          },
          initialPosition: HomePage.kInitialPosition,
          useCurrentLocation: true,
        ),
      ),
    );

PickResult

ParameterTypeDescription
placeIdStringA textual identifier that uniquely identifies a place. To retrieve information about the place, pass this identifier in the placeId field of a Places API request. See PlaceId for more information.
geometryGeometryContains geometry information about the result, generally including the location (geocode) of the place and (optionally) the viewport identifying its general area of coverage.
formattedAddressStringA string containing the human-readable address of this place. Often this address is equivalent to the "postal address".
typesList<String>Contains an array of feature types describing the given result. See the list of supported types. XML responses include multiple
addressComponentsList<AddressComponent>An array containing the separate components applicable to this address.

** Below results will be fetched only when using auto-complete search or usePlaceDetailSearch is set to true when searching by dragging the map.

PickResult (Optional)

ParameterTypeDescription
adrAddressStringA representation of the place's address in the adr microformat
formattedPhoneNumberStringContains the place's phone number in its local format
idString? (Not documented at Google - see more info below)
referenceString? (Not documented at Google - see more info below)
iconStringThe URL of a suggested icon which may be displayed to the user when indicating this result on a map.
nameStringHuman-readable name for the returned result
openingHoursOpeningHoursDetailOpening hour information
photosList<Photo>Array of photo objects, each containing a reference to an image
internationalPhoneNumberStringThe place's phone number in international format
priceLevelPriceLevelThe price level of the place, on a scale of 0 to 4. The exact amount indicated by a specific value will vary from region to region.
ratingnumThe place's rating, from 1.0 to 5.0, based on aggregated user reviews.
scopeString 
urlStringThe URL of the official Google page for this place.
vicinityStringLists a simplified address for the place, including the street name, street number, and locality, but not the province/state, postal code, or country
utcOffsetnumThe number of minutes this place’s current timezone is offset from UTC
websiteStringThe authoritative website for this place
reviewsList<Review>JSON array of up to five reviews

More info about results at Google document.

PlacePicker

ParameterTypeDescription
apiKeyString(Required) Your google map API Key
onPlacePickedCallback(PickResult)Invoked when user picks the place and selects to use it. This will not be called if you manually build 'selectedPlaceWidgetBuilder' as you will override default 'Select here' button.
initialPositionLatLng(Required) Initial center position of google map when it is created. If useCurrentLocation is set to true, it will try to get device's current location first using GeoLocator.
useCurrentLocationboolWhether to use device's current location for initial center position. This will be used instead of initial position when it is set to true AND user ALLOW to collect their location. If DENIED, initialPosition will be used.
desiredLocationAccuracyLocationAccuracyAccuracy of fetching current location. Defaults to 'high'.
hintTextStringHint text of search bar
searchingTextStringA text which appears when searching is performing. Default to 'Searching...'
selectText*String?Text to show in the button that allows to pick the focused address. Defaults to show only an icon.
outsideOfPickAreaText*String?Text to show in the disabled button when the focused address is outside of the pick area. Defaults to show only an icon.
proxyBaseUrlStringUsed for API calling on google maps. In case of using a proxy the baseUrl can be set. The apiKey is not required in case the proxy sets it.
httpClientClientUsed for API calling on google maps. In case of using a proxy url that requires authentication or custom configuration.
autoCompleteDebounceInMillisecondsintDebounce timer for auto complete input. Default to 500
cameraMoveDebounceInMillisecondsintDebounce timer for searching place with camera(map) dragging. Defaults to 750
intialMapTypeMapTypeMapTypes of google map. Defaults to normal.
enableMapTypeButtonboolWhether to display MapType change button on the map
enableMyLocationButtonboolWhether to display my location button on the map
usePinPointingSearchboolDefaults to true. This will allow user to drag map and get a place info where the pin is pointing.
usePlaceDetailSearchboolDefaults to false. Setting this to true will get detailed result from searching by dragging the map, but will use +1 request on Place Detail API.
onAutoCompleteFailedCallback(String)Invoked when auto complete search is failed
onGeocodingSearchFailedCallback(String)Invoked when searching place by dragging the map failed
onMapCreatedMapCreatedCallbackReturens google map controller when created
selectedPlaceWidgetBuilderWidgetBuilderSpecified on below section
pinBuilderWidgetBuilderSpecified on below section
introPanelWidgetBuilderWidgetBuilderSpecified on below section
autocompleteOffsetnumThe position, in the input term, of the last character that the service uses to match predictions
autocompleteRadiusnumThe distance (in meters) within which to return place results
autocompleteLanguageStringThe language code, indicating in which language the results should be returned, if possible.
autocompleteComponentsList<Components>A grouping of places to which you would like to restrict your results. Currently, you can use components to filter by up to 5 countries.
autocompleteTypesList<String>The types of place results to return. See Place Types.
strictboundsboolReturns only those places that are strictly within the region defined by location and radius.
regionStringregion — The region code, specified as a ccTLD (country code top-level domain) two-character value. Most ccTLD codes are identical to ISO 3166-1 codes, with some exceptions. This parameter will only influence, not fully restrict, search results. If more relevant results exist outside of the specified region, they may be included. When this parameter is used, the country name is omitted from the resulting formatted_address for results in the specified region.
pickArea*CircleAreaCircle that defines the area in which the address can be picked. Can be colored how it's preferred.
selectInitialPositionboolWhether to display selected place on initial map load. Defaults to false.
resizeToAvoidBottomInsetboolRefer to Scaffold's resizeToAvoidBottomInset property.
initialSearchStringStringSets initial search string for auto complete search
searchForInitialValueboolWether to automatically search for initial value on start
forceAndroidLocationManagerboolOn Android devices you can set this to true to force the geolocator plugin to use the 'LocationManager' to determine the position instead of the 'FusedLocationProviderClient'. On iOS this is ignored.
myLocationButtonCooldownintCooldown time in seconds for the 'myLocationButton'. Defaults to 10 seconds.
forceSearchOnZoomChangedboolWether to allow place search even when the zoom has changed. Defaults to false.
automaticallyImplyAppBarLeadingboolBy default, there is a back button on the top. Setting false will remove the back button.
autocompleteOnTrailingWhitespaceboolWhether to allow autocomplete to run even on whitespace at the end of the search. Defaults to false. Issue ref #54.
onTapBack*Function(PlaceProvider)?Called when leaving the Google Picker by pressing the back button.
onCameraMoveStarted*Function(PlaceProvider)?Called when the camera starts moving. (GoogleMap widget)
onCameraMove*CameraPositionCallback?Called repeatedly as the camera continues to move after an onCameraMoveStarted call. (GoogleMap widget)
onCameraIdle*Function(PlaceProvider)?Called when camera movement has ended, there are no pending animations and the user has stopped interacting with the map. (GoogleMap widget)

* MB edition exclusive, as of now

~ martin-braun

More info about autocomplete search at Google document.

Customizing picked place visualization

By default, when a user picks a place by using auto complete search or dragging the map, we display the information at the bottom of the screen (FloatingCard).

However, if you don't like this UI/UX, simply override the builder using 'selectedPlaceWidgetBuilder'. FloatingCard widget can be reused which is floating around the screen or build an entirely new widget as you want. It is stacked with the map, so you might want to use the Positioned widget.

Note that using this customization WILL NOT INVOKE [onPlacePicked] callback as it will override default 'Select here' button on floating card

...
PlacePicker(apiKey: APIKeys.apiKey,
            ...
            selectedPlaceWidgetBuilder: (_, selectedPlace, state, isSearchBarFocused) {
              return isSearchBarFocused
                  ? Container()
                  // Use FloatingCard or just create your own Widget.
                  : FloatingCard(
                      bottomPosition: 0.0,    // MediaQuery.of(context) will cause rebuild. See MediaQuery document for the information.
                      leftPosition: 0.0,
                      rightPosition: 0.0,
                      width: 500,
                      borderRadius: BorderRadius.circular(12.0),
                      child: state == SearchingState.Searching ?
                                      Center(child: CircularProgressIndicator()) :
                                      RaisedButton(onPressed: () { print("do something with [selectedPlace] data"); },),
                   );
            },
            ...
          ),
...
ParametersTypeDescription
contextBuildContextFlutter's build context value
selectedPlacePickResultResult data of user selected place
stateSearchingStateState of searching action. (Idle, Searching)
isSearchBarFocusedboolWhether the search bar is currently focused so the keyboard is shown

Customizing Pin

By default, Pin icon is provided with very simple picking animation when moving around.
However, you can also create your own pin widget using 'pinBuilder'

PlacePicker(apiKey: APIKeys.apiKey,
            ...
            pinBuilder: (context, state) {
                  if (state == PinState.Idle) {
                    return Icon(Icons.favorite_border);
                  } else {
                    return AnimatedIcon(.....);
                  }
                },
            ...
          ),
...
ParametersTypeDescription
contextBuildContextFlutter's build context value
statePinStateState of pin. (Preparing; When map loading, Idle, Dragging)

Add customized introduction modal

By default the map will show up, immediately. You might want to show a nice customized overlay modal with instructions, especially, when the map is turned on after first start of your app. In that case this custom widget builder makes sense, because you will obtain the most freedom in terms of branding to avoid people thinking they opened Google Maps.

PlacePicker(apiKey: APIKeys.apiKey,
            ...
            introModalWidgetBuilder: (context,  close) {
              return Positioned(
                top: MediaQuery.of(context).size.height * 0.35,
                right: MediaQuery.of(context).size.width * 0.15,
                left: MediaQuery.of(context).size.width * 0.15,
                child: Container(
                  width: MediaQuery.of(context).size.width * 0.7,
                  child: Material(
                    type: MaterialType.canvas,
                    color: Theme.of(context).cardColor,
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(12.0),
                    ),
                    elevation: 4.0,
                    child: ClipRRect(
                      borderRadius: BorderRadius.circular(12.0),
                      child: Container(
                        padding: EdgeInsets.all(8.0),
                        child: Column(
                          children: [
                            SizedBox.fromSize(size: new Size(0, 10)),
                            Text("Please select your preferred address.",
                              style: TextStyle(
                                fontWeight: FontWeight.bold,
                              )
                            ),
                            SizedBox.fromSize(size: new Size(0, 10)),
                            SizedBox.fromSize(
                              size: Size(MediaQuery.of(context).size.width * 0.6, 56), // button width and height
                              child: ClipRRect(
                                borderRadius: BorderRadius.circular(10.0),
                                child: Material(
                                  child: InkWell(
                                    overlayColor: MaterialStateColor.resolveWith(
                                      (states) => Colors.blueAccent
                                    ),
                                    onTap: close,
                                    child: Row(
                                      mainAxisAlignment: MainAxisAlignment.center,
                                      children: [
                                        Icon(Icons.check_sharp, color: Colors.blueAccent),
                                        SizedBox.fromSize(size: new Size(10, 0)),
                                        Text("OK",
                                          style: TextStyle(
                                            color: Colors.blueAccent
                                          )
                                        )
                                      ],
                                    )
                                  ),
                                ),
                              ),
                            )
                          ]
                        )
                      ),
                    ),
                  ),
                )
              );
            },
            ...
          ),
...
ParametersTypeDescription
contextBuildContextFlutter's build context value
closeFunctionFunction to be called to close the modal, thus removing the widget and its overlay from the tree.

Changing Colours of default FloatingCard

While you can build your own prediction tile, you still can change the style of default tile using themeData as below:

// Light Theme
final ThemeData lightTheme = ThemeData.light().copyWith(
  // Background color of the FloatingCard
  cardColor: Colors.white,
);

// Dark Theme
final ThemeData darkTheme = ThemeData.dark().copyWith(
  // Background color of the FloatingCard
  cardColor: Colors.grey,
);

Feature Requests and Issues

Please file feature requests at the original issue tracker and bugs at the MB edition issue tracker. I fetch any significant feature requests from the original repository, but bugs could be specific to this MB edition, so I want to take care by myself on them.

~ martin-braun

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add agromart_google_maps_place_picker

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  agromart_google_maps_place_picker: ^2.0.0-lws-0.2

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:agromart_google_maps_place_picker/agromart_google_maps_place_picker.dart'; 

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:agromart_google_maps_place_picker/agromart_google_maps_place_picker.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

// Your api key storage.
import 'keys.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // Light Theme
  final ThemeData lightTheme = ThemeData.light().copyWith(
    // Background color of the FloatingCard
    cardColor: Colors.white,
  );

  // Dark Theme
  final ThemeData darkTheme = ThemeData.dark().copyWith(
    // Background color of the FloatingCard
    cardColor: Colors.grey,
  );

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Google Map Place Picker Demo',
      theme: lightTheme,
      darkTheme: darkTheme,
      themeMode: ThemeMode.light,
      home: HomePage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key key}) : super(key: key);

  static final kInitialPosition = LatLng(-33.8567844, 151.213108);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  PickResult selectedPlace;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Google Map Place Picker Demo"),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              ElevatedButton(
                child: Text("Load Google Map"),
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) {
                        return PlacePicker(
                          apiKey: APIKeys.apiKey,
                          hintText: "Find a place ...",
                          searchingText: "Please wait ...",
                          selectText: "Select place",
                          outsideOfPickAreaText: "Place not in area",
                          initialPosition: HomePage.kInitialPosition,
                          useCurrentLocation: false,
                          selectInitialPosition: true,
                          usePinPointingSearch: true,
                          usePlaceDetailSearch: true,
                          autocompleteLanguage: "en",
                          region: 'my',
                          pickArea: CircleArea(
                            center: LatLng(3.157764, 101.711861),
                            radius: 7000,
                            fillColor:
                                Colors.lightGreen.withGreen(255).withAlpha(32),
                            strokeColor:
                                Colors.lightGreen.withGreen(255).withAlpha(192),
                            strokeWidth: 2,
                          ),
                          onPlacePicked: (result) {
                            selectedPlace = result;
                            Navigator.of(context).pop();
                            setState(() {});
                          },
                        );
                      },
                    ),
                  );
                },
              ),
              selectedPlace == null
                  ? Container()
                  : Text(selectedPlace.formattedAddress ?? ""),
            ],
          ),
        ));
  }
} 

Download Details:

Author: 

Source Code: https://pub.dev/packages/agromart_google_maps_place_picker

#flutter #widget 

A Flutter Plugin Which Provides using Google Maps Widget

A Widget for Flutter to Display Lyrics

flutter_lyric

Music Lyric Library.

Examples running screenshots

pic

Usage

1. Add library to your pubspec.yaml

latest version:pub package

dependencies:
  flutter_lyric: ^1.0.3 # such as version, you need use the latest version of pub.

2. new LyricController

    var controller = LyricController(vsync: this);

3. LyricStr To LyricList

  //歌词
  var songLyc =
      "[00:00.000] 作曲 : Maynard Plant/Blaise Plant/菊池拓哉 \n[00:00.226] 作词 : Maynard Plant/Blaise Plant/菊池拓哉\n[00:00.680]明日を照らすよSunshine\n[00:03.570]窓から射し込む…扉開いて\n[00:20.920]Stop!'cause you got me thinking\n[00:22.360]that I'm a little quicker\n[00:23.520]Go!Maybe the rhythm's off,\n[00:25.100]but I will never let you\n[00:26.280]Know!I wish that you could see it for yourself.\n[00:28.560]It's not,it's not,just stop,hey y'all!やだ!\n[00:30.930]I never thought that I would take over it all.\n[00:33.420]And now I know that there's no way I could fall.\n[00:35.970]You know it's on and on and off and on,\n[00:38.210]And no one gets away.\n[00:40.300]僕の夢は何処に在るのか?\n[00:45.100]影も形も見えなくて\n[00:50.200]追いかけていた守るべきもの\n[00:54.860]There's a sunshine in my mind\n[01:02.400]明日を照らすよSunshineどこまでも続く\n[01:07.340]目の前に広がるヒカリの先へ\n[01:12.870]未来の\n[01:15.420]輝く\n[01:18.100]You know it's hard,just take a chance.\n[01:19.670]信じて\n[01:21.289]明日も晴れるかな?\n[01:32.960]ほんの些細なことに何度も躊躇ったり\n[01:37.830]誰かのその言葉いつも気にして\n[01:42.850]そんな弱い僕でも「いつか必ずきっと!」\n[01:47.800]強がり?それも負け惜しみ?\n[01:51.940]僕の夢は何だったのか\n[01:56.720]大事なことも忘れて\n[02:01.680]目の前にある守るべきもの\n[02:06.640]There's a sunshine in my mind\n[02:14.500]明日を照らすよSunshineどこまでも続く\n[02:19.000]目の前に広がるヒカリの先へ\n[02:24.670]未来のSunshine\n[02:27.200]輝くSunshine\n[02:29.900]You know it's hard,just take a chance.\n[02:31.420]信じて\n[02:33.300]明日も晴れるかな?\n[02:47.200]Rain's got me now\n[03:05.650]I guess I'm waiting for that Sunshine\n[03:09.200]Why's It only shine in my mind\n[03:15.960]I guess I'm waiting for that Sunshine\n[03:19.110]Why's It only shine in my mind\n[03:25.970]明日を照らすよSunshineどこまでも続く\n[03:30.690]目の前に広がるヒカリの先へ\n[03:36.400]未来のSunshine\n[03:38.840]輝くSunshine\n[03:41.520]You know it's hard,just take a chance.\n[03:43.200]信じて\n[03:44.829]明日も晴れるかな?\n";
  var lyrics = LyricUtil.formatLyric(songLyc);

3.new LyricWidget

    var lyricWidget = LyricWidget(
                    size: Size(double.infinity, double.infinity),
                    lyrics: lyrics,
                    controller: controller,
                  );

API

LyricWidget

Constructor

parameterDefaultsdescribe
lyrics The lyrics list is converted using LyricUtil.formatLyric
remarkLyrics The lyrics list is converted using LyricUtil.formatLyric
size Lyrics layout size
controller Lyric controller to control progress, drag, animation
lyricStyleColors.grey, fontSize: 14Lyric style
currLyricStyleColors.red, fontSize: 14Currently playing lyric style
remarkStyleColors.black, fontSize: 14Transliteration/Translation Lyrics Style
currRemarkLyricStylecurrLyricStyleCurrent transliteration/translation lyrics style
draggingLyricStylelyricStyleSwipe the selected lyric style
draggingRemarkLyricStyleremarkStyleSlide the selected transliteration/translation lyrics style
enableDragtrueWhether to enable drag
LyricGap10distance between lyrics and bottom
remarkLyricGap20Space between transliteration/translation lyrics and bottom
lyricMaxWidth Lyrics Max Width

LyricControll

Constructor

parameterDefaultsdescribe
vsyncnullPass in the page object, which will contain animation when switching progress
draggingTimerDurationseconds: 3The lyrics list is converted using LyricUtil.formatLyric

APIs

Parameters/MethodsDefaultsdescribe
progress0Set the current progress through this parameter
isDraggingfalseUsed to determine whether the current drag
draggingComplete Move lyrics to sliding position
draggingProgress The current time to swipe to the lyrics

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add mmoo_lyric

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  mmoo_lyric: ^1.0.0

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:mmoo_lyric/lyric.dart';
import 'package:mmoo_lyric/lyric_controller.dart';
import 'package:mmoo_lyric/lyric_painter.dart';
import 'package:mmoo_lyric/lyric_util.dart';
import 'package:mmoo_lyric/lyric_widget.dart'; 

Download Details:

Author: ozyl

Source Code: https://github.com/ozyl/flutter_lyric

#flutter #widget 

A Widget for Flutter to Display Lyrics

Custom Expansion Tile Widget with Flutter

CustomExpansionTileWidget

A CustomExpansionTileWidget is An edited version of Expansion Tile that allows you customize header tile and expanded list.

Example

CustomExpansionTileWidget(
        headerTitle: "Overview",
        headerDecoration: BoxDecoration(
          borderRadius: BorderRadius.all(Radius.circular(12)),
          border: Border.all(color: Colors.blueAccent),
          color: Colors.yellow
          ),
        children: [
          Container(
            height: 50,
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black),
              color: Colors.green,
            ),
            child: const Center(
              child: Text("List1"),
            ),
          ),
          Container(
            height: 50,
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black),
              color: Colors.red,
            ),
            child: const Center(
              child: Text("List2"),
            ),
          ),
          Container(
            height: 50,
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black),
              color: Colors.blueAccent,
            ),
            child: const Center(
              child: Text("List3"),
            ),
          ),
          Container(
            height: 50,
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black),
              color: Colors.orangeAccent,
            ),
            child: const Center(
              child: Text("List4"),
            ),
          ),
        ],
      ),

Parameters

AttributeData typeDescription
headerLeadingWidget?A widget to display before the title
headerTitleStringPrimary title for List view
headerDecorationDecoration?It allows you to decorate the header tile
headerPaddingEdgeInsets?Specifies padding for header tile
headerHeightdouble?height parameter for Header tile ,default height is 50px
headerTextStyleTextStyle?It allows you to customize default style of headerTitle
onExpansionChangedValueChangedWhen the widget starts expanding, this function is called with the value true. When the tile starts collapsing, this function is called with the value false
childrenListThe widgets that are displayed when the tile expands
headerTileColorColor?The color of the header tile
headerTrailingWidget?A widget to display after the headerTitle
isHeaderTrailingAnimationbooldefault animation added to headerTrailing Widget if it is true.
initiallyExpandedboolSpecifies if the expansionWidget is initially expanded (true) or collapsed, default is false
animationDurationDuration?The length of time of animation ,default is 200 ms

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add expansion_tile_widget

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  expansion_tile_widget: ^0.0.1

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:expansion_tile_widget/expansion_tile_widget.dart'; 

example/lib/main.dart

import 'package:expansion_tile_widget/expansion_tile_widget.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Padding(
      padding: const EdgeInsets.symmetric(vertical: 100, horizontal: 50),
      child: CustomExpansionTileWidget(
        headerTitle: "Overview",
        headerDecoration: BoxDecoration(
            borderRadius: BorderRadius.all(Radius.circular(12)),
            border: Border.all(color: Colors.blueAccent),
            color: Colors.yellow),
        children: [
          Container(
            height: 50,
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black),
              color: Colors.green,
            ),
            child: const Center(
              child: Text("List1"),
            ),
          ),
          Container(
            height: 50,
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black),
              color: Colors.red,
            ),
            child: const Center(
              child: Text("List2"),
            ),
          ),
          Container(
            height: 50,
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black),
              color: Colors.blueAccent,
            ),
            child: const Center(
              child: Text("List3"),
            ),
          ),
          Container(
            height: 50,
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black),
              color: Colors.orangeAccent,
            ),
            child: const Center(
              child: Text("List4"),
            ),
          ),
        ],
      ),
    ) // This trailing comma makes auto-formatting nicer for build methods.
        );
  }
} 

Download Details:

Author: srtraj

Source Code: https://github.com/srtraj/expansion_tile_widget

#flutter #widget 

Custom Expansion Tile Widget with Flutter

A Tag for any Given Widget with Flutter

Introduction

Tag is a widget that simplify the process of creating a tag for any given widget. Just pass the string of the tag and Tag widget will position the tag above the desired widget.

Basic Usage

The most simple usage is just wrap the widget that you want to be tagged in a Tag widget.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        body: Center(
          child: Tag(
            child: Container(
              color: Colors.red,
              height: 200,
              width: 200,
            ),
            text: 'A red container',
            textStyle: TextStyle(
              color: Colors.white,
            ),
            color: Color(0xFFFF2D92),
            labelDecoration: BoxDecoration(
              borderRadius: BorderRadius.only(
                bottomLeft: Radius.circular(4),
                bottomRight: Radius.circular(4),
                topLeft: Radius.circular(4),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

This simple step will already configure the Tag overlay for use.

The example will produce something like this:

enter image description here

You can use Tag widget with any widget of your choice. Here we have another example using a CircleAvatar.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        body: Center(
          child: Tag(
            rightPadding: 12,
            child: CircleAvatar(
              backgroundImage: NetworkImage(
                  'https://t1.gstatic.com/images?q=tbn:ANd9GcSZqF3OGhXYqL8DSbLynQ-qA2EIniPAljZXhUTZ8Ay6f6g-um21wsmJsBkeLkjW'),
            ),
            text: 'Lewis Hamilton',
            textStyle: TextStyle(
              color: Colors.white,
            ),
            color: Colors.grey,
            labelDecoration: BoxDecoration(
              borderRadius: BorderRadius.only(
                bottomLeft: Radius.circular(4),
                bottomRight: Radius.circular(4),
                topLeft: Radius.circular(4),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

And produces this:

enter image description here

Customisation

There are many types of configurations that can be done to the Tag widget. You can configure spacing, tag decoration and much more. Just check the Tag constructor to see all possibilities. Missing any customisation? Please file a bug and i will be more than happy to work on it.

Todo

  • Tests
  • Add more options to the tip of the Tag

Suggestions & Bugs

For any suggestions or bug report please head to issue tracker.

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add tag

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  tag: ^2.0.0+2

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:tag/tag.dart'; 

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:tag/tag.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: Scaffold(
        body: Center(
          child: Tag(
            child: Container(
              color: Colors.red,
              height: 200,
              width: 200,
            ),
            text: 'A red container',
            textStyle: TextStyle(
              color: Colors.white,
            ),
            color: Color(0xFFFF2D92),
            labelDecoration: BoxDecoration(
              borderRadius: BorderRadius.only(
                bottomLeft: Radius.circular(4),
                bottomRight: Radius.circular(4),
                topLeft: Radius.circular(4),
              ),
            ),
          ),
        ),
      ),
    );
  }
} 

Download Details:

Author: rodrigobastosv

Source Code: https://github.com/rodrigobastosv/tag

#flutter #tag #widget 

 A Tag for any Given Widget with Flutter

A Flutter Package for Creating A Slider Button Widget

Slider Button v2.0.0

This package provides an easy implementation of a Slider Button to cancel current transaction or screen. Highly customizable iphone alike looking widget.

Null safety supported

How to use

Type 1

This is a Circle type widget. You just need to define the border radius to swap between rectangle and circle type widget.

import 'package:slider_button/slider_button.dart';

Center(child: SliderButton(
      action: () {
        ///Do something here
        Navigator.of(context).pop();
      },
       label: Text(
          "Slide to cancel Event",
          style: TextStyle(
              color: Color(0xff4a4a4a), fontWeight: FontWeight.w500, fontSize: 17),
        ),
      icon: Text(
        "x",
        style: TextStyle(
          color: Colors.white,
          fontWeight: FontWeight.w400,
          fontSize: 44,
        ),
      ),


    ));

Type 2

This is a Rectangle type widget.

import 'package:slider_button/slider_button.dart';

SliderButton(
      action: () {
        ///Do something here OnSlide
      },

      ///Put label over here
      label: Text(
        "Slide to cancel !",
        style: TextStyle(
            color: Color(0xff4a4a4a),
            fontWeight: FontWeight.w500,
            fontSize: 17),
      ),
      icon: Center(
          child: Icon(
        Icons.power_settings_new,
        color: Colors.white,
        size: 40.0,
        semanticLabel: 'Text to announce in accessibility modes',
      )),

      ///Change All the color and size from here.
      width: 230,
      radius: 10,
      buttonColor: Color(0xffd60000),
      backgroundColor: Color(0xff534bae),
      highlightedColor: Colors.white,
      baseColor: Colors.red,
    );

Custom Usage

There are several options that allow for more control:

PropertiesDefaultDescription
actionnull(required) Define an action after slidding a button
childnullFor more customizable button add your own widget
vibrationFlagfalsecontrols vibration on successful dismissed
heightnull ?? 70Gives a height to a widget
widthnull ?? 250Gives a width to a widget
backgroundColorColor(0xffececec)Gives a background color to a widget
baseColorColor(0xff4a4a4a)Gives a shimmer base color to a widget
highlightedColorColors.whiteGives a shimmer highlighted color to a widget
buttonColorColors.blackGives a color to a slidder button
labelnullA text widget which assigns a label.
alignLabelAlignment(0.4, 0)Aligns text label
boxShadownullGives a shadow to a slidder button
iconnullA widget to provide an icon to a button
shimmerfalseenables/disables shimmer effect on the label
dismissibletrueMake it false if you want maintain the widget in the tree
buttonSizenull ?? 60Gives size to a button
dismissThresholds1.0The offset threshold when it should be considered dismissed



 

👍 Contribution

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -m 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add slider_button

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  slider_button: ^2.0.0

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:slider_button/slider_button.dart'; 

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:slider_button/slider_button.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: MainApp());
  }
}

class MainApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    return Scaffold(
        body: Center(
            child: SliderButton(
      action: () {
        ///Do something here OnSlide
        print("working");
      },
      ///Put label over here
      label: Text(
        "Slide to cancel !",
        style: TextStyle(
            color: Color(0xff4a4a4a),
            fontWeight: FontWeight.w500,
            fontSize: 17),
      ),
      icon: Center(
          child: Icon(
        Icons.power_settings_new,
        color: Colors.white,
        size: 40.0,
        semanticLabel: 'Text to announce in accessibility modes',
      )),

      //Put BoxShadow here
      boxShadow: BoxShadow(
        color: Colors.black,
        blurRadius: 4,
      ),

      //Adjust effects such as shimmer and flag vibration here
      shimmer: true,
      vibrationFlag: true,

      ///Change All the color and size from here.
      width: 230,
      radius: 10,
      buttonColor: Color(0xffd60000),
      backgroundColor: Color(0xff534bae),
      highlightedColor: Colors.white,
      baseColor: Colors.red,
    )));
  }
} 

Download Details:

Author: anirudhsharma392

Source Code: https://github.com/anirudhsharma392/Slider-Button

#flutter #widget #slider 

A Flutter Package for Creating A Slider Button Widget

Detects Your Widget Appear or Disappear From Your Screen

Focus Detector

Get notified every time your widget appears or disappears from the screen.

Similar to onResume()/onPause() on Android and viewDidAppear()/viewDidDisappear() on iOS.

Focus Detector fires callbacks for you whenever something happens to take or give your widget focus. Such an event might be, for instance, the user:

  • Navigating to/from another screen;
  • Turning the device’s screen on/off while your widget is visible;
  • Switching to/from another app while your widget is visible;
  • Scrolling your widget in/out the screen;

Usage

@override
Widget build(BuildContext context) =>
    FocusDetector(
      onFocusLost: () {
        logger.i(
          'Focus Lost.'
          '\nTriggered when either [onVisibilityLost] or [onForegroundLost] '
          'is called.'
          '\nEquivalent to onPause() on Android or viewDidDisappear() on iOS.',
        );
      },
      onFocusGained: () {
        logger.i(
          'Focus Gained.'
          '\nTriggered when either [onVisibilityGained] or [onForegroundGained] '
          'is called.'
          '\nEquivalent to onResume() on Android or viewDidAppear() on iOS.',
        );
      },
      onVisibilityLost: () {
        logger.i(
          'Visibility Lost.'
          '\nIt means the widget is no longer visible within your app.',
        );
      },
      onVisibilityGained: () {
        logger.i(
          'Visibility Gained.'
          '\nIt means the widget is now visible within your app.',
        );
      },
      onForegroundLost: () {
        logger.i(
          'Foreground Lost.'
          '\nIt means, for example, that the user sent your app to the background by opening '
          'another app or turned off the device\'s screen while your '
          'widget was visible.',
        );
      },
      onForegroundGained: () {
        logger.i(
          'Foreground Gained.'
          '\nIt means, for example, that the user switched back to your app or turned the '
          'device\'s screen back on while your widget was visible.',
        );
      },
      child: Container(),
    );

Usage Scenarios

  • Turn on and off resource-consuming features, such as camera, location or bluetooth;
  • Sync your data with a remote API or local database;
  • Pause and resume video/audio playback or streaming;

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add pb_focus_detector

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  pb_focus_detector: ^1.0.0

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:pb_focus_detector/pb_focus_detector.dart'; 

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
import 'package:pb_focus_detector/pb_focus_detector.dart';
class FocusDetectorExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) => FocusDetector(
        onFocusLost: () {
          logger.i(
            'Focus Lost.'
            '\nTriggered when either [onVisibilityLost] or [onForegroundLost] '
            'is called.'
            '\nEquivalent to onPause() on Android or viewDidDisappear() on '
            'iOS.',
          );
        },
        onFocusGained: () {
          logger.i(
            'Focus Gained.'
            '\nTriggered when either [onVisibilityGained] or '
            '[onForegroundGained] '
            'is called.'
            '\nEquivalent to onResume() on Android or viewDidAppear() on iOS.',
          );
        },
        onVisibilityLost: () {
          logger.i(
            'Visibility Lost.'
            '\nIt means the widget is no longer visible within your app.',
          );
        },
        onVisibilityGained: () {
          logger.i(
            'Visibility Gained.'
            '\nIt means the widget is now visible within your app.',
          );
        },
        onForegroundLost: () {
          logger.i(
            'Foreground Lost.'
            '\nIt means, for example, that the user sent your app to the '
            'background by opening another app or turned off the device\'s '
            'screen while your widget was visible.',
          );
        },
        onForegroundGained: () {
          logger.i(
            'Foreground Gained.'
            '\nIt means, for example, that the user switched back to your app '
            'or turned the device\'s screen back on while your widget was '
            'visible.',
          );
        },
        child: Material(
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text(
                  'Send the app to the background or push another page and '
                  'watch the console.',
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    fontSize: 20,
                  ),
                ),
                const SizedBox(
                  height: 20,
                ),
                ElevatedButton(
                  onPressed: () {
                    final route = MaterialPageRoute(
                      builder: (_) => OtherPage(),
                    );
                    Navigator.of(context).push(route);
                  },
                  child: const Text(
                    'PUSH ANOTHER PAGE',
                  ),
                )
              ],
            ),
          ),
        ),
      );
}

class OtherPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(),
        body: const Padding(
          padding: EdgeInsets.all(16),
          child: Center(
            child: Text(
              'Look at the console and return to the first screen.',
              textAlign: TextAlign.center,
              style: TextStyle(
                fontSize: 20,
              ),
            ),
          ),
        ),
      );
}

Logger logger = Logger(
  printer: PrettyPrinter(
    methodCount: 0,
    printTime: false,
  ),
);

void main() {
  runApp(
    MaterialApp(
      home: FocusDetectorExample(),
      theme: ThemeData(),
    ),
  );
} 

Download Details:

Author: 

Source Code: https://pub.dev/packages/pb_focus_detector

#flutter #widget 

Detects Your Widget Appear or Disappear From Your Screen

A Flutter Package That Allows You to Search for Place Name

mapbox_autocomplete_search_widget

Language: English

mapbox_autocomplete_search_widget

MapboxAutocompleteSearchWidget is a flutter package that allows you to search for place name in a autocomplete fashion.

Technical Notes: The search is carried out only when search text length is greater than 2 and also a delay of 1 second is added before placing a server call. (Since user types continuously, unnessarry calls will be made to server. So we make the call with 1 second delay after user has stopped typing.)

The package uses Riverpod for state management. So Please ensure you import flutter_riverpod and wrap the app with ProviderScope.

import 'package:flutter_riverpod/flutter_riverpod.dart';

  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );

To use this Package, Please get the Access-Token from here https://docs.mapbox.com/help/glossary/access-token/

The Package has necessarry attributions to Mapbox and can doesnot violate mapbox Terms and Conditions.

How to use it.

the usage is very simple, just use the following

  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
  MapboxAutocompleteSearchWidget(
      onPlaceSelected: (BuildContext context, Place place) {
        
      },
      mapboxApiKey: 'mapboxApiKey',
    ),

parameters

parameterdescriptionvalue
onPlaceSelectedCompletion Handler which returns a BuildContext and selected place from picker(BuildContext context, Place place) {}
mapboxApiKeyYour Mapbox ApiKey (Auth-Token)ApiKey Value
appBarColorColor of App Bar widgetThis is a optional parameter
backButtonColorColor of back arrow buttonThis is a optional parameter
infoButtonColorColor of mapbox info buttonThis is a optional parameter
clearButtonColorColor of clear button in Search widgetThis is a optional parameter
cursorColorColor of cursor in Search widgetThis is a optional parameter
searchTextColorColor of Text in Search widgetThis is a optional parameter
searchBackgroundColorColor of Search area backgroundThis is a optional parameter

git repo here

Made with ❤ and dedicated with respect to the Saviour Sonu Sood

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add mapbox_autocomplete_search_widget

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  mapbox_autocomplete_search_widget: ^0.0.6

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:mapbox_autocomplete_search_widget/mapbox_autocomplete_search_widget.dart'; 

example/lib/main.dart

import 'package:example/example_page_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

//Please generate your Access-Token from here https://docs.mapbox.com/help/glossary/access-token/
void main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.grey,
      ),
      home: ExamplePageWidget(),
    );
  }
} 

Download Details:

Author: TeaTalkInternal

Source Code: https://github.com/TeaTalkInternal/mapbox_autocomplete_search_widget

#flutter #widget 

A Flutter Package That Allows You to Search for Place Name

Framework for Modularizing and Reusing For Flutter Widgets

Masamune Framework

Framework for modularizing and reusing not only Flutter widgets, but also models, pages, and the app itself.

The framework itself has the following components.

Package NameDetails
katanaPackage containing a collection of basic Dart utilities. It provides the base part of the Masamune framework.
katana_flutterPackage containing a collection of basic Flutter utilities. It provides the base part of the Masamune framework.
katana_routingPackage for routing. It supports page creation and page routing. And other extension methods of BuildContext.
katana_modulePackage that defines a base class for modularization. It defines abstract classes, etc. for use with the Masamune module.
model_notifierPackage that makes it easy to define ValueNotifier as a model and improves the affinity with riverpod and freezed.
masamunePackage that supports Flutter states and their transitions using the Model Notifier package and the Katana Routing package.
masamune_uiUI library using Masamune. Please be careful when using it normally, as it uses multiple external packages.
masamune_modulePackage in which various functions are modularized. The katana_routing routing system is used on the assumption that Riverpod is used.

The following plug-ins are additionally loaded depending on the functions used by the application.

Basically, you can pass the Adapter as a module to UIModuleMaterialApp to use additional functionality.

Package NameDetails
katana_firebaseKatana package that provides utilities for firebase. It initializes Firebase and so on.
firebase_model_notifierModelNotifier package for Firebase. When you listen in Firestore, you can tell riverpod and others about the update.
masamune_firebaseModule for supporting the Firebase/Firestore function of Masamune framework. It is also available on the web.
masamune_purchasePackage to provide mobile billing functionality. It is equipped with functions to perform all billing on the client without server verification, etc.
masamune_purchase_firebasePlugin that extends the billing system plugin to the processing by the server (Firebase). Firebase Functions are required.

Documentation

License


Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add masamune_signin_facebook

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  masamune_signin_facebook: ^0.15.0+25

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:masamune_signin_facebook/masamune_signin_facebook.dart'; 

Download Details:

Author: mathrunet

Source Code: https://github.com/mathrunet/flutter_masamune/tree/master/packages/masamune_signin_facebook

#flutter #android #widget 

Framework for Modularizing and Reusing For Flutter Widgets

A simple Text Widget with Flutter

Bye Bye Localization 👋

Its just a simple Text widget that will provide automatic fast translation for any text. it supports 59 languages.

No more boring Localization configuration files, all you have to do is change your old Text() widget to TranslatedText() and enjoy the sweet sweet life without Localization

PS: the translation will be fast as it uses translation model deployed to the device under the hood.

Demo 📹

Demo

How to use ?

Step 1: All you have to do is call the widget

TranslatedText('your text')

Step2: don't forget to call init the widget using the Manager

  Future<bool> initWidget() async {
    return await TranslationManager().init(
      originLanguage: Languages.ENGLISH,
      translateToLanguage: Languages.ARABIC,
    );
  } 

Step 3: Buy me Coffee 🙂! ☕️

Buy Me a Coffee

Quick example ⚡️

Widget buildWidget(){
    return FutureBuilder(
      future: initTranslation(),
      builder: (context, snapshot) {
        if (snapshot.hasError) {
          return Text('${snapshot.error}');
        }
        if (snapshot.connectionState == ConnectionState.done) {
          return TranslatedText('I am a text that will be translated always');
        }
        return CircularProgressIndicator();
      },
    );
  }
  Future<bool> initWidget() async {
    return await TranslationManager().init(
      originLanguage: Languages.ENGLISH,
      /// Change here the language to change the translation, and re run.
      /// For example Languages.RUSSIAN.
      translateToLanguage: Languages.ARABIC,
    );
  }

Live Demo 🔆

below you will find a link to APK contains live demo

Download APK

Author ✍️

Muwaffaq Imam

  • Edu email : m.imam@innopolis.university
  • Telegram : moofiy

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add bye_bye_localization

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  bye_bye_localization: ^1.0.0+8

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:bye_bye_localization/bye_bye_localization.dart'; 

example/lib/main.dart

import 'dart:ui' as ui;

import 'package:bye_bye_localization/bye_bye_localization.dart';
import 'package:flutter/material.dart';
import 'dart:async';

void main() => runApp(PdfExtractionMain());

class PdfExtractionMain extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: PdfExtraction(),
    );
  }
}

class PdfExtraction extends StatefulWidget {
  @override
  _PdfExtractionState createState() => _PdfExtractionState();
}

class _PdfExtractionState extends State<PdfExtraction> {
  static final String _startingText =
      "A simple Text Widget, that can translate any text to any language using instant on device translation AI model, all you have to do is to provide the text and the widget will translate automatically, as a result you don't have to specify and localization files and type translation manually the widget will do it for you.";
  String _text = _startingText;
  Map<String, String>? originLanguage = {'ENGLISH': "en"};
  Map<String, String>? translateTo;
  bool _translate = true;
  bool textDirection = false;


  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title:  TranslatedText(
            'Bye Bye Localization',
            style: TextStyle(fontSize: 24),
          ),
        ),
        body:
        FutureBuilder(
          // Initialize FlutterFire:
          future: initTranslation(),
          builder: (context, snapshot) {
            // Check for errors
            if (snapshot.hasError) {
              return Text('${snapshot.error}');
            }

            // Once complete, show your application
            if (snapshot.connectionState == ConnectionState.done) {
              return buildBody();
            }

            // Otherwise, show something whilst waiting for initialization to complete
            return Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Center(
                    child: RichText(
                      text: TextSpan(
                        text:
                            'Translating  from ${originLanguage!.keys.first} to ${translateTo == null ? Localizations.localeOf(context).languageCode : translateTo!.keys.first} \n',
                        style: TextStyle(fontSize: 30, color: Colors.black),
                        children: const <TextSpan>[
                          TextSpan(
                              text: 'this might take a while... \n',
                              style: TextStyle(
                                  fontWeight: FontWeight.bold, fontSize: 20)),
                          TextSpan(
                              text:
                                  'because we are downloading an AI model to translate through it,'
                                  ' once finished you will see an incredible thing, I PROMISE... \n ',
                              style: TextStyle(
                                  fontWeight: FontWeight.bold, fontSize: 16)),
                          TextSpan(
                              text:
                                  '  so say Astaghfer Allah in this time time!',
                              style: TextStyle(
                                  fontFamily: 'casual', fontSize: 30)),
                        ],
                      ),
                    ),
                  ),
                  CircularProgressIndicator(
                    strokeWidth: 5,
                  ),
                ],
              ),
            );
          },
        )
    );
  }

  TextEditingController _controller = new TextEditingController();

  Container buildBody() {
    return Container(
      padding: EdgeInsets.all(10),
      child: ListView(
        primary: true,
        shrinkWrap: true,
        children: <Widget>[
          ListTile(
            onTap: () {
              buildModelSheet().then((value) {
                setState(() {
                  translateTo = value;
                });
              });
            },
            leading: Icon(Icons.translate),
            trailing: Icon(Icons.arrow_forward_ios_rounded),
            title: Text(
              "tap to Change Local",
              style: TextStyle(color: Colors.black),
            ),
            subtitle: translateTo != null
                ? Text('${translateTo!.keys.first}')
                : Text('current local is -->'
                    '${LanguageHelper.languages.firstWhere(
                          (k) =>
                              k.values.first == ui.window.locale.languageCode,
                        ).keys.first}'),
          ),
          Divider(),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 8.0),
            child: TextFormField(
              controller: _controller,
              decoration: const InputDecoration(
                icon: Icon(Icons.edit_rounded),
                hintText: 'Write any text then press translate',
              ),
            ),
          ),
          TextButton(
            child: TranslatedText(
              "Translate the text",
              style: TextStyle(color: Colors.white),
            ),
            style: TextButton.styleFrom(
                padding: EdgeInsets.all(5), backgroundColor: Colors.blueAccent),
            onPressed: () {
              setState(() {
                _translate = true;
                _text = _controller.text.isNotEmpty
                    ? _controller.text
                    : _startingText;
              });
            },
          ),
          TextButton(
            child: TranslatedText(
              "Change Text direction",
              style: TextStyle(color: Colors.white),
            ),
            style: TextButton.styleFrom(
                padding: EdgeInsets.all(5), backgroundColor: Colors.blueAccent),
            onPressed: () {
              setState(() {
                textDirection = !textDirection;
              });
            },
          ),
          TextButton(
            child: Text(
              _translate ? "Show Original language" : "Show translation",
              style: TextStyle(color: Colors.white),
            ),
            style: TextButton.styleFrom(
                padding: EdgeInsets.all(5), backgroundColor: Colors.blueAccent),
            onPressed: () {
              setState(() {
                _translate = !_translate;
              });
            },
          ),
          TextButton(
            child: TranslatedText(
              'Reset text',
              style: TextStyle(color: Colors.white),
            ),
            style: TextButton.styleFrom(
                padding: EdgeInsets.all(5), backgroundColor: Colors.blueAccent),
            onPressed: () {
              setState(() {
                _text = _startingText;
              });
            },
          ),
          _translate
              ? TranslatedText(_text,
                  textDirection:
                      textDirection ? TextDirection.ltr : TextDirection.rtl,
                  style: TextStyle(
                    fontSize: 18,
                  ))
              : Text(
                  _text,
                  textDirection:
                      textDirection ? TextDirection.ltr : TextDirection.rtl,
                  style: TextStyle(
                    fontSize: 18,
                  ),
                ),
        ],
      ),
    );
  }

  Future<bool> initTranslation() async {
    Locale myLocale = Localizations.localeOf(context);
    print('myLocale.languageCode ${ui.window.locale.languageCode}');
    return await TranslationManager().init(
        translateToLanguage: translateTo == null
            ? ui.window.locale.languageCode
            : translateTo!.values.first,
        originLanguage: originLanguage!.values.first);
  }

  Future<bool> initWidget() async {
    return await TranslationManager().init(
      originLanguage: Languages.ENGLISH,
      translateToLanguage: Languages.ARABIC,
    );
  }

  Future<Map<String, String>?> buildModelSheet() async {
    return await showModalBottomSheet<Map<String, String>>(
      enableDrag: true,
      context: context,
      builder: (BuildContext context) {
        return Container(
          height: 400,
          color: Colors.amberAccent,
          child: Center(
            child: ListView.builder(
              itemCount: LanguageHelper.languages.length,
              itemBuilder: (BuildContext context, int index) {
                return Column(
                  children: [
                    ListTile(
                      onTap: () {
                        Navigator.pop(context, LanguageHelper.languages[index]);
                      },
                      title: Text(
                        '${LanguageHelper.languages[index].keys.first}',
                        style: TextStyle(fontSize: 16),
                      ),
                    ),
                    Divider(),
                  ],
                );
              },
            ),
          ),
        );
      },
    );
  }
} 

Download Details:

Author: MuwaffaqImam

Source Code: https://github.com/MuwaffaqImam/bye-bye-localization

#flutter #widget 

A simple Text Widget with Flutter