Ok as the question suggests, I want to make a menu like the spotify app currently have.
I have come across a code in github that resembles this but i want to know how to achieve this on a DIY(Do it yourself) level.
I can understand that a pageview controller is needed but am lost. Please point me to the right direction.
EDIT
So that people might understand properly the requirement I am talking about, Here is a png
Notice the top menu that slides with the underline as the selected menu.
The github link that i posted is a library that does that, but its in swift, so can anyone tell me as to how to achieve this in objective c
Regards
I have made a similar kind of sample but that is in Swift 2.0. Have a look. May be it can be of some help.
In the sample link posted below, the query you are asking can be done in the following way.
We can use this method to setup the buttons first on the top of page view
In your terms this is the Top Menu
func setupSegmentButtons(){
navigationView = UIView(frame: CGRectMake(0, 0, self.view.frame.size.width, (self.navigationController?.navigationBar.frame.size.height)! - 4))
//navigationView.backgroundColor = UIColor.redColor()
navigationView.layoutIfNeeded()
let numControllers:NSInteger = viewControllerArray.count
if(buttonText == nil)
{
buttonText = NSArray(objects: "First","Second","Third")
}
let buttonWidth:CGFloat = self.view.frame.size.width/CGFloat(numControllers)
for (var i = 0; i < numControllers; i++) {
let button:UIButton = UIButton(frame: CGRectMake( CGFloat(i) * buttonWidth, 0, buttonWidth, 40))
button.addTarget(self, action: "tapSegmentButtonAction:", forControlEvents: .TouchUpInside)
navigationView.addSubview(button)
button.tag = i
button.titleLabel?.font = UIFont(name: "Helvetica", size: 14)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.setTitle(buttonText.objectAtIndex(i) as? String, forState: .Normal)
}
self.view.addSubview(navigationView)
self.setupSelector()
}
Now we have to add the selection bar which will slide accordingly with the menu selected.
Setting up the selection bar view
func setupSelector(){
//selection bar view
selectionBar = UIView(frame: CGRectMake(X_BUFFER - X_OFFSET + SELECTED_POSITION , SELECTOR_Y_BUFFER, (self.view.frame.size.width - 2 * X_BUFFER)/CGFloat(viewControllerArray.count), SELECTOR_HEIGHT))
selectionBar.backgroundColor = UIColor.brownColor()
selectionBar.alpha = 0.8
navigationView.addSubview(selectionBar)
}
Now we can use the scroll view's scrollViewDidScroll delegate in order to make the selection bar view slides towards the selected menu. Each time this delegate is called whenever the page view controller is scrolled, we change the frame of selected bar view every moment.
func scrollViewDidScroll(scrollView: UIScrollView) {
let xFromCenter : CGFloat = self.view.frame.size.width-scrollView.contentOffset.x;
let xCoors : CGFloat = X_BUFFER + selectionBar.frame.size.width * CGFloat(currentPageIndex) - X_OFFSET
_ = selectionBar.frame
if(CGFloat(xCoors)-xFromCenter / CGFloat(viewControllerArray.count) > self.view.frame.size.width - selectionBar.frame.width)
{
selectionBar.frame = CGRectMake(self.view.frame.size.width - selectionBar.frame.width, selectionBar.frame.origin.y, selectionBar.frame.size.width, selectionBar.frame.size.height);
}
else if(CGFloat(xCoors)-xFromCenter / CGFloat(viewControllerArray.count) < 0)
{
selectionBar.frame = CGRectMake(0, selectionBar.frame.origin.y, selectionBar.frame.size.width, selectionBar.frame.size.height);
}
else
{
selectionBar.frame = CGRectMake(CGFloat(xCoors)-xFromCenter/CGFloat(viewControllerArray.count), selectionBar.frame.origin.y, selectionBar.frame.size.width, selectionBar.frame.size.height);
}
}
For more details please see the sample link below.
https://github.com/RajanMaheshwari/PageViewController
Related
My scenario, I am trying to create centre circle button in UITabbarViewController. I tried many sample but not getting output like below Image. Please provide some code to achieve this. I am using storyboard for this.
sample Image
You need to do is your UITabbarViewController must contain five tabs in bottom tab bar that you can do by adding five view controller and make sure the middle tab contain no title and icon.
After that in onCreate method of your UITabbarViewController add this custom button Code -
let button = UIButton(type: .custom)
var toMakeButtonUp = 40
button.frame = CGRect(x: 0.0, y: 0.0, width: 65, height: 65)
button.setBackgroundImage(ADD, for: .normal)
button.setBackgroundImage(ADD, for: .highlighted)
let heightDifference: CGFloat = CGFloat(toMakeButtonUp)
if heightDifference < 0 {
button.center = tabBar.center
} else {
var center: CGPoint = tabBar.center
center.y = center.y - heightDifference / 2.0
button.center = center
}
button.addTarget(self, action: #selector(btnTouched), for:.touchUpInside)
view.addSubview(button)
FYI - toMakeButton is the margin from bottom you can set it accordingly.
and #selector(btnTouched) is the function defined in class which will perform on click on the button.
I have 4 buttons in a UIViewController in XCode. I already added code to them so I would prefer to keep the buttons. I want to have the buttons side by side in the view where there is only one button on the screen at a time and the edge of the other buttons on the edge of the screen. Where you can just barely see them. I wanted to know how would I be able to accomplish this? If you need more information than this just let me know?
var scrollView: UIScrollView!
private func addButton() {
for index in 0...2{
let button = UIButton()
let x = scrollView.frame.size.width * CGFloat(index)
button.frame = CGRect(x: x, y: 0, width: scrollView.frame.width, height: self.view.frame.height)
button.backgroundColor = UIImage(named: ColorArr[index])
scrollView.contentSize.width = scrollView.frame.size.width * CGFloat(index + 1)
scrollView.addSubview(button)
}
}
You can call this function in viewDidLoad() and i took color array to differentiate buttons
i wanted to make my UITabBarItem's size Bigger then other buttons so i tried this in Subclass of TabBarController :
var button = UIButton(type: .Custom)
button.frame = CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height)
button.setBackgroundImage(buttonImage, forState: .Normal)
button.setBackgroundImage(highlightImage, forState: .Highlighted)
var heightDifference: CGFloat = buttonImage.size.height - self.tabBar.frame.size.height
if heightDifference < 0 {
button.center = self.tabBar.center
}
else {
var center = self.tabBar.center
center.y = center.y - heightDifference / 2.0
button.center = center
}
self.view.addSubview(button)
it worked fine cause now i have a Button on top of my BarButtonItem (expected Behavior ) but now this new button is blocking the TouchEvents which supposed to handle by barbuttonitem , any idea how can i solve this problem ?? i followed this article for getting this newButton:
what i want is look like this :
SOLVED:
All i needed was to disable the user interaction for my button.
you can try below code for your UIButton Clicked event e.g.
-(void)clickedEvent:(id)sender{
.... some code
[self.tabBarController setSelectedIndex:2];
..... some code
}
Hopefully, It should work.
self.tableView.tableFooterView = PromptInviteView.instantiateFromNib()
I've tried putting this in viewWillAppear and viewDidLoad.
Great, everything shows up and displays correctly.
However, if:
I push HOME and open 4-5 other apps, then return back to my app, the footer will "jump" to the top, covering the first row.
If I perform other actions inside the app (navigating back and forth), and then finally going back to his vc, then it will jump to the top also.
When I pull to refresh, all is good again. But if I don't do anything...the footer stays at the top (replacing the top row + is not clickable)
Does anyone know why this behavior is occurring, and how I can solve it?
Update: I realize that "drawRect" in my xib gets called when I open the app after 4-5 other apps. And this is why the problem is happening.
In my drawRect code, I have this:
override func drawRect(rect: CGRect) {
super.drawRect(rect)
inviteLabel.textColor = UIColor(hex: 0x404040)
inviteLabel.text = STRINGS["PromptInviteLabelText"]
inviteLabel.numberOfLines = 0
inviteLabel.sizeToFit()
inviteButton.setTitle(STRINGS["PromptInviteButtonText"], forState: UIControlState.Normal)
inviteButton.backgroundColor = FlatWatermelon()
inviteButton.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
inviteButton.setTitleColor(UIColor(hex: 0xcccccc), forState: UIControlState.Selected)
inviteButton.layer.cornerRadius = 2.0
inviteButton.clipsToBounds = true
super.layoutSubviews() //this will allow the view's frame to be set.
var padding = CGFloat(20.0)
self.frame = CGRectMake(0, 0, screenWidth, CGRectGetMaxY(inviteButton.frame) + padding )
var topBorder = UIView()
topBorder.frame = CGRectMake(0, 0, screenWidth, 0.5)
topBorder.backgroundColor = UIColor(hex: 0xededed)
self.addSubview(topBorder)
var bottomBorder = UIView()
bottomBorder.frame = CGRectMake(0, self.frame.size.height, screenWidth, 0.5)
bottomBorder.backgroundColor = UIColor(hex: 0xededed)
self.addSubview(bottomBorder)
}
How can I remove my code (especially the layoutSubview part) and put it somewhere else?
Is there another location where I should put the code? Is there a didLayoutSubviews() equivalent?
I have a weird issue that I just found out when I re-installed and launched my project first time on Simulator
My main ViewController has a collection view that will show a list of recipes. After a recipe is added and navigated back to this screen, the list will reflect the update.
There is also a ScrollView that appears when recipe.count > 0 with subview containing buttons (to filter list by category). The scrollview reflect the update on the recipes but it won't work on the very first launch in Simulator.
I've tried reloading collectionview, fetching recipe data on viewDidAppear, viewWillAppear but no luck with the first-time launch.
How can I make sure the first app launch experience is the same with the subsequent launches? Is there any known issue with first-time launch on Simulator that I should know about?
Here is the code that creates buttons and add to ScrollView.
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
fetchRecipe()
collection.reloadData()
if recipes.count == 0 {
categoryScrollView.hidden = true
categoryScrollViewHeight.constant = 0
} else {
populateCategoryScrollView()
}
}
func populateCategoryScrollView() {
//Create category sort buttons based on fetched category.name and add to scrollview
if recipes.count > 0 {
var categories: [String] = []
for recipe in recipes {
if let value = recipe.category {
let category = value as! RecipeCategory
categories.append(category.name!)
}
}
var distinctCategories = Array(Set(categories))
var widthStack = 0
if distinctCategories.count != 0 {
for subView in categoryScrollView.subviews {
subView.removeFromSuperview()
}
for i in 0..<distinctCategories.count {
//Pilot button creation to get width
let frame1 = CGRect(x: 0, y: 6, width: 80, height: 40 )
let button = UIButton(frame: frame1)
button.setTitle("\(distinctCategories[i])", forState: .Normal)
button.sizeToFit()
let buttonWidth = Int(button.frame.size.width)
var frame2: CGRect
if i == 0 {
frame2 = CGRect(x: 10, y: 6, width: buttonWidth+20, height: 30 )
} else {
frame2 = CGRect(x: 10 + widthStack, y: 6, width: buttonWidth+20, height: 30 )
}
widthStack += buttonWidth+32
let button1 = UIButton(frame: frame2)
let attributedTitle = NSAttributedString(string: "\(distinctCategories[i])".uppercaseString, attributes: [NSKernAttributeName: 1.0, NSForegroundColorAttributeName: UIColor.blackColor()])
button1.setAttributedTitle(attributedTitle, forState: .Normal)
button1.titleLabel!.font = UIFont(name: "HelveticaNeue", size: 13.0)
button1.layer.borderWidth = 2.0
button1.layer.borderColor = UIColor.blackColor().CGColor
button1.backgroundColor = UIColor.whiteColor()
button1.addTarget(self, action: "filterByCategory:", forControlEvents: UIControlEvents.TouchUpInside)
self.categoryScrollView.addSubview(button1)
}
}
}
}
The first time you enter the application, the recipes.count is 0, so you are hiding the scroll view by the constraint categoryScrollViewHeight.constant = 0. So next time you create a new recipe, the scroll view is still with a zero height. That's why you didn't see the scroll on first time launch.