Wrap with Space between and Start Alignment in Flutter - flutter

I have a wrap with start alignment and it shows like this.
In my case, I do not want the free space that you see on the right to remain. I can fix this with space between alignment and it looks like this.
But in this case I don't want the last line, having 3 items, to be placed that way, if not in the way that start alignment provides me.

I implemented this by calculating spacing value:
Wrap(
spacing: _calculateSpacing(),
alignment: WrapAlignment.start,
children: tiles,
);
double _calculateSpacing() {
return _calculateSpacingWith(
width: MediaQuery.of(context).size.width,
tileWidth: _TileWidget.width,
minSpacing: 4,
);
}
double _calculateSpacingWith({
required double width,
required double tileWidth,
required double minSpacing,
}) {
// N = tilesInRow
// tileWidth * N + spacing * (N-1) = width
final tilesInRow = ((width + minSpacing) / (tileWidth + minSpacing)).floor();
if (tilesInRow <= 1) {
return 0;
}
final spacing = ((width - tileWidth * tilesInRow) / (tilesInRow - 1)).floorToDouble();
return spacing;
}

Related

How to give custom margin around 'CupertinoSwitch' thumb?

Is there any way we can add custom margin around 'CupertinoSwitch' thumb? Below is how I am using 'CupertinoSwitch', I don't find any property for the same available for this widget.
`CupertinoSwitch(
onChanged: onChanged,
value: value,
activeColor:
MyColors.primaryColor.platformBrightnessColor(context),
trackColor:
MyColors.greyColor.platformBrightnessColor(context),
),`
And below is how it is looking--
Bydefault the (white-circular thumb) margin is 1px, I want to make it custom as per the business needs. Please suggest if there is any workaround available for this, also let me know if more details required on the same. Thanks in advance!
this is flutter source code form thumb_painter.dart && geometry.dart.
you can edit #param delta for you need.
/// Returns a new [RRect] with edges and radii moved outwards by the given
/// delta.
RRect inflate(double delta) {
return RRect._raw(
left: left - delta,
top: top - delta,
right: right + delta,
bottom: bottom + delta,
tlRadiusX: math.max(0, tlRadiusX + delta),
tlRadiusY: math.max(0, tlRadiusY + delta),
trRadiusX: math.max(0, trRadiusX + delta),
trRadiusY: math.max(0, trRadiusY + delta),
blRadiusX: math.max(0, blRadiusX + delta),
blRadiusY: math.max(0, blRadiusY + delta),
brRadiusX: math.max(0, brRadiusX + delta),
brRadiusY: math.max(0, brRadiusY + delta),
);
}
' Container(
// margin:EdgeInsets.only(left: 10,right: 5,top: 50,bottom: 20),
//margin: EdgeInsets.all(50),
//margin: EdgeInsets.symmetric(vertical: 50,horizontal: 50),
child:CupertinoSwitch(
onChanged: onChanged,
value: value,
activeColor:
MyColors.primaryColor.platformBrightnessColor(context),
trackColor:
MyColors.greyColor.platformBrightnessColor(context),)) `

Save ColorFiltered image to disk

In Flutter, if we use the ColorFilter widget, it takes a ColorFilter.matrix and an Image, on which it applies the ColorFilter.matrix.
const ColorFilter sepia = ColorFilter.matrix(<double>[
0.393, 0.769, 0.189, 0, 0,
0.349, 0.686, 0.168, 0, 0,
0.272, 0.534, 0.131, 0, 0,
0, 0, 0, 1, 0,
]);
Container _buildFilterThumbnail(int index, Size size) {
final Image image = Image.file(
widget.imageFile,
width: size.width,
fit: BoxFit.cover,
);
return Container(
padding: const EdgeInsets.all(4.0),
decoration: BoxDecoration(
border: Border.all(color: _selectedIndex == index ? Colors.blue : Theme.of(context).primaryColor, width: 4.0),
),
child: ColorFiltered(
colorFilter: ColorFilter.matrix(filters[index].matrixValues),
child: Container(
height: 80,
width: 80,
child: image,
),
),
);
}
How can we get the underlying image (in pixels/bytes) so that it can be saved on disk. I don't want to save the rendered ColorFiltered area on the screen.
Curretly am forced to use the photofilters library from pub.dev, which does the pixel manipulation to apply the custom filters. However, its not very efficient and essentially applies the pixel level manipulation for every thumbnail, making it very slow. On the other hand, ColorFiltered widget is lightening fast!
Below is internal working of photofilters library
int clampPixel(int x) => x.clamp(0, 255);
// ColorOverlay - add a slight color overlay.
void colorOverlay(Uint8List bytes, num red, num green, num blue, num scale) {
for (int i = 0; i < bytes.length; i += 4) {
bytes[i] = clampPixel((bytes[i] - (bytes[i] - red) * scale).round());
bytes[i + 1] =
clampPixel((bytes[i + 1] - (bytes[i + 1] - green) * scale).round());
bytes[i + 2] =
clampPixel((bytes[i + 2] - (bytes[i + 2] - blue) * scale).round());
}
}
// RGB Scale
void rgbScale(Uint8List bytes, num red, num green, num blue) {
for (int i = 0; i < bytes.length; i += 4) {
bytes[i] = clampPixel((bytes[i] * red).round());
bytes[i + 1] = clampPixel((bytes[i + 1] * green).round());
bytes[i + 2] = clampPixel((bytes[i + 2] * blue).round());
}
}
Any pointers appreciated.

Is it possible to modify the position of items in a LazyVGrid/LazyHGrid (SwiftUI 5.5)?

I'm relatively new to Swift and have a grid layout question: I'm currently using a LazyHGrid with adaptive grid items and a single column to flexibly layout items without a predetermined column count. I determine the number of columns shown by setting a maxWidth the grid layout with a maxWidth based on the number of items to be displayed
What I'm trying to accomplish in each of the scenarios below (with a solution that would scale up too) is essentially to adjust the positions in the examples below by shifting items out of position "🔴" and into position "⚪️", eliminating the "floating orphan" item not hugging the edge. The "⚫️" positions are already correct.
CONSTRAINTS
I want to minimize the width that this grid uses, but not all rows can accommodate the taller stacks (so setting a bunch of brittle rules seems like a poor solution) and I'm not interested in setting a fixed row item height to remove the need for a dynamic solution
I'd like to avoid creating grid manually with nested HStacks and VStacks and writing a bunch of extra logic to manage the contents of each row and column given the height of the parent row (as retrieved via GeometryReader).
WHAT I'VE TRIED
I looked in the Lazy_Grid docs to see if there was a view modifier that would accomplish this -- didn't come across one (though it's entirely possible I've missed it!)
I thought maybe flipping the layoutDirection (from LTR to RTL) might do it, but no such luck
I shifted around the alignment values of the repeated gridItem and lazyHGrid container, but the floating orphan remained
EXAMPLES
For three items:
/* short */
___________
⚫️⚫️|
🔴⚪️|
/* tall */
___________
⚫️|
⚫️|
⚫️|
For four items:
/* short */
___________
⚫️⚫️|
⚫️⚫️|
/* tall */
___________ ___________
⚫️⚫️| ⚫️⚫️| // NOTE: I *could* constrain the height in this case
🔴⚪️| ⚫️⚫️| // to achieve the 2x2 grid but would rather not
🔴⚪️|
For five items:
/* short */
___________
⚫️⚫️⚫️|
🔴⚫️⚪️|
/* tall */
___________
⚫️⚫️|
⚫️⚫️|
🔴⚪️|
For six items:
/* short */
___________
⚫️⚫️⚫️|
⚫️⚫️⚫️|
/* tall */
___________
⚫️⚫️|
⚫️⚫️|
⚫️⚫️|
For seven items:
/* short */
___________
⚫️⚫️⚫️⚫️|
🔴⚫️⚫️⚪️|
/* tall */
___________
⚫️⚫️|
⚫️⚫️|
⚫️⚫️|
🔴⚪️|
let items = filterItems()
let iconCount = CGFloat(items.count)
let iconSize: CGFloat = 18
let spacing: CGFloat = 2
// NOTE: `iconCount / 2` because the min-height of the parent
// only fits two items. The current item count is 7 and it's
// unlikely that it'd ever do more than double.
let cols = CGFloat(iconCount / 2).rounded(.up)
let maxWidth = calcWidth(for: cols, iconSize: iconSize, spacing: spacing)
let minWidth = cols < 2 ? maxWidth : calcWidth(for: cols - 1, iconSize: iconSize, spacing: spacing)
LazyHGrid(
rows: Array(
repeating: GridItem(
.adaptive(minimum: iconSize, maximum: iconSize),
spacing: spacing,
alignment: .center
),
count: 1
),
alignment: .center,
spacing: spacing
) {
ForEach(0..<items.count, id: \.self) { n in
...item views...
}
}
.frame(minWidth: minWidth, maxWidth: maxWidth)
My brain is stuck on finding a Swift concept similar to CSS's FlexBox justify-content: flex-end; align-items: flex-start but it feels to me there should be a more Flexy/Swifty solution for this that I'm just missing?
(The grid is nested within an HStack currently, and shoved to the top-trailing corner of it's parent with a spacer, effectively accomplishing the align-items: flex-start portion of the Flexbox solution mentioned above asd as shown in the illustrations above)
Edit: Layout direction works for me
You mentioned this didn't work in your post, but I just tested setting layout direction to right-to-left, and it works. All the end items are aligned to the right. Maybe the specific OS you're testing on has a layout bug. The full playground snippet (tested on Xcode 13):
import UIKit
import PlaygroundSupport
import SwiftUI
import Foundation
let iconCount: CGFloat = 4
let iconSize: CGFloat = 18
let spacing: CGFloat = 2
let cols: CGFloat = 2
let maxWidth = calcWidth(for: cols, iconSize: iconSize, spacing: spacing)
let minWidth = cols < 2 ? maxWidth : calcWidth(for: cols - 1, iconSize: iconSize, spacing: spacing)
func calcWidth(for cols: CGFloat, iconSize: CGFloat, spacing: CGFloat) -> CGFloat {
return iconSize * cols + spacing * cols
}
PlaygroundPage.current.liveView = UIHostingController(rootView: {
TabView {
HStack {
LazyHGrid(
rows: Array(
repeating: GridItem(
.adaptive(minimum: iconSize, maximum: iconSize),
spacing: spacing,
alignment: .center
),
count: 1
),
alignment: .center,
spacing: spacing
) {
ForEach(0..<Int(iconCount), id: \.self) { n in
Text("B")
.frame(width: iconSize, height: iconSize)
.border(.red)
}
}
.frame(minWidth: minWidth, maxWidth: maxWidth)
.background(Color.green)
.frame(height: iconSize * 3 + spacing * 2)
.environment(\.layoutDirection, .rightToLeft)
// I also tried this, but it isn't needed
//.flipsForRightToLeftLayoutDirection(true)
}
}
}())
Original answer:
This is not the ideal solution, but one option is to use 3D rotation to flip the layout on the Y axis. I used a simple text view in Playgrounds as an example:
LazyHGrid(
rows: Array(
repeating: GridItem(
.adaptive(minimum: iconSize, maximum: iconSize),
spacing: spacing,
alignment: .center
),
count: 1
),
alignment: .center,
spacing: spacing
) {
ForEach(0..<Int(iconCount), id: \.self) { n in
Text("B")
.frame(width: iconSize, height: iconSize)
.rotation3DEffect(.degrees(180), axis: (x: 0, y: 1, z: 0))
}
}
.frame(minWidth: minWidth, maxWidth: maxWidth)
.rotation3DEffect(.degrees(180), axis: (x: 0, y: 1, z: 0))

ItextSharp - Add text watermark on separate lines

I am trying to add a watermak on a pdf file with itextsharp 5.1.2.0 .
I want the watermark to be in the center of the page, with a 45° angle, with a border around these lines.
Here is my code :
for (int i = 1; i <= reader.NumberOfPages; i++)
{
iTextSharp.text.Rectangle pageSize = reader.GetPageSizeWithRotation(i);
PdfContentByte pdfPageContents;
pdfPageContents = pdfStamper.GetOverContent(i);
pdfPageContents.BeginText();
PdfGState gstate = new PdfGState();
gstate.FillOpacity = 0.4f;
gstate.StrokeOpacity = 0.4f;
pdfPageContents.SaveState();
pdfPageContents.SetGState(gstate);
BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, Encoding.ASCII.EncodingName, false);
pdfPageContents.SetRGBColorFill(255, 0, 0);
double radians = Math.Atan2(pageSize.Height, pageSize.Width);
float textAngle = radians * (180 / Math.PI);
pdfPageContents.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Phrase 1 This is Phrase 2 and must be centered below phrase 1" , pageSize.Width / 2, pageSize.Height / 2, textAngle);
//pdfPageContents.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Phrase 1", pageSize.Width / 2, pageSize.Height / 2, textAngle);
//pdfPageContents.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "This is Phrase 2 and must be centered below phrase 1", pageSize.Width / 2 + 20 , pageSize.Height / 2 - 20, textAngle);
}
This adds the watermark on one line.
I am able to have two lines with the commented code.
What i dont like are the hardcoded values for the position for the second line.
I am sure there must be a better way of achieving this.
Regarding the border i did not manage to add it around the lines.
If someone can help me with this case .
Thanks
basically what I do for my project is as under... here font_size and style are the variables... also llx, lly, urx,ury are variable for the the corrdinates position and size.. in alignment variable, you can set the alignment easily....
for opacity your code will work fine(you can add state options)
Dim Font = New Font(arial, FONT_SIZE, STYLE, iTextSharp.text.Color.BLACK )
dim text = GetRowValue(row, "CONTROL_MAP")
Dim ct As ColumnText = New ColumnText(pdf_cb)
ct.SetSimpleColumn(LLX, LLY, URX, URY, FONT_SIZE, ALIGNMENT)
ct.SetText(New Paragraph(0, text, Font))
ct.Go()

Raphael / CoffeeScript attempt to constrain Y coordinate when dragging

I want to drag an image along a horizontal line. In other words, I want to ignore the Y value of the mouse movement. I also want to limit the range of the X values. Here is a CoffeeScript class that drags an image, but attempts unsuccessfully to constrain the image's Y value. The other problem with this code is that the image's X value seems to be twice what it should be.
class TripleSlider
circle = ""
# (#x,#y) is coordinate of upper left corner of component bounding box
constructor: (#editArea, #x, #y, #tsLabel, #showLimits=false) ->
dragger: (x, y) =>
x2 = Math.min(Math.max(x, 0), 127)
circle.attr({x: x2, y:0}) # does not do anything; I hoped it would constrain Y
drawRaphael: () =>
paper = Raphael(10, 50, 320, 200)
paper.fixNS()
paper.draggable.enable()
circle = paper.image("/assets/images/sliderTipDef.png", 0, 0, 13, 16).draggable.enable()
circle.drag(#dragger)
$ ->
tripleSlider = new TripleSlider($('#editArea'), 50, 100, "Attribute", true)
tripleSlider.draw()
BTW, I applied the patch to raphael.draggable.js by inserting the code below at line 13.
/** Fix from https://github.com/DmitryBaranovskiy/raphael/issues/409
* Just call it once after constructing paper:
*
* var paper = Raphael(0, 0, 300, 300);
* paper.fixNS();
* paper.draggable.enable();
*/
Raphael.fn.fixNS = function() {
var r = this;
for (var ns_name in Raphael.fn) {
var ns = Raphael.fn[ns_name];
if (typeof ns == 'object') for (var fn in ns) {
var f = ns[fn];
ns[fn] = function(){ return f.apply(r, arguments); }
}
}
};
Mike