Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scaling #9

Merged
merged 3 commits into from
Jul 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* feat: `RoundedBackgroundTextField` is now scrollable. The background will follow the scroll of the text field
* feat: Added `.scrollController`, `.scrollPhysics`, `.scrollBehavior` and `.scrollPadding` to `RoundedBackgroundTextField`
* `RoundedBackgroundTextField.controller` is no longer required. If omitted, a local controller is created instead
* Dynamically calculate padding and factors for `RoundedBackgroundText` ([#6](https://github.com/bdlukaa/rounded_background_text/issues/6))

## 0.2.1

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ To paint the background, the line metrics generated before is used. Each line ha

With these values, we can generate the background for each line. The background is generated around the whole text: from top-left to bottom-left to bottom-right to top-right to top-left. This makes it easy to calculate when there is a corner, either outer or inner.

The inner and outer radius are dynamically calculated based on the line height, provided by the line metrics, and the given `innerFactor` and `outerFactor`, respectively. By default, `innerFactor` is `8.0` and `outerFactor` is `10.0`. For safety, in order to keep the roundnesses correct, these values must be in the bounds of `0.0` (min) and `20.0` max, otherwise the painting would go off-line.

## Contribution

Feel free to [file an issue](https://github.com/bdlukaa/rounded_background_text/issues/new) if you find a problem or [make pull requests](https://github.com/bdlukaa/rounded_background_text/pulls).
Expand Down
6 changes: 4 additions & 2 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,10 @@ Done with so much <3 by @bdlukaa''',
child: Slider(
onChanged: (v) => setState(() => fontSize = v),
value: fontSize,
min: 10,
max: 20,
min: 8,
max: 30,
divisions: 30 - 8,
label: '${fontSize.toInt()}',
),
),
Expanded(
Expand Down
149 changes: 83 additions & 66 deletions lib/src/rounded_background_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@ Color? foregroundColor(Color? backgroundColor) {
: Colors.white;
}

/// Calculates the line height based on [fontSize]
double calculateHeight(double fontSize) {
// fontSize * x = fontSize + 14
// x = (fontSize + 14) / fontSize
return (fontSize + 14) / fontSize;
}

List<List<LineMetricsHelper>> generateLineInfosForPainter(
TextPainter painter, [
double maxWidth = double.infinity,
Expand All @@ -49,24 +42,9 @@ List<List<LineMetricsHelper>> generateLineInfosForPainter(
return lineInfos;
}

const singleLinePadding = EdgeInsets.symmetric(horizontal: 8.0, vertical: 8.0);
const firstLinePadding = EdgeInsets.only(
left: 8.0,
right: 8.0,
top: 8.0,
bottom: 0,
);
const innerLinePadding = EdgeInsets.only(
left: 8.0,
right: 8.0,
top: 0.0,
bottom: 4.0,
);
const lastLinePadding = EdgeInsets.only(
left: 8.0,
right: 8.0,
top: 0.0,
bottom: 4.0,
const singleLinePadding = EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 8.0,
);

/// Creates a paragraph with rounded background text
Expand Down Expand Up @@ -290,14 +268,20 @@ class RoundedBackgroundText extends StatelessWidget {
/// {@template rounded_background_text.innerRadius}
/// The radius of the inner corners.
///
/// Defaults to [this.innerFactor]
/// The radius is dynamically calculated based on the line height and the
/// provided factor.
///
/// Defaults to 8.0
/// {@end-template}
final double innerRadius;

/// {@template rounded_background_text.outerRadius}
/// The radius of the inner corners.
///
/// Defaults to [this.outerFactor]
/// The radius is dynamically calculated based on the line height and the
/// provided factor.
///
/// Defaults to 10.0
/// {@end-template}
final double outerRadius;

Expand All @@ -311,7 +295,6 @@ class RoundedBackgroundText extends StatelessWidget {
style: TextStyle(
color: foregroundColor(backgroundColor),
leadingDistribution: TextLeadingDistribution.proportional,
height: calculateHeight(style.fontSize ?? 16),
fontSize: style.fontSize ?? 16.0,
).merge(style),
),
Expand Down Expand Up @@ -341,15 +324,13 @@ class _TextSpanEditingController extends TextEditingController {
final TextSpan _textSpan;

@override
TextSpan buildTextSpan(
{required BuildContext context,
TextStyle? style,
required bool withComposing}) {
TextSpan buildTextSpan({
required BuildContext context,
TextStyle? style,
required bool withComposing,
}) {
// This does not care about composing.
return TextSpan(
style: style,
children: <TextSpan>[_textSpan],
);
return TextSpan(style: style, children: <TextSpan>[_textSpan]);
}

@override
Expand Down Expand Up @@ -511,7 +492,7 @@ class _HighlightPainter extends CustomPainter {
info.y,
info.fullWidth,
info.fullHeight,
Radius.circular(outerFactor),
Radius.circular(info.outerFactor(outerFactor)),
),
Paint()..color = backgroundColor,
);
Expand Down Expand Up @@ -541,6 +522,9 @@ class _HighlightPainter extends CustomPainter {

final next = nextElement();

final outerFactor = info.outerFactor(this.outerFactor);
final innerFactor = info.innerFactor(this.innerFactor);

if (next != null) {
final difference = () {
final width = (info.width - next.width);
Expand All @@ -557,16 +541,16 @@ class _HighlightPainter extends CustomPainter {
}

void drawTopLeftCorner(LineMetricsHelper info) {
final outerFactor = lastUsedInfo == info
? this.outerFactor
: (lastUsedInfo.x - info.x).clamp(0, this.outerFactor);
final localOuterFactor = lastUsedInfo == info
? outerFactor
: (lastUsedInfo.x - info.x).clamp(0, outerFactor);
final controlPoint = Offset(
info.x,
info.y,
);
final endPoint = Offset(info.x, info.y + outerFactor);
final endPoint = Offset(info.x, info.y + localOuterFactor);

path.lineTo(info.x + outerFactor, info.y);
path.lineTo(info.x + localOuterFactor, info.y);
path.quadraticBezierTo(
controlPoint.dx,
controlPoint.dy,
Expand Down Expand Up @@ -594,16 +578,17 @@ class _HighlightPainter extends CustomPainter {

void drawInnerCorner(LineMetricsHelper info, [bool toLeft = true]) {
if (toLeft) {
final formattedHeight = info.fullHeight - innerLinePadding.bottom;
final formattedHeight =
info.fullHeight - info.innerLinePadding.bottom;

final innerFactor = (info.x - next!.x).clamp(0, this.innerFactor);
path.lineTo(info.x, info.fullHeight - innerFactor);
final localInnerFactor = (info.x - next!.x).clamp(0, innerFactor);
path.lineTo(info.x, info.fullHeight - localInnerFactor);
final iControlPoint = Offset(
info.x,
formattedHeight,
);
final iEndPoint = Offset(
info.x - innerFactor,
info.x - localInnerFactor,
formattedHeight,
);

Expand All @@ -614,17 +599,17 @@ class _HighlightPainter extends CustomPainter {
iEndPoint.dy,
);
} else {
final formattedY = next!.y + innerLinePadding.bottom;
final formattedY = next!.y + info.innerLinePadding.bottom;

final innerFactor = (next.x - info.x).clamp(0, this.innerFactor);
path.lineTo(next.x - innerFactor, formattedY);
final localInnerFactor = (next.x - info.x).clamp(0, innerFactor);
path.lineTo(next.x - localInnerFactor, formattedY);
final iControlPoint = Offset(
next.x,
formattedY,
);
final iEndPoint = Offset(
next.x,
formattedY + innerFactor,
formattedY + localInnerFactor,
);

path.quadraticBezierTo(
Expand Down Expand Up @@ -682,6 +667,9 @@ class _HighlightPainter extends CustomPainter {

final next = nextElement();

final outerFactor = info.outerFactor(this.outerFactor);
final innerFactor = info.innerFactor(this.innerFactor);

void drawTopRightCorner(
LineMetricsHelper info, [
double? factor,
Expand Down Expand Up @@ -725,7 +713,8 @@ class _HighlightPainter extends CustomPainter {
void drawInnerCorner(LineMetricsHelper info, [bool toRight = true]) {
// To left
if (!toRight) {
final formattedHeight = info.fullHeight - innerLinePadding.bottom;
final formattedHeight =
info.fullHeight - info.innerLinePadding.bottom;
path.lineTo(
info.fullWidth + innerFactor,
formattedHeight,
Expand All @@ -747,7 +736,7 @@ class _HighlightPainter extends CustomPainter {
endPoint.dy,
);
} else {
final formattedY = info.y + innerLinePadding.bottom;
final formattedY = info.y + info.innerLinePadding.bottom;
path.lineTo(
info.fullWidth,
formattedY + innerFactor,
Expand Down Expand Up @@ -848,16 +837,45 @@ class LineMetricsHelper {
/// Whether this line is the last line in the paragraph
bool get isLast => metrics.lineNumber == length - 1;

late EdgeInsets firstLinePadding = EdgeInsets.only(
left: height * 0.3,
right: height * 0.3,
top: height * 0.3,
bottom: 0,
);
late EdgeInsets innerLinePadding = EdgeInsets.only(
left: height * 0.3,
right: height * 0.3,
top: 0.0,
bottom: height * 0.15,
);
late EdgeInsets lastLinePadding = EdgeInsets.only(
left: height * 0.3,
right: height * 0.3,
top: 0.0,
bottom: height * 0.15,
);

/// Dynamically calculate the outer factor based on the provided [outerFactor]
double outerFactor(double outerFactor) {
return (height * outerFactor) / 35;
}

/// Dynamically calculate the inner factor based on the provided [innerFactor]
double innerFactor(double innerFactor) {
return (height * innerFactor) / 25;
}

double get x {
if (overridenX != null) return overridenX!;
final result = metrics.left;

if (metrics.lineNumber == 0) {
return result - firstLinePadding.left;
return result - (firstLinePadding.left);
} else if (isLast) {
return result - lastLinePadding.left;
return result - (lastLinePadding.left);
} else {
return result - innerLinePadding.left;
return result - (innerLinePadding.left);
}
}

Expand All @@ -866,9 +884,9 @@ class LineMetricsHelper {
if (metrics.lineNumber == 0) {
// return result - firstLinePadding.top;
} else if (isLast) {
return result + lastLinePadding.top / 2;
return result + (lastLinePadding.top / 2);
} else {
return result - innerLinePadding.top;
return result - (innerLinePadding.top);
}
return result;
}
Expand All @@ -879,24 +897,23 @@ class LineMetricsHelper {

if (!isEmpty) {
if (metrics.lineNumber == 0) {
return result + firstLinePadding.left;
return result + (firstLinePadding.left);
} else if (isLast) {
return result + lastLinePadding.left;
return result + (lastLinePadding.left);
} else {
return result + innerLinePadding.left;
return result + (innerLinePadding.left);
}
}
return x + metrics.width;
}

double get fullHeight {
// final result = metrics.lineNumber * metrics.height + height;
final result = y + height;

if (isLast) {
return result + lastLinePadding.bottom;
return result + (lastLinePadding.bottom);
} else {
return result + innerLinePadding.bottom;
return result + (innerLinePadding.bottom);
}
}

Expand All @@ -906,11 +923,11 @@ class LineMetricsHelper {
final result = metrics.width;

if (metrics.lineNumber == 0) {
return result + firstLinePadding.right;
return result + (firstLinePadding.right);
} else if (isLast) {
return result + lastLinePadding.right;
return result + (lastLinePadding.right);
} else {
return result + innerLinePadding.right;
return result + (innerLinePadding.right);
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/src/rounded_background_text_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ class _RoundedBackgroundTextFieldState
style: (widget.hintStyle ?? TextStyle(color: theme.hintColor))
.copyWith(
fontSize: fontSize,
height: calculateHeight(fontSize),
// height: calculateHeight(fontSize),
),
textAlign: widget.textAlign,
maxLines: widget.maxLines,
Expand All @@ -492,7 +492,7 @@ class _RoundedBackgroundTextFieldState
// color: Colors.transparent,
// color: Colors.amber,
fontSize: fontSize,
height: calculateHeight(fontSize),
// height: calculateHeight(fontSize),
leadingDistribution: TextLeadingDistribution.proportional,
),
textAlign: widget.textAlign,
Expand Down