Is there a way to get the left yAxis width? I'm drawing custom markers and would like to avoid to draw over the left yAxis.
There is a solution for the android version of this library but it doesn't work in iOS because of different render methods: How to get the width of y-axis label in MPAndroidChart
You can retrieve the axis width by the requiredSize() method.
chartView.leftAxis.requiredSize()
This is what requiredSize() method actually does:
#objc open func requiredSize() -> CGSize
{
let label = getLongestLabel() as NSString
var size = label.size(withAttributes: [NSAttributedString.Key.font: labelFont])
size.width += xOffset * 2.0
size.height += yOffset * 2.0
size.width = max(minWidth, min(size.width, maxWidth > 0.0 ? maxWidth : size.width))
return size
}
Use this only after you set the chart data, cause the chart will automatically calculate the width with the longest label in your axis.
Hope it helps
Does this give you what you need?
let yourBarChartView = BarChartView()
let leftAxis = yourBarChartView.leftAxis
let width = leftAxis.axisLineWidth
Hope this helps!
Related
I'm trying to position a button at a fixed position inside a UIImageView (AspectFit) which itself is inside a UIScrollView. This worked perfectly on my first try when the UIScrollView and the UIImageView containers both covered the whole screen, the button was pinned to a certain location of the image and stayed at position during zooming. You can see the result in the below image.
As you can obviously see there are white borders above and below the image (related to aspect fit) therefore I had to do some calculation to get the margin from top to calculate the "real" y position of the red square. My code looks like this:
let originalImageSize: CGSize = CGSize(width: image.size.width, height: image.size.height)
let aspectRatio = image.size.width/image.size.height;
let requiredHeight = self.view.bounds.size.width / aspectRatio;
let screenHeight = self.view.bounds.height;
let marginTop = (screenHeight - requiredHeight) / 2;
let renderedImageSize: CGSize = CGSize(width: self.view.bounds.width, height: requiredHeight)
let x:Double = 0
let y:Double = 0
let button = UIButton()
button.frame = CGRect(x: Double(renderedImageSize.width/originalImageSize.width) * x,
y: Double(renderedImageSize.height/originalImageSize.height) * y + Double(marginTop),
width: 10, height: 10)
button.backgroundColor = UIColor.red
imageView.addSubview(button)
As you see I calculated the "marginTop" to get the real y position. The square is perfectly located on x: 0 and y:0 (relative to the image). So far so good, this example worked perfectly.
Now I created a new view which contains a navigation bar and tab bar. The scrollView is in between and no longer covers the whole screen but only the area between my navigation and my tab bar. The imageView has the same size like my scrollView. Pretty much the same as in the example above. Now I tried to set my button a specific location again, but this time there is an offset on the y axis of exactly 6 pixels and I have no idea what I'm doing wrong. And to make it even worse when testing it on other devices the offset on the y axis is even bigger than 6 pixels, while the first example works perfectly accross all devices I tested. You can see the result with the "wrong" y-axis value here.
I changed my code to the following, based on the fact that sizes should be calculated according to the "new" scrollView size.
let originalImageSize: CGSize = CGSize(width: image.size.width, height: image.size.height)
let aspectRatio = image.size.width/image.size.height;
let requiredHeight = scrollView.bounds.size.width / aspectRatio;
let screenHeight = scrollView.bounds.height;
let marginTop = (screenHeight - requiredHeight) / 2;
let renderedImageSize: CGSize = CGSize(width: scrollView.bounds.width, height: requiredHeight)
let x:Double = 0
let y:Double = 0
let button = UIButton()
button.frame = CGRect(x: Double(renderedImageSize.width/originalImageSize.width) * x,
y: Double(renderedImageSize.height/originalImageSize.height) * y + Double(marginTop),
width: 10, height: 10)
button.backgroundColor = UIColor.red
imageView.addSubview(button)
A quick workaround would be something likes this, but it is hacky as hell and doesn't work for other device sizes and I obviously want to learn how to do it the right way:
[...] y: Double(renderedImageSize.height/originalImageSize.height) * y + Double(marginTop) - 6, [...]
I've been sitting on this for hours now and still don't have any idea why the y-axis is off even though the calculation of the top margin should be right and why the y axis offset is even bigger now on different devices. I'm thankful for any advice as I'm pretty new to iOS developing and I guess I'm missunderstanding something related to calculating correct sizes.
Turns out, that the solution to my problem is rather simple. I first started wondering when I saw that scrollView.bounds.size.height
returned a bigger value than the actual screen height on devices smaller than the iPhone X, which seemed pretty strange. Then I tried to figure out how to find the "real" size of my scrollView on different devices, because it is obviously not really bigger than the whole screen according to the simulator visual result.
So instead of doing the above quoted calculation inside viewDidLoad() doing all my calculation in viewDidLayoutSubviews() instead and this solved the whole problem.
The only thing I'm still wondering about is, why there was an offset even on the iPhone X as it was my default template in Xcode.
I'm making an app chat and I have a problem with the chat message's size.
I've calculate my message's height like this and I've got the correct height
maximumMessageWidth = 300.0
let size = CGSize(width: maximumMessageWidth, height: 1000.0)
let messageAttributeText = messageBody.attributedText
let height = messageAttributeText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil).height
To avoid the special case like this image. I have to calculate the width
It has the big space after my message
I want it to look like this:
This is the code I use to calculate the message width (I used the correct height which I've calculated the width)
let size = CGSize(width: 1000.0, height: height)
let messageAttributeText = messageBody.attributedText
var width = messageAttributeText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil).width
but width in this code seem not right. Because I think it does care about my height property. It assume that my text is in only 1 line.
But I want to calculate the width, so that my text will `fill the whole label' just like the second image
Does anyone know how to calculate the width in my case ?
You can do that by casting String to NSString
var string = "Hello, World"
let nsString = string as NSString
let size = nsString.size(attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 14)])
The size will give you width and height of the string.
You can apply this to your NSAttributedStrings string property.
After a bit of research, I find out this:
The calculate width code doesn't work right because it do not care about the height property.
If height = 100 or height = 1000 it will return the same result because it assume to draw all the text in just one line.
So to calculate the width, I used binary search
var minWidth:CGFloat = 0.0
var maxWidth = maxWidth
while true {
if (minWidth >= maxWidth) {
width = minWidth
break
}
let testWidth = (maxWidth + minWidth) / 2.0
if calculateMessageHeight(width: testWidth) > messageHeight {
minWidth = testWidth + 2.0
continue
} else {
maxWidth = testWidth - 2.0
continue
}
I have a UIScrollView which contains a UIImage. On top of that is a box that the user can move the image, so that that portion is cropped.
This screenshot explains it better:
So they can scroll the image around until the portion they want is inside that box.
I then want to be able to crop the scrollView/UIImage to exactly that size and store the cropped image.
It shouldn't be very hard but I've spent ages trying screenshots, UIGraphicsContext, etc. and cant seem to get anything to work.
Thanks for the help.
I finally figured out how to get it to work. Here is the code:
func croppedImage() -> UIImage {
let cropSize = CGSize(width: 280, height: 280)
let scale = (imageView.image?.size.height)! / imageView.frame.height
let cropSizeScaled = CGSize(width: cropSize.width * scale, height: cropSize.height * scale)
if #available(iOS 10.0, *) {
let r = UIGraphicsImageRenderer(size: cropSizeScaled)
let x = -scrollView.contentOffset.x * scale
let y = -scrollView.contentOffset.y * scale
return r.image { _ in
imageView.image!.draw(at: CGPoint(x: x, y: y))
}
} else {
return UIImage()
}
}
So it first calculates the scale of the imageView and the actual image.
Then it creates a CGSize of that crop box as shown in the photo. However, the width and height must be scaled by the scale factor. (e.g. 280 * 6.5)
You must check if the phone is running iOS 10.0 for UIGraphicsImageRender - if not, it won't work.
Initialise this with the crop box size.
The image must then be offset, and this is calculated by getting the scrollView's content offset, negating it, and multiplying by the scale factor.
Then return the image drawn at that point!
I'm trying to make some UIImageViews in Xcode that fill the screen based on different conditions. For example, I might have a 3x3 square of images that have to fill the screen, or a 4x4 square that must fill the screen, based on different initial conditions. Every time I try to accomplish this, the ImageViews just end up being the same size for both conditions. I've tried many different solutions but the one I'm currently trying is:
if fieldDimensions == 3 {
let spacing = screenWidth / 16
let boxsize = screenWidth / 4
let xadjust = spacing / 2 //Value to help align view
let interval = spacing + boxsize
Button1Image.translatesAutoresizingMaskIntoConstraints = false
button1height.constant = boxsize
button1width.constant = boxsize
button2height.constant = boxsize
button2width.constant = boxsize
}
else if fieldDimensions == 4 {
let spacing = screenWidth / 20
let boxsize = screenWidth * 3/16
let interval = spacing + boxsize
button1height.constant = boxsize
button1width.constant = boxsize
button2height.constant = boxsize
button2width.constant = box size
All of the button heights and widths are linked to the height and width constraints in the storyboard (I just control-dragged them). Any help would be really appreciated, I've been working on this problem for almost a week now, thanks!!
I'm trying to make a grid view on iOS with adaptive column width.
On Android it's possible to do this by setting stretchMode attribute to spacingWidth .
This attribute take the cell width as minimum width and grow cell automatically if there is free space available but no enough to add another column keeping the same space between column everywhere.
I didn't found any way to do that on iOS.
It look like that (left image) on iPhone 6, but on iPhone 5 (right image) the space is very big and ugly. I wan't to auto resize cells to avoid this big space.
How can i do that on iOS ?
(I'm using Xcode 6.1)
Thanks
EDIT :
This i why i wan't (black space is approximatively desired additional cell width, sorry my draw is ugly I did it quickly)
EDIT 2:
I tried to calculate new size with this code, but the result is "strange" (wrong size, position) , i think i missed something
let CELL_SIZE : Float = 92
let CELL_MARGIN : Float = 10
let COLLECTION_VIEW_MARGIN : Float = 20 //Left right margin
let screenWidth = Float(UIScreen.mainScreen().bounds.width)
let numberOfCell = Float(Int(screenWidth / (CELL_SIZE + CELL_MARGIN + COLLECTION_VIEW_MARGIN)))
let oldCellSize = Float(cell.frame.width)
var newCellSize : Float
if(numberOfCell >= 2){
newCellSize = (screenWidth / numberOfCell) - (CELL_MARGIN * (numberOfCell-1))
} else {
newCellSize = (screenWidth / numberOfCell) }
let indexPathRow = Float(indexPath.row)
var xOffsetMultiplier = indexPathRow % numberOfCell
if(xOffsetMultiplier == 0){
xOffsetMultiplier = numberOfCell
}
var newX : Float = 0
if(xOffsetMultiplier == 1){
newX = COLLECTION_VIEW_MARGIN / 2
} else {
newX = (newCellSize + CELL_MARGIN) * (xOffsetMultiplier-1) + (COLLECTION_VIEW_MARGIN / 2)
}
var frame = CGRectMake(CGFloat(newX), cell.frame.minY, CGFloat(newCellSize), cell.frame.height)
cell.frame = frame
This code is written in func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell in my ViewController
You should use UICollectionViewFlowLayout to adopt cell size according to collection view size.