Skip to content

Commit

Permalink
Pre-release of first version - 1.0.0-nullsafety.0
Browse files Browse the repository at this point in the history
  • Loading branch information
matuella committed Feb 24, 2021
1 parent e0d1ba4 commit 20ef041
Show file tree
Hide file tree
Showing 111 changed files with 1,685 additions and 1,081 deletions.
47 changes: 47 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"version": "0.3.0",
"configurations": [
{
"name": "Common Layout | Inherited Widget",
"type": "dart",
"request": "launch",
"program": "example/lib/common_layout/inherited_widget.dart",
},
{
"name": "Common Layout | Override Inherited Widget",
"type": "dart",
"request": "launch",
"program": "example/lib/common_layout/override_inherited_widget.dart",
},
{
"name": "Custom Layout",
"type": "dart",
"request": "launch",
"program": "example/lib/custom_layout/main.dart",
},
{
"name": "Granular Layout | Override Inherited Widget",
"type": "dart",
"request": "launch",
"program": "example/lib/granular_layout/override_inherited_widget.dart",
},
{
"name": "Granular Layout | Override Inherited Widget",
"type": "dart",
"request": "launch",
"program": "example/lib/granular_layout/override_inherited_widget.dart",
},
{
"name": "Provider",
"type": "dart",
"request": "launch",
"program": "example/lib/provider.dart",
},
{
"name": "Riverpod",
"type": "dart",
"request": "launch",
"program": "example/lib/river_pod.dart",
},
]
}
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"editor.formatOnSave": true,
"dart.lineLength": 120,
"editor.rulers": [120]
}
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## [0.0.1] - TODO: Add release date.
## [1.0.0-nullsafety.0]

* TODO: Describe initial release.
First library release, everything already documented in `README.md`.

For a stable release, just the tests and a little improvement on examples remains.
153 changes: 129 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,129 @@
# responsive_layout

A new Flutter package project.

## Getting Started

TODO:
- [] rename examples;
- [] `granular_layout` sub-package;
- Add granular examples to pre-existing ones.
- [] In-depth usage example;
- [] Multiple resolvers example;
- [] lint + vscode + strict;
- [] README/Contributing/Changelog/Architecture;
- [] Unit/Integration tests.

This project is a starting point for a Dart
[package](https://flutter.dev/developing-packages/),
a library module containing code that can be shared easily across
multiple Flutter or Dart projects.

For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
# layoutr

[![pub package](https://img.shields.io/pub/v/layoutr?style=flat-square)](https://pub.dev/packages/layoutr)

A set of succinct Dart/Flutter utilities to help doing responsive layouts with less verbosity.

## Why

There are already a ton of layout/UI libraries out there and this is just another one to solve the same problem: responsive layouts.

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.

## Usage

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:

### Layout Resolvers

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.

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".

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.

#### Exemplifying with CommonLayout

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:
```dart
import 'package:layoutr/common_layout.dart';
// ...
Widget build(BuildContext context) {
final layout = context.commonLayout;
final textTheme = Theme.of(context).textTheme;
return layout.value(
desktop: () => Text('Desktop layout', style: textTheme.headline1),
phone: () => Text('Phone layout', style: textTheme.headline4),
tinyHardware: () => Text('Tiny Hardware layout', style: textTheme.headline6),
);
}
// ...
```

> 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`
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`:

```dart
import 'package:layoutr/common_layout.dart';
// ...
CommonLayoutWidget(
resolver: CommonLayout(context.deviceWidth, desktop: 800),
child: /* My child */,
);
// ...
```

> 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.
Other than `layout.value`, the `CommonLayout` provide utilities for simple boolean comparisons:

```dart
import 'package:layoutr/common_layout.dart';
// ...
Widget build(BuildContext context) {
final layout = context.commonLayout;
const pageTitle = 'Title';
final myAppBar = layout.isTabletOrSmaller ? AppBar(title: const Text(pageTitle)) : null;
return Scaffold(
// We wan't to have an `AppBar` if the current layout is a tablet or smaller
appBar: myAppBar,
body: Center(
child: Column(
children: [
// And we wan't to have a custom title `AppBar` if the current layout is a tablet or smaller
if (layout.isDesktop)
Padding(
padding: const EdgeInsets.only(bottom: 40),
child: Text(pageTitle, style: Theme.of(context).textTheme.headline3),
),
// ... the rest of the widget
],
),
),
);
}
// ...
```

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`)).

#### Available Built-in `LayoutResolver`
- `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));
- `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)).

### Custom `LayoutResolver`

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).

### Utilities

- Syntax-sugar for common use-cases, like: `deviceWidth` and `deviceHeight` (plus a couple more that are WIP);
- Other helper Widgets are WIP.

## Reference OS Projects

List of open source projects that use this package and can be used as a reference to implement your own use-cases:

WIP

## Contributing

There is no rocket science to contributing to this project. Just open your issue or pull request if needed - but please be descriptive!

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.

Even though there is no "rules" to how you should contribute, there goes my quick tips on it:

- If you're experiencing a bug that can be demonstrated visually, please take screenshots and post them alongside the issue;
- For a quicker/seamless understanding of the issue, please post a sample project, so the evaluation will be bulletproof;
- This is a git overall tip - do atomic commits with a descriptive message (no more than 50 characters is ideal).
1 change: 1 addition & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include: package:strict/analysis_options.yaml
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.

version:
revision: 5d36f2e7f5387b6c751449258ade8e4e6edf99be
revision: 48c9d3e0e19e8fec84f1d316ce0559f26ca7277d
channel: beta

project_type: app
58 changes: 58 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# layoutr_example

A list of implementation examples in common use-cases and built-in resolvers of `layoutr`.

## Examples

### Common Layout

Other than the specific usage of the class, you can see that:
- `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;
- `DetailsPage` implementation exemplifies a "Hybrid" Widget approach - meaning that we have the same entry-point (in
this case, the `build` function) to fit all of our use cases.

#### Common Layout Inherited Widget

Example entry-point: `lib/common_layout/inherited_widget.dart`.

Shows the "default" usage of the `CommonLayout`, nothing else.

#### Common Layout Override Inherited Widget

Example entry-point: `lib/common_layout/override_inherited_widget.dart`.

Overrides the default behavior of the `CommonLayoutWidget` by adding our own custom `CommonLayout`, with the desired
changes to the breakpoints values.

### Granular Layout

Read the [Common Layout](#Common-Layout) approach that is also used in this example.

#### Granular Layout Inherited Widget

Example entry-point: `lib/granular_layout/inherited_widget.dart`.

Shows the "default" usage of the `GranularLayout`, nothing else.

#### Granular Layout Override Inherited Widget

Example entry-point: `lib/granular_layout/override_inherited_widget.dart`.

Overrides the default behavior of the `GranularLayoutWidget` by adding our own custom `GranularLayout`, with the desired
changes to the breakpoints values.

### Custom Layout

Extends the `LayoutResolver` to create a completely custom resolver and passes it down through the widget tree.

### `provider`

Example entry-point: `lib/provider.dart`.

Uses the `provider` package to _provide_ a layout resolver through the widget's tree.

### `river_pod`

Example entry-point: `lib/river_pod.dart`.

Uses the `river_pod` package to _provide_ a layout resolver through the widget's tree.
1 change: 1 addition & 0 deletions example/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include: package:strict/analysis_options.yaml
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ android {

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.no_package_example"
applicationId "com.example.layoutr_example"
minSdkVersion 16
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.no_package_example">
package="com.example.layoutr_example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.no_package_example">
package="com.example.layoutr_example">
<application
android:label="no_package_example"
android:label="layoutr_example"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.no_package_example
package com.example.layoutr_example

import io.flutter.embedding.android.FlutterActivity

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.no_package_example">
package="com.example.layoutr_example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions example/ios/Flutter/Debug.xcconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "Generated.xcconfig"
1 change: 1 addition & 0 deletions example/ios/Flutter/Release.xcconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "Generated.xcconfig"
Loading

0 comments on commit 20ef041

Please sign in to comment.