How do I remove all subviews in Rubymotion? - ios

Basically, I have a quiz app where I add have questions, then switch to a different screen to show an expanded version of the correct answer after it is chosen. I've tried adding button and labels, but when I do this, I eventually end up with buttons and labels 'ghosting' on the screen, after I went them gone. How can I remove all subviews, so that each button and label I add from within a method appears on a fresh screen?
class MyApplicationController < UIViewController
def loadView
self.view = UIImageView.alloc.init
end
def viewDidLoad
super
view.userInteractionEnabled=true
#question_index=0
#answerChoices = []
#questionChoices=["What is best in life?",...]
makeQuestion
end
def makeQuestion
left =20
top=100
label = UILabel.new
label.text =#questionChoices[#question_index]
label.textAlignment = UITextAlignmentCenter
label.textColor = UIColor.redColor
label.frame = [[20,20], [view.frame.size.width-40, 40]]
label.lineBreakMode = UILineBreakModeWordWrap
label.numberOfLines = 0
label.sizeToFit
view.image = UIImage.imageNamed('background.jpg')
view.addSubview(label)
4.times do |i|
#button = UIButton.buttonWithType(UIButtonTypeRoundedRect)
#button.setTitle(#answerChoices[i][#question_index], forState:UIControlStateNormal)
#button.frame = [[left, top], [view.frame.size.width - left * 2, 40]]
#button.addTarget(self, action:'actionTapped:', forControlEvents:UIControlEventTouchUpInside)
#button.tag=i
top+=45
view.addSubview(#button)
end
end
def makeAnswer
#button.removeFromSuperview
#button.removeFromSuperview
#button.removeFromSuperview
#button.removeFromSuperview
view.image = UIImage.imageNamed('back.jpg')
label = UILabel.new
label.text =#rightArray[#question_index]
label.textAlignment = UITextAlignmentCenter
label.textColor = UIColor.blackColor
label.frame = [[20,20], [view.frame.size.width-40, 40]]
label.lineBreakMode = UILineBreakModeWordWrap
label.numberOfLines = 0
label.sizeToFit
view.addSubview(label)
#button = UIButton.buttonWithType(UIButtonTypeRoundedRect)
#button.setTitle("More questions", forState:UIControlStateNormal)
#button.tag=1
#button.addTarget(self, action:'makeQuestion', forControlEvents:UIControlEventTouchUpInside)
#button.frame = [[20, 100], [view.frame.size.width - 20 * 2, 40]]
view.addSubview(#button)
end
end

You need an array of buttons. In your 4.times loop, you are overwriting the instance variable #button four times. Instead, make #button an array of buttons, and assign a different button to each index.
If you have a variable myView and want to remove all of its subviews, I believe this will work:
myView.subviews.each {|sv| sv.removeFromSuperview}

Related

Wrapping text on TitleLabel and DetailLabel - Material Card

I am using CosmicMind - Material Framework to create a Card. titleLabel and DetailLabel do not wrap to a new line.
My question is: What do I need to do to accomplish such task and is it supposed to be automatically adjusted by the framework?
This is what I have so far:
let card = Card()
var heartIcon = IconButton()
heartIcon = IconButton(image: Icon.favoriteBorder, tintColor: Color.red.base)
//Title Bar
let toolbar = Toolbar(rightViews: [heartIcon])
toolbar.title = cardData.cardTitleText
toolbar.titleLabel.textAlignment = .left
toolbar.titleLabel.numberOfLines = 0
toolbar.detail = "Company: " + cardData.cardTitleSubtitle
toolbar.detailLabel.font = RobotoFont.regular(with: 14)
toolbar.detailLabel.textColor = Color.grey.base
toolbar.detailLabel.textAlignment = .left
toolbar.detailLabel.numberOfLines = 0
And this is my output:
Update:
I managed to achieve what I wanted by increasing the size of the toolbar frame.
toolbar.frame = CGRect(x:0,y:0,width: view.frame.width,height: 100)
My goal was to at least show 2 lines of text.
Thanks!
I have no experience with the CosmicMind framework but usually, the label.numberOfLines property defines the maximum number of lines that the label text can have. You can set it to 2 instead of 0 and it should wrap.

How to force word wrapping of UILabel that adjusts font size and is multiline

The problem I am facing is that UILabel will break line in the middle of the word although I am using word wrapping.
You can create a new project and replace content of view controller to see the result:
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))
label.center = CGPoint(x: view.frame.midX, y: view.bounds.midY)
label.numberOfLines = 2 // Setting this to 1 produces expected result
label.lineBreakMode = .byWordWrapping
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.5
view.addSubview(label)
label.text = "Singlewordtext"
label.backgroundColor = .red
}
This produces 2 lines of text which is broken in the middle of the word. The reason this naturally happens is because the word itself is wider than the label itself so it makes sense (I guess). But I would hope that it would use adjustsFontSizeToFitWidth and minimumScaleFactor prior to breaking it. If I set it to single line (label.numberOfLines = 1) I get expected result which is that the text will shrink instead of break. Note that doing so in this case will fit all of the text inside the label.
The question is, is there a configuration on UILabel to prevent line break in such case? Or is there some other elegant solution?
A current result:
Desired result (produced by using label.numberOfLines = 1):
Do note that I still do need to have 2 lines enabled to nicely display for instance label.text = "Three words fit".

UILabel not respecting truncate

This is puzzling me for a while. This is my code:
let label:UILabel = UILabel(frame: CGRectMake(0, 0, obTextRect.width, obTextRect.height))
label.text = stText
label.backgroundColor = UIColor.redColor()
label.textAlignment = NSTextAlignment.Center
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.ByTruncatingTail
label.font = obDrawItem.m_obFont
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.1
label.layer.drawInContext(obContext)
CGContextRestoreGState(obContext)
and this is the result I am getting...
proceedin
g
The word "proceeding" does not "auto shrink" to fit the width.
Also if I add a line break (\n) then it works ok.
Any ideas???
The code works absolutely correctly. Why?
The text doesn't shrink because it fits into its frame.
The text doesn't use truncation because it fits into its frame.
Word wrapping is ignored because the word doesn't fit into single line.
I would advise you to set wrapping properties dynamically, depending on content. If the text has only one word, then set numberOfLines to 1, otherwise set it to 0 or 2-3. That will fix most of your problems.
let multipleWords = stText.rangeOfCharacterFromSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) != nil
label.numberOfLines = multipleWords ? 0 : 1
Try this:
label.numberOfLines = 1
Setting numberOfLines to 0 makes the label multi-line.

Line Breaks and Number of Lines in Swift Label (Programmatically)

By selecting a Label in a StoryBoard, I can select Line Break to be Word Wrap and change number of lines to be more than 1. How can I do that Programmatically in Swift?
You can do this to set it programmatically
label.lineBreakMode = NSLineBreakMode.ByWordWrapping
label.numberOfLines = 3
Swift 3/4
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 3
If you want the label to have multiple lines, do this:
var myLabel:UILabel = UILabel(frame: CGRectMake(7, 200, 370, 100))
myLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
myLabel.numberOfLines = 0 //'0' means infinite number of lines
Do remember to increase the height in "CGRectMake(7, 200, 370, 100)" <-- This
Otherwise the label won't be able to take the multiple lines of text.
Note with Swift 3 you need to use updated method byWordWrapping
productNameLabel.lineBreakMode = .byWordWrapping
productNameLabel.numberOfLines = 1
Or for adding Ellipsis at the end use byTruncatingTail
productNameLabel.lineBreakMode = .byTruncatingTail
productNameLabel.numberOfLines = 1

Adding UIScrollView to table cell seems to affect table scroll performance

I'm not sure this was poor implementation or a poor decision to start with, but I'm attempting to add a horizontal UIScrollView inside of each cell within my UITableView. I add it is as a subview to the cell's contentView, then call cell.clipsToBounds = true (FYI, I'm using RubyMotion). When I tap a button on the cell, I use beginUpdates/endUpdates to trigger heightForRowAtIndexPath to expand the cell's height and show the "hidden" scrollview.
Anyway, since doing that my table's scroll is a bit sluggish. I've added my code below and am wondering if my implementation can be improved to fix that scroll performance. Any help/insight is helpful (though if possible I'd like to try and keep the scroll views).
my_array = [
["Hi", "there", "one"],
["Hi", "there", "two"],
["Hi", "there", "three"],
["Hi", "there", "four"],
]
scroll_frame = CGRectMake(
0, rowHeight - 1, hidden_width, 51
)
hidden_scroll = UIScrollView.alloc.initWithFrame(scroll_frame)
hidden_scroll.alwaysBounceHorizontal = true
hidden_scroll.bounces = true
hidden_scroll.contentSize = CGSizeMake(hidden_width * my_array.size, scroll_frame.size.height)
hidden_scroll.delegate = parent
hidden_scroll.clipsToBounds = true
hidden_scroll.pagingEnabled = true
hidden_scroll.showsHorizontalScrollIndicator = false
hidden_scroll.layer.borderWidth = 1
hidden_scroll.layer.borderColor = UIColor.colorWithRed(200.0/255, green:200.0/255, blue:200.0/255, alpha: 1).CGColor
hidden_scroll.backgroundColor = UIColor.colorWithRed(248.0/255, green:248.0/255, blue:248.0/255, alpha: 1)
hidden_scroll.scrollEnabled = false
my_array.each_with_index do |data, index|
hidden_view = UIView.alloc.initWithFrame(CGRectMake(
(parent.view.frame.size.width * index), 0, parent.view.frame.size.width, 50
)
)
label_frame = CGRectMake(
40, 5, (parent.view.frame.size.width - 40 - 7) * 2/3, 40
)
label = UILabel.alloc.initWithFrame(label_frame)
label.font = UIFont.boldSystemFontOfSize(11)
label.backgroundColor = UIColor.clearColor
label.text = data[0]
label.numberOfLines = 0
label.lineBreakMode = UILineBreakModeWordWrap
label_size = data[0].sizeWithFont(label.font)
label.sizeToFit
new_frame = label.frame
new_frame.origin.y = (50 - label.frame.size.height) / 2
new_frame.size.height = label.frame.size.height
label.frame = new_frame
button = UIButton.buttonWithType(UIButtonTypeCustom)
button.backgroundColor = UIColor.orangeColor
button.font = UIFont.systemFontOfSize(11)
button.setTitle(data[3].upcase, forState:UIControlStateNormal)
button.setTitleColor(UIColor.whiteColor, forState:UIControlStateNormal)
button.layer.cornerRadius = 2.0
button.instance_variable_set(:#data, data)
button_size = data[3].upcase.sizeWithFont(button.font)
button.frame = [
[label.frame.origin.x + label_frame.size.width + 5, (50 - label_size.height) / 2 - 3],
[80, button_size.height + 6]
]
button.addTarget(parent, action:"add_user_goal:", forControlEvents:UIControlEventTouchUpInside)
hidden_view.addSubview(label)
hidden_view.addSubview(button)
hidden_scroll.insertSubview(hidden_view, belowSubview: cell.contentView)
end
Since the UIScrollView isn't in view anyway, try creating the UIScrollView only when the user taps the cell to view it. Before then, there's just an empty area of the cell.
For cleaner code, I'd also recommend subclassing UIScrollView and doing your customization in a custom initializer.
class CellScrollView < UIScrollView
def initWithCustom(args={})
self.initWithFrame(args[:frame])
# ... all your customizations. Use the args hash to pass in any other data you need.
self
end
end

Resources