I want to create layout for following layout inside collection view.
Align one cell in centre and two cell outside with scale down using transform.
I have used third party library DXScaleFlowLayout and implemented following code to make like same.
let scaleLayout = DXScaleFlowLayout()
scaleLayout.transformScale = 0
scaleLayout.isPagingEnabled = true
scaleLayout.minimumAlpha = 0.8
scaleLayout.minimumLineSpacing = 0
scaleLayout.minimumInteritemSpacing = 0
let width = self.cvBusinessPlans.bounds.width
let height = self.cvBusinessPlans.bounds.height
scaleLayout.itemSize = CGSize(width: width, height: height)
scaleLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
self.cvBusinessPlans.collectionViewLayout = scaleLayout
But it didn't work for me. If anyone know how to make this then please help. I have search of SOF, but I can't find exact or similar solution.
Related
I'm trying to implement a Chat screen using UICollectionView in Swift 4.2. I've done it.
I want to improve it by making the cells grow from bottom to top instead of top to bottom (while keeping the order of messages too). Any help? I've tried searching for it, still unsuccessful.
The easiest way would be to flip the collection view and its cells:-
cv.transform = CGAffineTransform(scaleX: 1, y: -1)
cell.contentView.transform = CGAffineTransform(scaleX: 1, y: -1)
Doing this will just flip your CollectionView's content and won't require you to handle anything, I guess
EDIT:-
For your requirement, you shouldn't be appending elements to your array. You should insert new objects as the first element of the array(the data source):-
myArray.insert(element, at: 0)
In order to get the right order, you can just reverse the array
You have to make collection view height constraint outlet for it and calculate your cells height after that you can set height of collectionView. and one case will come of maximum height, your collection height will equal from screen height with calculate space your navigation and input textview.
Have you tried
let diff = collectionView.frame.height - collectionView.contentSize.height
if diff > 0 {
collectionView.contentInset = UIEdgeInsets(top: diff, left: 0, bottom: 0, right: 0)
}
You can modify the top inset of the collection view as the collectionView reloads.
Call this after calling reloadData():
func updateCollectionContentInset() {
let contentSize = yourCollectionView.collectionViewLayout.collectionViewContentSize
var contentInsetTop = yourCollectionView.bounds.size.height
contentInsetTop -= contentSize.height
if contentInsetTop <= 0 {
contentInsetTop = 0
}
yourCollectionView.contentInset = UIEdgeInsets(top: contentInsetTop,left: 0,bottom: 0,right: 0)
}
Just as the following image, how to draw that black line?
I want the line to be drawn on layer, not on another view.
The problem I got is how to locate the bottom. Thanks for any suggestion.
Here i have used textfield same way you can use for button also
let borderOld = CALayer()
let width = CGFloat(1.5)
borderOld.frame = CGRect(x: 0, y: txtField.frame.size.height - width, width: txtField.frame.size.width, height: txtField.frame.size.height)
borderOld.borderWidth = width
txtField.layer.masksToBounds = true
txtField.layer.addSublayer(borderOld)
I implemented a UICollectionView with horizontal scrolling. My cells are simply thumbnails (UIImageView) with a size of 50x50.
let cvLayout = UICollectionViewFlowLayout()
cvLayout.sectionInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
cvLayout.itemSize = CGSize(width: 50, height: 50)
cvLayout.scrollDirection = .horizontal
All works fine, as long as the UICollectionView's height is above ca. 100. If I set its height any lower, the images don't appear anymore and the view looks messed up. I tried playing around with all available settings, nothing changes this.
Does the UICollectionView have a minimum height requirement or is this something I could solve with a Custom Layout?
I appreciate any hint!
Grasping a straws a little unless you update the question for more detail. I am going to say it is one of two things. But most likely the first.
1) You build your layout like in the current question but you never assign it.
let cvLayout = UICollectionViewFlowLayout()
cvLayout.sectionInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
cvLayout.itemSize = CGSize(width: 50, height: 50)
cvLayout.scrollDirection = .horizontal
//possibly not assigning it
collectionView.collectionViewLayout = cvLayout
2) you don't have constraints on your imageview but my guess is this is not the case.
Again, I am just taking a stab at it. If you comment below if neither of these fix the issue I will update the answer provided I have more information. I can set the height to 50 and it fits perfect.
I am trying to create a UIButton that contains a UIImage and text. So far I have managed to do that but I can't make it look pretty because the button width is half of the screen size (and this means the proportions are not right on big screens when I set the image)
Is there a way to position the Image exactly before the text Label in the button? Now I am doing this:
economicsButton.imageEdgeInsets = UIEdgeInsets(top: 15,left: 10,bottom: 15,right: 30)
economicsButton.titleEdgeInsets = UIEdgeInsets(top: 0,left: 0,bottom: 0,right: 0)
Try this
let somespace: CGFloat = 10
self.economicsButton.setImage(UIImage(named: "cross"), forState: UIControlState.Normal)
self.economicsButton.imageEdgeInsets = UIEdgeInsetsMake(0, self.economicsButton.frame.size.width - somespace , 0, 0)
print(self.economicsButton.imageView?.frame)
self.economicsButton.titleEdgeInsets = UIEdgeInsetsMake(0,(self.economicsButton.imageView?.frame.width)! + somespace, 0, 10 )
check the original answer Align image on right side
So if we want to stretch only parts of an image, be it a regular image or a background image, we use the following settings in layout editor:
How do you set those programmatically?
I'm using Xcode 7.2.1
Specifying the cap insets of your image
You can set the stretch specifics by making use of the UIImage method .resizableImageWithCapInsets(_:UIEdgeInsets, resizingMode: UIImageResizingMode).
Declaration
func resizableImageWithCapInsets(capInsets: UIEdgeInsets, resizingMode: UIImageResizingMode) -> UIImage
Description
Creates and returns a new image object with the specified cap insets
and options.
A new image object with the specified cap insets and resizing mode.
Parameters
capInsets: The values to use for the cap insets.
resizingMode: The mode with which the interior of the image is
resized.
Example: custom stretching using the specified cap insets
As an example, let's try to---programmatically---stretch my (current) profile picture along its width, precisely at my right leg (left side from viewing point of view), and leave the rest of the image with its original proportions. This could be comparable to stretching the width of some button texture to the size of its content.
First, let's load our original image foo.png as an UIImage object:
let foo = UIImage(named: "foo.png") // 328 x 328
Now, using .resizableImageWithCapInsets(_:UIEdgeInsets, resizingMode: UIImageResizingMode), we'll define another UIImage instance, with specified cap insets (to the middle of my right leg), and set resizing mode to .Stretch:
/* middle of right leg at ~ |-> 0.48: LEG :0.52 <-| along
image width (for width normalized to 1.0) */
let fooWidth = foo?.size.width ?? 0
let leftCapInset = 0.48*fooWidth
let rightCapInset = fooWidth-leftCapInset // = 0.52*fooWidth
let bar = UIEdgeInsets(top: 0, left: leftCapInset, bottom: 0, right: rightCapInset)
let fooWithInsets = foo?.resizableImageWithCapInsets(bar, resizingMode: .Stretch) ?? UIImage()
Note that 0.48 literal above corresponds to the value you enter for X in the interface builder, as shown in the image in your question above (or as described in detail in the link provided by matt).
Moving on, we finally place the image with cap insets in an UIImageView, and let the width of this image view be larger than the width of the image
/* put 'fooWithInsets' in an imageView.
as per default, frame will cover 'foo.png' size */
let imageView = UIImageView(image: fooWithInsets)
/* expand frame width, 328 -> 600 */
imageView.frame = CGRect(x: 0, y: 0, width: 600, height: 328)
The resulting view stretches the original image as specified, yielding an unproportionally long leg.
Now, as long as the frame of the image has 1:1 width:height proportions (328:328), stretching will be uniform, as if only fitting any image to a smaller/larger frame. For any frame with width values larger than the height (a:1, ratio, a>1), the leg will begin to stretch unproportionally.
Extension to match the X, width, Y and height stretching properties in the Interface Builder
Finally, to thoroughly actually answer your question (which we've really only done implicitly above), we can make use of the detailed explanation of the X, width, Y and height Interface Builder stretching properties in the link provided by matt, to construct our own UIImage extension using (apparently) the same properties, translated to cap insets in the extension:
extension UIImage {
func resizableImageWithStretchingProperties(
X X: CGFloat, width widthProportion: CGFloat,
Y: CGFloat, height heightProportion: CGFloat) -> UIImage {
let selfWidth = self.size.width
let selfHeight = self.size.height
// insets along width
let leftCapInset = X*selfWidth*(1-widthProportion)
let rightCapInset = (1-X)*selfWidth*(1-widthProportion)
// insets along height
let topCapInset = Y*selfHeight*(1-heightProportion)
let bottomCapInset = (1-Y)*selfHeight*(1-heightProportion)
return self.resizableImageWithCapInsets(
UIEdgeInsets(top: topCapInset, left: leftCapInset,
bottom: bottomCapInset, right: rightCapInset),
resizingMode: .Stretch)
}
}
Using this extension, we can achieve the same horizontal stretching of foo.png as above, as follows:
let foo = UIImage(named: "foo.png") // 328 x 328
let fooWithInsets = foo?.resizableImageWithStretchingProperties(
X: 0.48, width: 0, Y: 0, height: 0) ?? UIImage()
let imageView = UIImageView(image: fooWithInsets)
imageView.frame = CGRect(x: 0, y: 0, width: 600, height: 328)
Extending our example: stretching width as well as height
Now, say we want to stretch my right leg as above (along width), but in addition also my hands and left leg along the height of the image. We control this by using the Y property in the extension above:
let foo = UIImage(named: "foo.png") // 328 x 328
let fooWithInsets = foo?.resizableImageWithStretchingProperties(
X: 0.48, width: 0, Y: 0.45, height: 0) ?? UIImage()
let imageView = UIImageView(image: fooWithInsets)
imageView.frame = CGRect(x: 0, y: 0, width: 500, height: 500)
Yielding the following stretched image:
The extension obviously allows for a more versatile use of the cap inset stretching (comparable versatility as using the Interface Builder), but note that the extension, in its current form, does not include any user input validation, so it's up to the caller to use arguments in the correct ranges.
Finally, a relevant note for any operations covering images and their coordinates:
Note: Image coordinate axes x (width) and y (height) run as
x (width): left to right (as expected)
y (height): top to bottom (don't miss this!)