Skip to content

Commit 20ef041

Browse files
committed
Pre-release of first version - 1.0.0-nullsafety.0
1 parent e0d1ba4 commit 20ef041

File tree

111 files changed

+1685
-1081
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+1685
-1081
lines changed

.vscode/launch.json

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"version": "0.3.0",
3+
"configurations": [
4+
{
5+
"name": "Common Layout | Inherited Widget",
6+
"type": "dart",
7+
"request": "launch",
8+
"program": "example/lib/common_layout/inherited_widget.dart",
9+
},
10+
{
11+
"name": "Common Layout | Override Inherited Widget",
12+
"type": "dart",
13+
"request": "launch",
14+
"program": "example/lib/common_layout/override_inherited_widget.dart",
15+
},
16+
{
17+
"name": "Custom Layout",
18+
"type": "dart",
19+
"request": "launch",
20+
"program": "example/lib/custom_layout/main.dart",
21+
},
22+
{
23+
"name": "Granular Layout | Override Inherited Widget",
24+
"type": "dart",
25+
"request": "launch",
26+
"program": "example/lib/granular_layout/override_inherited_widget.dart",
27+
},
28+
{
29+
"name": "Granular Layout | Override Inherited Widget",
30+
"type": "dart",
31+
"request": "launch",
32+
"program": "example/lib/granular_layout/override_inherited_widget.dart",
33+
},
34+
{
35+
"name": "Provider",
36+
"type": "dart",
37+
"request": "launch",
38+
"program": "example/lib/provider.dart",
39+
},
40+
{
41+
"name": "Riverpod",
42+
"type": "dart",
43+
"request": "launch",
44+
"program": "example/lib/river_pod.dart",
45+
},
46+
]
47+
}

.vscode/settings.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"editor.formatOnSave": true,
3+
"dart.lineLength": 120,
4+
"editor.rulers": [120]
5+
}

CHANGELOG.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
## [0.0.1] - TODO: Add release date.
1+
## [1.0.0-nullsafety.0]
22

3-
* TODO: Describe initial release.
3+
First library release, everything already documented in `README.md`.
4+
5+
For a stable release, just the tests and a little improvement on examples remains.

README.md

+129-24
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,129 @@
1-
# responsive_layout
2-
3-
A new Flutter package project.
4-
5-
## Getting Started
6-
7-
TODO:
8-
- [] rename examples;
9-
- [] `granular_layout` sub-package;
10-
- Add granular examples to pre-existing ones.
11-
- [] In-depth usage example;
12-
- [] Multiple resolvers example;
13-
- [] lint + vscode + strict;
14-
- [] README/Contributing/Changelog/Architecture;
15-
- [] Unit/Integration tests.
16-
17-
This project is a starting point for a Dart
18-
[package](https://flutter.dev/developing-packages/),
19-
a library module containing code that can be shared easily across
20-
multiple Flutter or Dart projects.
21-
22-
For help getting started with Flutter, view our
23-
[online documentation](https://flutter.dev/docs), which offers tutorials,
24-
samples, guidance on mobile development, and a full API reference.
1+
# layoutr
2+
3+
[![pub package](https://img.shields.io/pub/v/layoutr?style=flat-square)](https://pub.dev/packages/layoutr)
4+
5+
A set of succinct Dart/Flutter utilities to help doing responsive layouts with less verbosity.
6+
7+
## Why
8+
9+
There are already a ton of layout/UI libraries out there and this is just another one to solve the same problem: responsive layouts.
10+
11+
This package aims to be a single dependecy to handle responsive use-cases in Flutter applications while keeping the verbosity to a minimum, because we know how quickly verbose (reads harder-to-read) we can get with those Widgets.
12+
13+
## Usage
14+
15+
Before finding out the package's API, make sure to [install this package](https://pub.dev/packages/layoutr/install). With this out of the way, let's get an overview what this package does:
16+
17+
### Layout Resolvers
18+
19+
These are the core layout classes that should make the process of handling multiple-layout widgets much less verbose. We can use these resolvers whenever you have a `BuildContext` (usually in the Widgets `build` function) available.
20+
21+
Even though the magic should happen inside the abstract `LayoutResolver`, we need to extend this class to provide our desired `Breakpoint`s. This is intended due to the fact that there is an incredible amount of use-cases available when building any kind of UI - meaning that these breakpoints are completely subjective, based on each project "constraints".
22+
23+
But that's not any reason to not have built-in Layout Resolvers, and these will probably fit the most generic use-cases. To exemplify the resolvers, we can see how the `CommonLayout` works.
24+
25+
#### Exemplifying with CommonLayout
26+
27+
The `CommonLayout` is split in 4 breakpoints: `desktop`, `tablet`, `phone` and `tinyHardware`. A simple usage of returning a responsive `Text` widget that has both its value and style customized based on the current device's constraints may be done like the below:
28+
```dart
29+
import 'package:layoutr/common_layout.dart';
30+
31+
// ...
32+
33+
Widget build(BuildContext context) {
34+
final layout = context.commonLayout;
35+
final textTheme = Theme.of(context).textTheme;
36+
37+
return layout.value(
38+
desktop: () => Text('Desktop layout', style: textTheme.headline1),
39+
phone: () => Text('Phone layout', style: textTheme.headline4),
40+
tinyHardware: () => Text('Tiny Hardware layout', style: textTheme.headline6),
41+
);
42+
}
43+
// ...
44+
```
45+
46+
> You can see that there is no `tablet` supplied to the `layout.value`, and that is intended to exemplify a common scenario, where we may want to just provide two or three arguments - and that means not all possible scenarios are "covered" - and that's where the resolver comes in handy: if the **current breakpoint** value is not passed to `layout.value`, it will fallback to the "nearest" available one, fitting the most suitable layout for your particular value. This "nearest logic" can be confusing, but you can find out more how it works in `LayoutResolver.closestValue`
47+
48+
Also, if you want to keep the structure but want to override the sizes of each breakpoint, you can provide your `CommonLayout` instance through the InheritedWidget called `CommonLayoutWidget`:
49+
50+
```dart
51+
import 'package:layoutr/common_layout.dart';
52+
53+
// ...
54+
55+
CommonLayoutWidget(
56+
resolver: CommonLayout(context.deviceWidth, desktop: 800),
57+
child: /* My child */,
58+
);
59+
// ...
60+
```
61+
62+
> You will probably want to add these above the top-most widget of your tree, usually the `MaterialApp`, but be careful that `MediaQuery` may not be available if you don't have any other widget above `CommonLayoutWidget`, which is required when we use the `context.deviceWidth`. You can check out an [`example/`](https://pub.dev/packages/layoutr/example#Common-Layout-Inherited-Widget) that overrides the custom values.
63+
64+
Other than `layout.value`, the `CommonLayout` provide utilities for simple boolean comparisons:
65+
66+
```dart
67+
import 'package:layoutr/common_layout.dart';
68+
69+
// ...
70+
71+
Widget build(BuildContext context) {
72+
final layout = context.commonLayout;
73+
const pageTitle = 'Title';
74+
75+
final myAppBar = layout.isTabletOrSmaller ? AppBar(title: const Text(pageTitle)) : null;
76+
77+
return Scaffold(
78+
// We wan't to have an `AppBar` if the current layout is a tablet or smaller
79+
appBar: myAppBar,
80+
body: Center(
81+
child: Column(
82+
children: [
83+
// And we wan't to have a custom title `AppBar` if the current layout is a tablet or smaller
84+
if (layout.isDesktop)
85+
Padding(
86+
padding: const EdgeInsets.only(bottom: 40),
87+
child: Text(pageTitle, style: Theme.of(context).textTheme.headline3),
88+
),
89+
// ... the rest of the widget
90+
],
91+
),
92+
),
93+
);
94+
}
95+
// ...
96+
```
97+
98+
Tip: we can easily use this package with common libraries like `provider` (see in [`example/`](https://pub.dev/packages/layoutr/example#`provider`)) and `river_pod` (see in [`example/`](https://pub.dev/packages/layoutr/example#`river_pod`)).
99+
100+
#### Available Built-in `LayoutResolver`
101+
- `CommonLayout`: a resolver split in 4 breakpoints: `desktop`, `tablet`, `phone` and `tinyHardware`. Import this resolver through `package:layoutr/common_layout.dart` - (see in [`example/`](https://pub.dev/packages/layoutr/example#Common-Layout));
102+
- `GranularLayout`: a resolver split in 6 breakpoints: `xxLarge`, `xLarge`, `large`, `medium`, `small` and `xSmall`. Import this resolver through `package:layoutr/granular_layout.dart` - (see in [`example/`](https://pub.dev/packages/layoutr/example#Granular-Layout)).
103+
104+
### Custom `LayoutResolver`
105+
106+
If the above built-in resolvers don't match the requirements, `LayoutResolver` can be customized by extending it, taking advantage of the utilities built-in in the abstract class itself. To extend the and implement your custom `LayoutResolver`, import `package:layoutr/layoutr.dart`. Check out a custom implementation example in the [`example/`](https://pub.dev/packages/layoutr/example#Custom-Layout).
107+
108+
### Utilities
109+
110+
- Syntax-sugar for common use-cases, like: `deviceWidth` and `deviceHeight` (plus a couple more that are WIP);
111+
- Other helper Widgets are WIP.
112+
113+
## Reference OS Projects
114+
115+
List of open source projects that use this package and can be used as a reference to implement your own use-cases:
116+
117+
WIP
118+
119+
## Contributing
120+
121+
There is no rocket science to contributing to this project. Just open your issue or pull request if needed - but please be descriptive!
122+
123+
To submit a PR, follow [these useful guidelines](https://gist.github.com/MarcDiethelm/7303312), respect the dartfmt lint (modifications/exceptions may be discussed), and create an awesome description so we can understand it.
124+
125+
Even though there is no "rules" to how you should contribute, there goes my quick tips on it:
126+
127+
- If you're experiencing a bug that can be demonstrated visually, please take screenshots and post them alongside the issue;
128+
- For a quicker/seamless understanding of the issue, please post a sample project, so the evaluation will be bulletproof;
129+
- This is a git overall tip - do atomic commits with a descriptive message (no more than 50 characters is ideal).

analysis_options.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include: package:strict/analysis_options.yaml
File renamed without changes.

examples/no_package_example/.metadata renamed to example/.metadata

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# This file should be version controlled and should not be manually edited.
55

66
version:
7-
revision: 5d36f2e7f5387b6c751449258ade8e4e6edf99be
7+
revision: 48c9d3e0e19e8fec84f1d316ce0559f26ca7277d
88
channel: beta
99

1010
project_type: app

example/README.md

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# layoutr_example
2+
3+
A list of implementation examples in common use-cases and built-in resolvers of `layoutr`.
4+
5+
## Examples
6+
7+
### Common Layout
8+
9+
Other than the specific usage of the class, you can see that:
10+
- `HomePage` implementation exemplifies a "Split" Widget approach - meaning that we create private sub-widget for each layout, common in more complex scenarios, to improve the "core" widget readability;
11+
- `DetailsPage` implementation exemplifies a "Hybrid" Widget approach - meaning that we have the same entry-point (in
12+
this case, the `build` function) to fit all of our use cases.
13+
14+
#### Common Layout Inherited Widget
15+
16+
Example entry-point: `lib/common_layout/inherited_widget.dart`.
17+
18+
Shows the "default" usage of the `CommonLayout`, nothing else.
19+
20+
#### Common Layout Override Inherited Widget
21+
22+
Example entry-point: `lib/common_layout/override_inherited_widget.dart`.
23+
24+
Overrides the default behavior of the `CommonLayoutWidget` by adding our own custom `CommonLayout`, with the desired
25+
changes to the breakpoints values.
26+
27+
### Granular Layout
28+
29+
Read the [Common Layout](#Common-Layout) approach that is also used in this example.
30+
31+
#### Granular Layout Inherited Widget
32+
33+
Example entry-point: `lib/granular_layout/inherited_widget.dart`.
34+
35+
Shows the "default" usage of the `GranularLayout`, nothing else.
36+
37+
#### Granular Layout Override Inherited Widget
38+
39+
Example entry-point: `lib/granular_layout/override_inherited_widget.dart`.
40+
41+
Overrides the default behavior of the `GranularLayoutWidget` by adding our own custom `GranularLayout`, with the desired
42+
changes to the breakpoints values.
43+
44+
### Custom Layout
45+
46+
Extends the `LayoutResolver` to create a completely custom resolver and passes it down through the widget tree.
47+
48+
### `provider`
49+
50+
Example entry-point: `lib/provider.dart`.
51+
52+
Uses the `provider` package to _provide_ a layout resolver through the widget's tree.
53+
54+
### `river_pod`
55+
56+
Example entry-point: `lib/river_pod.dart`.
57+
58+
Uses the `river_pod` package to _provide_ a layout resolver through the widget's tree.

example/analysis_options.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include: package:strict/analysis_options.yaml

examples/no_package_example/android/app/build.gradle renamed to example/android/app/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ android {
3434

3535
defaultConfig {
3636
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
37-
applicationId "com.example.no_package_example"
37+
applicationId "com.example.layoutr_example"
3838
minSdkVersion 16
3939
targetSdkVersion 30
4040
versionCode flutterVersionCode.toInteger()

examples/no_package_example/android/app/src/profile/AndroidManifest.xml renamed to example/android/app/src/debug/AndroidManifest.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2-
package="com.example.no_package_example">
2+
package="com.example.layoutr_example">
33
<!-- Flutter needs it to communicate with the running application
44
to allow setting breakpoints, to provide hot reload, etc.
55
-->

examples/no_package_example/android/app/src/main/AndroidManifest.xml renamed to example/android/app/src/main/AndroidManifest.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2-
package="com.example.no_package_example">
2+
package="com.example.layoutr_example">
33
<application
4-
android:label="no_package_example"
4+
android:label="layoutr_example"
55
android:icon="@mipmap/ic_launcher">
66
<activity
77
android:name=".MainActivity"
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.example.no_package_example
1+
package com.example.layoutr_example
22

33
import io.flutter.embedding.android.FlutterActivity
44

examples/no_package_example/android/app/src/debug/AndroidManifest.xml renamed to example/android/app/src/profile/AndroidManifest.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2-
package="com.example.no_package_example">
2+
package="com.example.layoutr_example">
33
<!-- Flutter needs it to communicate with the running application
44
to allow setting breakpoints, to provide hot reload, etc.
55
-->
File renamed without changes.

example/ios/Flutter/Debug.xcconfig

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "Generated.xcconfig"

example/ios/Flutter/Release.xcconfig

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "Generated.xcconfig"

0 commit comments

Comments
 (0)