I am trying to draw a text with background color and border radius, but the text does not show.
I've used sizeToFit to make the textfield fit its content.
When the below code is added to its superview, this is what is shown:
As you can see, the text is missing even though the view has adjusted itself to fit the text. I have tried setting a huge frame but its the same issue.
let text = NSTextField(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
text.stringValue = "ABC"
text.sizeToFit()
text.wantsLayer = true
text.isBordered = true
text.drawsBackground = true
let textFieldLayer = CALayer()
text.layer = textFieldLayer
text.backgroundColor = NSColor.blue
text.layer?.backgroundColor = NSColor.blue.cgColor
text.layer?.borderColor = NSColor.red.cgColor
text.layer?.borderWidth = 1
text.layer?.cornerRadius = 5
text.textColor = NSColor.red
let positionRelativeToScreen = toOrigin(point: positionFlipped, size: text.frame.size)
let positionRelativeToWindow = borderWindow.convertPoint(fromScreen: positionRelativeToScreen)
text.frame.origin = positionRelativeToWindow
return text
Solution was to remove textFieldLayer. Thanks #Willeke!
Related
I there a way, at runtime, other than using styles, to change the background color of a TListBox? Can I use the OnPaint event?
Because the TListbox doesn't have a property to change the background color, I can only think of the following, which is based on combining two components, of which one (the TListBox) uses a built-in style. Note however, that this is not depending on TStyleBook nor any of the style files supplied with Delphi Firemonkey.
Place a TRectangle as a background for the TListBox. Set its Fill - Color property to a color you like. (I used "Cornsilk" in the example).
Place the TListBox on the rectangle as a child of the rectangle. In the "Object Inspector" locate the StyleLookup property and change its value to transparentlistboxstyle. This makes the listbox transparent and the rectangle and its fill color to shine through.
If you make the TListBox one pixel smaller than the rectangle on each side, you can use the Sides property to provide a thin frame around the listbox. Or you can choose to make them equally sized and not show any frame.
My test result looks like this:
The TRectangle and the TListbox properties from the .fmx file:
object Rectangle1: TRectangle
Anchors = [akLeft, akTop, akBottom]
Fill.Color = claCornsilk
Position.X = 7.000000000000000000
Position.Y = 40.000000000000000000
Size.Width = 361.000000000000000000
Size.Height = 219.000000000000000000
Size.PlatformDefault = False
object ListBox1: TListBox
Anchors = [akLeft, akTop, akRight, akBottom]
Position.X = 1.000000000000000000
Position.Y = 1.000000000000000000
Size.Width = 359.000000000000000000
Size.Height = 217.000000000000000000
Size.PlatformDefault = False
StyleLookup = 'transparentlistboxstyle'
TabOrder = 0
ParentShowHint = False
ShowHint = False
DisableFocusEffect = True
ItemHeight = 48.000000000000000000
DefaultItemStyles.ItemStyle = 'listboxitemrightdetail'
DefaultItemStyles.GroupHeaderStyle = ''
DefaultItemStyles.GroupFooterStyle = ''
Viewport.Width = 359.000000000000000000
Viewport.Height = 217.000000000000000000
end
end
To change the color of ListBox1, you actually change the color of the TRectangle:
procedure TForm5.ColorListBox1ItemClick(const Sender: TCustomListBox;
const Item: TListBoxItem);
begin
Rectangle1.Fill.Color := TColorListBox(Sender).Color;
end;
Good evening,
I have been trying to figure out how to fade a screen when I press a button in order to give a subview a more distinct appearance. I have researched zPositions and I thought that implementing this feature within my code would help. When I run my code, the entire screen fades. I would like there to be a circle progress ring that shows up, while the background is faded. I will show a picture and my code. Thank you in advance.
#objc func handlePost() {
let center = view.center
let trackLayer = CAShapeLayer()
let circularPath = UIBezierPath(arcCenter: center, radius: 100, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)
blackScreen=UIView(frame: self.view.bounds)
blackScreen.backgroundColor=UIColor(white: 0, alpha: 0.8)
blackScreen.isHidden=true
self.navigationController?.view.addSubview(blackScreen)
blackScreen.layer.zPosition=50
blackScreen.isHidden=false
self.view.backgroundColor = UIColor.white
trackLayer.path = circularPath.cgPath
trackLayer.strokeColor = UIColor.lightGray.cgColor
trackLayer.lineWidth = 10
trackLayer.fillColor = UIColor.clear.cgColor
trackLayer.lineCap = kCALineCapRound
// The zPosition is supposed to bring this layer to the front.
trackLayer.zPosition = 100
shapeLayer.path = circularPath.cgPath
shapeLayer.strokeColor = GREEN_Theme.cgColor
shapeLayer.lineWidth = 10
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineCap = kCALineCapRound
shapeLayer.strokeEnd = 0
// The zPosition is supposed to bring this layer to the front.
shapeLayer.zPosition = 100
let basicAnimation = CABasicAnimation(keyPath: "strokeEnd")
basicAnimation.toValue = 1
basicAnimation.duration = 2
basicAnimation.fillMode = kCAFillModeForwards
basicAnimation.isRemovedOnCompletion = false
shapeLayer.add(basicAnimation, forKey: "dataSearch")
shapeLayer.removeAnimation(forKey: "finished")
view.layer.addSublayer(trackLayer)
view.layer.addSublayer(shapeLayer)
}
Again after spending hours with my code, I managed to figure out my own answer.
before I had
self.navigationController?.view.addSubview(blackScreen)
// (faded screen)
I simply needed to add
self.view.addSubview(blackScreen)
to turn it into a layer that way I could manipulate it with my zPosition.
I am trying to write text labels on a graph view representing a variety of data points (imagine a line graph in Excel).
I select a data set using a tableView. Each time a select a new data set the graph is redrawn.
I can draw the line graph using a custom view. No problems.
I can draw the text labels using the following function called from drawRect():
func drawDataPointLabels(size: CGSize) { //size is the view.bounds
var dataLabelsArray: [(NSColor, String, NSRect)] = []
// graphDetails contain an array of tuples [(), (), (), ()] - this represents one graph type = eg Monthly Fees ** there will be a maximum of 12 items in the array
for graphDetails in graphDetailsArray {
// each dataPoint object is a tuple (graphType: columnLabel: columnColor: columnHeight: columnNumber: ) representing one dataPoint
for dataPoint in graphDetails {
let graphHeight = size.height / 2
let graphWidth = size.width - graphOrigin.x - rightMargin
let columnAndGapSize = graphWidth / 25
let labelX: CGFloat = (graphOrigin.x + columnAndGapSize) + (columnAndGapSize * dataPoint.columnNumber) * 2
let labelY: CGFloat = dataPoint.columnHeight * (graphHeight - topMargin - bottomMargin)
// determine the location and frame for the text label to match dataPoint
let textFrame = NSRect(x: labelX, y: labelY, width: 30, height: 10)
let dataPointTuple = (dataPoint.columnColor, dataPoint.columnLabel, textFrame)
dataLabelsArray.append(dataPointTuple)
}
for dataPoint in dataLabelsArray {
let (color, label, frameRect) = dataPoint
let lblDataPoint = NSTextField(frame: frameRect)
lblDataPoint.stringValue = label
lblDataPoint.backgroundColor = backgroundColor
lblDataPoint.textColor = color
self.addSubview(lblDataPoint)
}
}
}
However, I can not work out how to remove the data labels when the view is updated and a new data set presented. The graph redraws but the text labels remain from the previous data set.
Any guidance/suggestions would be appreciated.
Adding the following code to the top of the function has solved the issue for me.
let subViewsToRemove = self.subviews
for object in subViewsToRemove {
object.removeFromSuperview()
}
I am trying to create a ScrollView that grows according to the amount of information added to it and save the data. How can I accomplish this? I have been trying to figure this out for a while and am unsure of how to do it. The data that I want to save is inside a TextField. I am unsure if this could cause any problems.
Any input and suggestions would be greatly appreciated.
Thanks in advance.
You can use the .contentSize of a UIScrollView to set the content size.
If you want to base the content size of the size of the information, you could expand the content size every time you add new content
var scrollView:UIScrollView = UIScrollView(frame: CGRectMake(0, 0, 100, 200))
scrollView.contentSize = CGSizeMake(100, 800)
var textField:UITextField = UITextField(frame: CGRectMake(0, scrollView.frame.height, scrollView.frame.width, 200))
scrollView.contentSize = CGSizeMake(scrollView.contentSize.width, scrollView.contentSize.height + textField.frame.height)
scrollView.addSubview(textField)
textField.text = "Foo"
var lbls = [String]()
for view in scrollView.subviews{
if let view:UITextField = view as? UITextField{
var lbl = view.text
}
}
//Save lbls as array or every string inside lbls using core data
Here I set the height of the content size to the height of my label + the current height of the content size.
Creating a label programatically (i.e. not in designer) won't right-align on my form.
Set lblStatus = StatusForm.Controls.Add("VB.Label", "lbl" & xml(Prop, "column"))
With lblStatus
.Visible = True
.Caption = Text
.Alignment = vbRightJustify
.WordWrap = False
.AutoSize = True
.top = Index * (lblStatus.height)
.left = MaxWidth - Screen.TwipsPerPixelX * 15
.Width = StatusForm.TextWidth(Text)
End With
I created three of these controls, but they continue to expand from the left, rather than from the right:
Ideally, I want those labels (surrounded by #) to have their semicolons line up.
Since you set AutoSize to true, the width is set to the precise width of the text, leaving no room for alignment.
To layout the text within a fixed width, turn off AutoSize.