VirtualTreeView node height based on icon font size - delphi

I am trying to set node height based on system icon font size.
My code so far:
LOGFONT lf;
ZeroMemory(&lf, sizeof(lf));
if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0))
{
// This is a hack because font height itself doesn't give me correct node height - everything is too tight
int Height = VST->DefaultNodeHeight - abs(VST->Font->Height)+1;
VST->DefaultNodeHeight = abs(lf.lfHeight)+Height;
VST->Font->Name = lf.lfFaceName;
VST->Font->Height = lf.lfHeight;
}
The above works but I cannot get the DefaultNodeHeight right - it is not the same size as default used when font is fixed. Font height is good.
How can I retrieve the correct value from the system, or auto-size VirtualTreeView to use correct node height which would be the same as default but based on above code?
Default font height is -14, font size is 8 and node height is 18.
So in other words I need:
a) icon font size
b) appropriate DefaultNodeHeight, based on font size (in case if I use different font size, then DefaultNodeHeight is recalculated based on that particular size)

Related

Multicolumn list with flexible columns width - iOS

I want to create list with two columns. Text in first column should be aligned to left and text in second column should be aligned to right. Space between columns should be constant. Different cases depends on texts length should be covered:
1.
Text 123
TextText 12
Tex 123
Text 1
Te 123456
T 12
Te 1234
Te 1
Text 123
TextText 12
TextTextTextTextText 123
Text 1
Both columns should have flexible width depends on the longest text. They also should have some minimum width so it will not be completely invisible if text in other column will be too long. Whole list also should have flexible width, of course there is some max width and then text in first column should be divided into lines. I don't want to divide into lines text in second column as long as I don't have to.
How to create such list?
I try to use for it two stack views one next to the other. These two stack views I have in my custom control. My custom control is added to container view using xib and have constraints equals to 0 for top, leading and bottom and greater or equals 0 for trailing. To these stack views I add labels programatically and I also set content hugging priority for them (first label has lower priority than second one). One think stil doesn't work, first stack view is as width as first label in this stack view. It doesn't change his width when other labels with longer texts are added. Is it possible to have working solution without calculating stack views width manually?
private void Initialize()
{
_firstStackView = new UIStackView
{
TranslatesAutoresizingMaskIntoConstraints = false,
Axis = UILayoutConstraintAxis.Vertical,
Spacing = 4
};
_secondStackView = new UIStackView
{
TranslatesAutoresizingMaskIntoConstraints = false,
Axis = UILayoutConstraintAxis.Vertical,
Spacing = 4,
Alignment = UIStackViewAlignment.Trailing
};
Add(_firstStackView);
Add(_secondStackView);
AddConstraints();
}
private void AddConstraints()
{
NSLayoutConstraint.ActivateConstraints(
new[]
{
_firstStackView.LeadingAnchor.ConstraintEqualTo(LeadingAnchor),
_secondStackView.LeadingAnchor.ConstraintEqualTo(_firstStackView.TrailingAnchor, 20),
TrailingAnchor.ConstraintEqualTo(_secondStackView.TrailingAnchor),
_firstStackView.TopAnchor.ConstraintEqualTo(TopAnchor),
_firstStackView.BottomAnchor.ConstraintEqualTo(BottomAnchor),
_secondStackView.CenterYAnchor.ConstraintEqualTo(_firstStackView.CenterYAnchor),
_secondStackView.WidthAnchor.ConstraintGreaterThanOrEqualTo(WidthAnchor, 0.25f),
_firstStackView.WidthAnchor.ConstraintGreaterThanOrEqualTo(WidthAnchor, 0.25f),
});
}
You can use UICollectionView to create list with two columns. Space between columns and grid size can be adjusted by changing UICollectionViewLayout.
Implement text adaptive width and height:
Instantiate UILabel
Set the UILabel property to get the text content and font
Calculate the size according to text and font
Use CGSize to set the maximum width you want
Set the frame according to the size
You can see some useful info here
For more details, you can refer to the following doc:
Collection Views in Xamarin.iOS | Microsoft Docs

How to scale the button text based on screen design swift?

In my project, i am using scaling for UI components. I am able to scale the text for UIlabel like below and it's working in all device:
1. Autoshrinks - minimum font scale set it to 0.5
2. No of lines - 0
3. Enable dynamic type in attribute inspector
4. adjustFontSizeToWidth to true
But when i am trying to adjust font for UI Button using beolow steps and i am not able to scale the text for UI button.
button.titleLabel?.numberOfLines = 1 // Tried with 0 also
button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.lineBreakMode = // tried differenet linebreakmode
Could anyone have an idea of scaling UI Button text?
Are you sure it's not working?
Edit - After comments...
UIKit elements such as UILabel / UIButton / etc to not have a built-in "auto-adjust font height" property.
I don't work for Apple, so just guessing that is (at least in part) due to the fact that, in general...
Based on screen height, the UI is designed to either:
provide more or less information, e.g. more rows in a table, or
adjust vertical spacing between elements
That doesn't mean you can't or shouldn't adjust your font sizes... it just means you have to do it manually.
Couple options:
set the font-size at run-time, as suggested by Duncan
use a UIAppearance proxy to set the font-size, again at run-time
in either case, you could use a height-to-fontSize table or a "percentage" calculation.
Another option would be a custom class that sets the font-size based on the constrained button height.
Here's a simple example (note: for demonstration purposes only):
class AutoFontSizeButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
guard let fnt = titleLabel?.font else { return }
// default system type button has 6-pts top / bottom inset
// and font size is 15/18ths of that height
let h = ((bounds.height - 12.0) * (15.0 / 18.0)).rounded()
let fs = fnt.pointSize
if h != fs {
titleLabel?.font = UIFont(descriptor: fnt.fontDescriptor, size: h)
}
}
}
Result - the top three (yellow) buttons are 30, 40 and 50-points in height, with the default font-size of 15. The bottom three (green) buttons are again 30, 40 and 50-points in height, but the font-size is automatically set at run-time:
I don't think there is a way to get the font to auto-size. However, if you set the button's titleLabel.font to a specific font size the button will update to use the new font size, including resizing the button.
Use code like this:
let size: CGFloat = useLargeFont ? 50.0 : 17.0 //Change as needed
if let buttonFont = button.titleLabel?.font {
button.titleLabel?.font = buttonFont.withSize(size)
}

Make UILabel auto-adjust font size to screen width, but not to text length

In a very simple single screen app, I have a single-line UILabel going from left edge to right edge of the screen.
The text of the label is dynamically updated at runtime. The length of the text varies, as it contains a number in the range 0...100, and I am neither using a monospaced font nor leading zeroes.
Here is an illustration:
|<--------- Screen width --------------->|
|<----- UILabel "Some value = 0" ------->|
|<----- UILabel "Some value = 50" ------>|
|<----- UILabel "Some value = 100" ----->|
I would like the label to always use the maximum width for any device (i.e. screen size). This can be achieved by using auto-layout, suitable leading and trailing constraints, a large font size and the "auto-shrink" property for the label.
The problem is, that this approach will make the font size also vary depending on the value displayed, which is not what I want. It should only vary with the width of the screen, but not with the length of the label text.
In the example above, a large font size would be used for the value 0, a medium one for 50 and a small one for 100. I want it to adjust to the worst-case (100) and use the resulting size for any text afterwards.
Is it possible to achieve this using Interface-Builder properties and auto-layout constraints only?
I can think of ways how to calculate sizes in code, but I think there must be an easier way.
You cannot express font size as a proportion of view width in interface builder but you can do it very easily in code:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let textSize = Constant.baseFontSize * bounds.size.width / Constant.baseViewWidth
label.font = .systemFont(ofSize: textSize)
}

Make responsive label font size for iphone devices

I am new to iOS Development.I am having problem with font size with phone screen size.For example Font size in iPhone 8 Plus looks fine but that text size is bigger in iPhone SE.I tried check Dynamic Type to Automatically Adjusts Font.And try to play with Autoshrink in StoryBoard.And i also tried to Add Font Variation in storyBoard.But I didnt get any good solution.Hope you understand my problem.Thanks in advance
Try this
class func dynamicFontSizeForIphone(fontSize : CGFloat) -> CGFloat
{
var current_Size : CGFloat = 0.0
current_Size = (UIScreen.main.bounds.width/320) //320*568 is my base
let FinalSize : CGFloat = fontSize * current_Size
return FinalSize
}
hope this work
You can change font size by using constraints.
1.take a label give its basic two constraint to satisfy. give one more constraint of equal.width to parent view. keep width as wide as your label text is.(a bit more than label text).
In attribute inspector there is a property name 'auto shrink' set it to 'minimum font size'
thats it.
Note: This will work fine if your Label text is constant. For changeable text there will be other approaches.

AdjustsFontSizeToFitWidth vs. SizeToFit

I'm using SizeToFit because I don't have to specify the Frame property to have an adaptive size of the UIButton/UILabel. In my case it's a button on a toolbar. Now I made the following observation:
If I use AdjustsFontSizeToFitWidth together with SizeToFit than the font size isn't adapted anymore. So I can
Specify a Frame and use AdjustsFontSizeToFitWidth
Use SizeToFit but don't have the adjustable font size anymore
Do you also have this problem? How do you circumvent this problem? How to let the intrinsic content size drive the frame size? Or do I have to set the Frame property? The advantage of Autolayout was to not define a frime size any more ...
I think I made an error in reasoning. SizeToFit defines the size after the content (content has already a fixed size). AdjustsFontSizeToFitWidth needs a frame in which it can change the font size. Both together doesn't work.
Here is a macro I've made to address this issue so that you can shrink font size to fit width AND call sizeToFit without the font size going back up post-shrink.
///Works like `adjustsFontSizeToFitWidth` but allows you to use `sizeToFit` and/or measure the new [adjusted] font size; one time adjustment, needs to be called again if `.text` changes.
#define shrinkFontSizeIfNeeded(__label) {\
UIFont *__currentFont = __label.font;\
CGFloat __originalFontSize = __currentFont.pointSize;\
CGSize __currentSize = [__label.text sizeWithAttributes:#{NSFontAttributeName : __currentFont}];\
while (__currentSize.width > __label.frame.size.width && __currentFont.pointSize > (__originalFontSize * __label.minimumScaleFactor)) {\
__currentFont = [__currentFont fontWithSize:__currentFont.pointSize - 1];\
__currentSize = [__label.text sizeWithAttributes:#{NSFontAttributeName : __currentFont}];\
}\
__label.font = __currentFont;\
}

Resources