I am trying to create two drop down menu's side by side in swift. So far it consists of a UIView (created using a NIB) then two UIView's created in code that is used as a wrapper for the two UITableView's which will be displayed when the drop down menu is pressed. I have gotten the left hand menu (Leaderboard Menu) working perfectly but when I'm trying to create the 2nd menu the exact same way it is not displaying when the 2nd menu is pressed. For some reason if the x value of the frame is any more than 194 it is not displayed, my guess is that the 2nd menu is being added as a subview of the first but since the first's bounds is only 194 wide it is outside of the bounds to be displayed for that view. I will give a bit of code to show what I am trying to do. Thank you for any responses!
let leaderboardMenuFrame = CGRect(x: 0.0, y: 0.0, width: 194.0, height: leaderboardTableHeight)
let rankingMenuFrame = CGRect(x: 195.0, y: 0.0, width: 92.0, height: rankingTableHeight)
// Set up leaderboard DropdownMenu
self.leaderboardMenuWrapper = UIView(frame: leaderboardMenuFrame)
self.leaderboardMenuWrapper.clipsToBounds = true
self.leaderboardMenuWrapper.autoresizingMask = UIViewAutoresizing.FlexibleWidth.union(UIViewAutoresizing.FlexibleHeight)
// Set up ranking DropdownMenu
self.rankingMenuWrapper = UIView(frame: rankingMenuFrame)
self.rankingMenuWrapper.clipsToBounds = true
self.rankingMenuWrapper.autoresizingMask = UIViewAutoresizing.FlexibleWidth.union(UIViewAutoresizing.FlexibleHeight)
//Init Leaderboard menu table view
self.leaderboardMenuTableView = DropDownTableView(frame: CGRectMake(leaderboardMenuFrame.origin.x, leaderboardMenuFrame.origin.y + 0.5, leaderboardMenuFrame.width, leaderboardMenuFrame.height+300))
//Init Ranking menu table view
self.rankingMenuTableView = DropDownTableView(frame: CGRectMake(rankingMenuFrame.origin.x, rankingMenuFrame.origin.y + 0.5, rankingMenuFrame.width, rankingMenuFrame.height+300))
self.leaderboardMenuWrapper.addSubview(self.leaderboardMenuTableView)
self.rankingMenuWrapper.addSubview(self.rankingMenuTableView)
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
// Add Menu View to container view
view.addSubview(self.rankingMenuWrapper)
view.addSubview(self.leaderboardMenuWrapper)
addSubview(view)
I guess the issue is this line of code:
//Init Ranking menu table view
self.rankingMenuTableView = DropDownTableView(frame: CGRectMake(rankingMenuFrame.origin.x, rankingMenuFrame.origin.y + 0.5, rankingMenuFrame.width, rankingMenuFrame.height+300))
The origin of the rankingMenuTableView should be x = 0. But as you are using the rankingMenuFrame to init the frame of the rankingMenuTableView its origin would be x = 195. This will push your rankingMenuTableView out of bounds.
So the correct way to achieve what you want should be:
//Init Ranking menu table view
self.rankingMenuTableView = DropDownTableView(frame: CGRectMake(0, rankingMenuFrame.origin.y + 0.5, rankingMenuFrame.width, rankingMenuFrame.height+300))
Hope this helps.
Related
I'm trying to set the width and height of my child view controller's frame, but it's not working. Here's what I'm trying to do:
let frame = UIScreen.main.bounds
let vc = FieldsTableViewController()
addChild(vc)
view.addSubview(vc.view)
vc.didMove(toParent: self)
vc.view.frame = CGRect(x: (frame.maxX+frame.minX)/2, y: 300, width: 200, height: 5)
The x and y positions are correctly set, but no matter what I try I can't seem to set the width and the height. The weird thing is that I am using the same child vc in another vc, with the exact same code as above, and I have no problem setting the width and height there.
I also tried using Auto-Layout but was not able to make it work for a child view controller (is that possible? I didn't find any example).
Thanks for your help.
I found a way around it.
I finally realized that the issue occurs when I set the view of my view controller, like so :
let v = PlayerSelectionView()
view = v
I'm not sure why that caused the problem described, but adding my view as a subview instead fixed it:
let v = PlayerSelectionView()
v.frame = view.frame
view.addSubview(v)
Now I'm able to edit the width and height of my child view controllers.
I want to display my upload progress of a file in the table view cell.
I am using Progress View programatically for the same. However, the progress view overlaps the file name and its related data. How can I make the progress view appear behind the text?
Following is the code used:
let animationProgress = UIProgressView(progressViewStyle: .bar)
var prog: Float = 0.0
animationProgress.progress += 0.5
animationProgress.rightAnchor.accessibilityActivate()
animationProgress.tintColor = .dbbSearchBarBackgroundColor()
animationProgress.setProgress(prog, animated: true)
perform(#selector(updateProgress), with: nil, afterDelay: 1.0)
animationProgress.frame = CGRect(x: 0, y: 0, width: prog, height: 85)
animationProgress.transform = animationProgress.transform.scaledBy(x: 1, y: 85)
self.contentView.addSubview(animationProgress)
Actual tableview cell :
Progress view getting overlapped :
The issue you're having is related to the order of subviews. I'm not sure what cell you are you using how and when do you add other labels. But it looks like you need to send the UIProgressView to the back.
In your case the fix should be after calling self.contentView.addSubview(animationProgress) make sure to send the subview to the back which means calling self.contentView.sendSubviewToBack(animationProgress).
I have a uiview that is overlaying and blocking interaction with my view on top of the superview. I've tried bringing the blocked view to the front but that doesn't work either.
Here's the code for the blocking view:
self.gesstureView = UIView(frame: screenBounds)
if let gestureView = self.gesstureView, let controlDockView = self.controlDockView, let controlTopView = self.controlTopView {
gestureView.autoresizingMask = [.flexibleWidth, .flexibleBottomMargin]
gestureView.frame.size.height -= controlDockView.frame.height
gestureView.contentMode = .center
gestureView.backgroundColor = UIColor.red
self.view.addSubview(gestureView)
Heres the code for the view that's blocked:
let topHeight = screenBounds.height * 0.15
self.controlTopView = UIView(frame: CGRect(x: 0, y: 0, width: screenBounds.width, height: topHeight))
if let controlTopView = self.controlTopView {
controlTopView.backgroundColor = UIColor.clear
controlTopView.autoresizingMask = [.flexibleTopMargin]
controlTopView.addBlurEffect()
self.view.addSubview(controlTopView)
// does not work view is still hidden
self.view.bringSubview(toFront: controlTopView)
Thanks for the sample code!
The problem is that you add your gestureView to the view hierarchy after you brought controlTopView to front. So controlTopView will actually be the second view this is why it is not visible.
To solve the problem either add controlTopView lastly or bring it to the front after you've added everything.
view.addSubview(previewView)
view.addSubview(controlDockView)
view.addSubview(gestureView)
view.addSubview(controlTopView)
Just in case -- have you checked if your controlTopView is not visible simply because it has nothing visible to draw? In your code snippet, the controlTopView only has a transparent background color and a blur effect (which wouldn't do anything to the solid red behind it).
The best way to really see whats going on is to use the UI debugger in Xcode. It will show you what is obscuring what. Also, it is very likely that the UIViews are being drawn in an order you are not anticipating.
You should resize and select the hidden view....if its actually there.
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'm writing an iOS app which has multiple labels in one view, like shown:
I would like these labels to be in the vertical centre of the view, with the middle of the collection of labels as the centre of the view.
I need to use auto layout for this, as the top label may be multiple lines, or may only be one depending on input, and will change height depending on this. This, along with the top label being a different size, means that I cannot simple have the middle label in the middle, and the others relative to that.
I'm looking for a solution either in code or IB.
EDIT: To clarify, I am looking to centre the middle of multiple labels, like so:
(The vertical middle might be slightly off)
*The image should read vertical middle
This is an old question of mine, but it maintains a fair number of views, and is quite a common use-case. I do not feel the other answer is a very efficient method to achieve this.
The easiest method to centre a collection of views is to place them within a UIView object which is itself centred.
To use the example above, the three UILabels would be within one UIView, with a 0 constraint between the top and bottom labels and the View. The view itself would then be set to be centred vertically.
I don't think there is a way to do this with Auto Layout, but you can code. I'm assuming you've already figured out the spacing of the labels, so I'll just help you center the whole thing.
var o1 = label1.frame.origin
var o4 = label4.frame.origin
var h4 = label4.frame.height
var w4 = label4.frame.width
var hc4 = o4.y + h4
var wc4 = o4.x + w4
var screen = UIScreen.mainScreen().bounds.size.height
var remainingScreen = (screen - (hc4 - o1.y))/2.0
var screenW = UIScreen.mainScreen().bounds.size.width
var remainingScreenW = (screenW - (wc4 - o1.x))/2.0
var moveH = remainingScreen - o1.y
var moveW = remainingScreenW - o1.x
var frame1 = label1.frame
var frame2 = label2.frame
var frame3 = label3.frame
var frame4 = label4.frame
label1.frame = CGRect(x: frame1.origin.x + moveW, y: frame1.origin.y + moveH, width: frame1.width, height: frame1.height)
label2.frame = CGRect(x: frame2.origin.x + moveW, y: frame2.origin.y + moveH, width: frame2.width, height: frame2.height)
label3.frame = CGRect(x: frame3.origin.x + moveW, y: frame3.origin.y + moveH, width: frame3.width, height: frame3.height)
label4.frame = CGRect(x: frame4.origin.x + moveW, y: frame4.origin.y + moveH, width: frame4.width, height: frame4.height)
This whole thing isn't very self explanatory, but I won't talk about what every line does. The overall idea is it finds the distance between the upper left and lower right corner of all the labels (so UL of label1 and LR of label4 [this only works if you've already set the spacing between labels and the width/height of each label]), then it finds the width/height (W/H) of the screen and subtracts the W/H of the label area, divides by two, giving the space between the top of the screen and the labels. Finally, it finds the distance the entire assembly needs to move by comparing the UL corner with where it should be, and combines the amount to be moved with the original location of all the labels.
Note: This code could be heavily condensed, it is just easier to view and read if it is written like this.