How to add Read more/less in Paragraph with Swift 3? - text

I have a problem with adding Read More/Less text in paragraph. That text needs in iPod but no need for iPad. Please view the attached image below.
The first problem is that before I clicking "Read More" button, there is a space at the top left corner. When I click on Read More button, the label is goes to top and there is no space.
The second problem is that Read More button does not require if the device is iPad because the screen size is big and all the texts are show.For iPod, it needs to have that button.
Here is my code.
func getLabelHeight(text: String, width: CGFloat, font: UIFont) -> CGFloat {
let lbl = UILabel(frame: .zero)
lbl.frame.size.width = width
lbl.font = font
lbl.numberOfLines = 0
lbl.text = text
lbl.sizeToFit()
return lbl.frame.size.height
}
#IBAction func btnReadMore(_ sender: Any) {
if isLabelAtMaxHeight {
btnReadmore.setTitle("Read more", for: .normal)
isLabelAtMaxHeight = false
lblReviewHeight.constant = 93
}
else {
btnReadmore.setTitle("Read less", for: .normal)
isLabelAtMaxHeight = true
lblReviewHeight.constant = getLabelHeight(text: lblReview.text!, width: view.bounds.width, font: lblReview.font)
}
}
How can I check this when Read button is require or not? Please help me. I don't want to add any other library file.

You can Identify the device using following code (get it from here)
import UIKit
public extension UIDevice {
var modelName: String {
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let identifier = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
switch identifier {
case "iPod5,1": return "iPod Touch 5"
case "iPod7,1": return "iPod Touch 6"
case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4"
case "iPhone4,1": return "iPhone 4s"
case "iPhone5,1", "iPhone5,2": return "iPhone 5"
case "iPhone5,3", "iPhone5,4": return "iPhone 5c"
case "iPhone6,1", "iPhone6,2": return "iPhone 5s"
case "iPhone7,2": return "iPhone 6"
case "iPhone7,1": return "iPhone 6 Plus"
case "iPhone8,1": return "iPhone 6s"
case "iPhone8,2": return "iPhone 6s Plus"
case "iPhone9,1", "iPhone9,3": return "iPhone 7"
case "iPhone9,2", "iPhone9,4": return "iPhone 7 Plus"
case "iPhone8,4": return "iPhone SE"
case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2"
case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad 3"
case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad 4"
case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air"
case "iPad5,3", "iPad5,4": return "iPad Air 2"
case "iPad2,5", "iPad2,6", "iPad2,7": return "iPad Mini"
case "iPad4,4", "iPad4,5", "iPad4,6": return "iPad Mini 2"
case "iPad4,7", "iPad4,8", "iPad4,9": return "iPad Mini 3"
case "iPad5,1", "iPad5,2": return "iPad Mini 4"
case "iPad6,3", "iPad6,4", "iPad6,7", "iPad6,8":return "iPad Pro"
case "AppleTV5,3": return "Apple TV"
case "i386", "x86_64": return "Simulator"
default: return identifier
}
}
}
// Swift 3
let modelName = UIDevice.current.modelName
Then you can use if,else ..
if(modelName == iPad 3 || modelName == iPad 4 ||modelName == iPad Air){
// No Read More button
}else{
// Add Read More button
}

Related

Tab to next text field when 'next/return' key hit on keyboard in SwiftUI

This is strictly for SwiftUI.
I would like to have the keyboard move to the next available text field when the user hits the 'return' key on the keyboard.
I have the following view:
var body: some View {
VStack {
NavigationView {
Form {
TextField("First name", text: $model.firstname)
.tag(1)
TextField("Last name", text: $model.lastname)
.tag(2)
}
.navigationBarTitle("Add a Person", displayMode: .inline)
}
}
}
And the following code that should allow the tab:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let nextTag = textField.tag + 1
if let nextResponder = textField.superview?.viewWithTag(nextTag) {
nextResponder.becomeFirstResponder()
} else {
textField.resignFirstResponder()
}
return true
}
I am just not sure how to implement it in SwiftUI?
How do I assign it to the delegate of the textfield?!
****UPDATE****
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
print("Current Tag: ", textField.tag) // Works correctly
let nextTag = textField.tag + 1
print("Next Tag: ", nextTag) // Works correctly
let nextResponder = textField.superview?.viewWithTag(nextTag) as UIResponder? // ALWAYS RETURN NIL
....
Not sure why the assignment of nextResponder always returns nil?!
iOS15+
Now it can be easily done with FocusState+.focused(,equals:) specifying named tags and updating focus state on needed action.
Tested with Xcode 13.3 / iOS 15.4
Here is main part:
#FocusState private var infocus: Field?
enum Field {
case first, last
}
// ...
TextField("First name", text: $firstname,
onCommit: { infocus = .last }) // << here !!
.focused($infocus, equals: .first)
Complete test module in project is here

SwiftUI SystemColors for Lists

I have a list in witch I want to highlight a selected line.
This works fine with:
struct ContentView: View {
var body: some View {
List {
Line(text: "Line 1")
Line(text: "Line 2")
Line(text: "Line 3",selected: true)
Line(text: "Line 4")
}
}
}
struct Line: View {
var text :String
var selected = false
var body: some View {
Text(text)
.listRowBackground(selected ? Color.blue : Color.white)
.foregroundColor(selected ? Color.white : Color.black)
}
}
However when switching to darkmode it looks ugly.
Ofcourse I could detect dark mode and set the color explicitly, but I am looking for a way to set the color for the "not selected" line to the standard foreground and backgroundcolor of a list.
How can I get these "Systemcolors"
A simple way to access system colors is with Color(UIColor) like this:
var body: some View {
Text(text)
.listRowBackground(Color(.systemBackground))
.foregroundColor(Color(.label))
}

Groovy switch not behaving as expected

I've got the test.groovy script below, but when I run it, I get the following output.
groovy test.groovy
set color to good
set color to unstable
unstable
Why am I seeing 'set color to good'?
Line 13 states
case "SUCCESS" :
But buildStatus is "UNSTABLE"
I've never used a switch statement before in groovy, so could be missing something pretty basic.
test.groovy
def print_arg(def arg){
buildStatus = "UNSTABLE"
previousBuild = "FAILURE"
// println "$arg"
switch(buildStatus) {
case { it != "SUCCESS" } :
switch(previousBuild) {
case "SUCCESS" :
println "set color to danger"
color = 'danger'
break;
}
case "SUCCESS" :
switch(previousBuild) {
case { it != "SUCCESS"} :
println "set color to good"
color = 'good'
break;
}
case "UNSTABLE" :
println "set color to unstable"
color = 'unstable'
break;
}
println "$color"
}
print_arg()
You see set color to good because you don't have a break statement at the end of your 1st case.
The 1st case matches with { it != "SUCCESS" }, the nested switch does not. Then the excecution proceeds to the 2nd case due to the lack of break before. The 2nd case executes and also doesn't have a break, so it falls through to the 3rd case.
So, the switch operates exactly how it supposed to.
I'm not sure what your original intention was and having nested switch ops does not increase the readability of your code, but I'd put your code like that:
switch(buildStatus) {
case { it != "SUCCESS" } :
switch(previousBuild) {
case "SUCCESS" :
println "set color to danger"
color = 'danger'
break;
}
break // << ADD THIS
case "SUCCESS" :
switch(previousBuild) {
case { it != "SUCCESS"} :
println "set color to good"
color = 'good'
break;
}
break // << ADD THIS
case "UNSTABLE" :
println "set color to unstable"
color = 'unstable'
break;
}

Toolbar search customization

I added the new toolbar search in my app, which is awesome. I have some questions regarding it.
How can I remove the cancel icon (x) in the right of the search toolbar?
Also, since the transition is not very smooth between the app toolbar and search toolbar, how can I set the animatelayout etc when I close or go back to the search toolbar?
Currently neither one of those can be customized but it should be pretty easy to do your own custom search support without those. This is discussed in the Toolbar javadoc:
Toolbar.setGlobalToolbar(true);
Style s = UIManager.getInstance().getComponentStyle("Title");
Form hi = new Form("Toolbar", new BoxLayout(BoxLayout.Y_AXIS));
TextField searchField = new TextField("", "Toolbar Search"); // <1>
searchField.getHintLabel().setUIID("Title");
searchField.setUIID("Title");
searchField.getAllStyles().setAlignment(Component.LEFT);
hi.getToolbar().setTitleComponent(searchField);
FontImage searchIcon = FontImage.createMaterial(FontImage.MATERIAL_SEARCH, s);
searchField.addDataChangeListener((i1, i2) -> { // <2>
String t = searchField.getText();
if(t.length() < 1) {
for(Component cmp : hi.getContentPane()) {
cmp.setHidden(false);
cmp.setVisible(true);
}
} else {
t = t.toLowerCase();
for(Component cmp : hi.getContentPane()) {
String val = null;
if(cmp instanceof Label) {
val = ((Label)cmp).getText();
} else {
if(cmp instanceof TextArea) {
val = ((TextArea)cmp).getText();
} else {
val = (String)cmp.getPropertyValue("text");
}
}
boolean show = val != null && val.toLowerCase().indexOf(t) > -1;
cmp.setHidden(!show); // <3>
cmp.setVisible(show);
}
}
hi.getContentPane().animateLayout(250);
});
hi.getToolbar().addCommandToRightBar("", searchIcon, (e) -> {
searchField.startEditingAsync(); // <4>
});
hi.add("A Game of Thrones").
add("A Clash Of Kings").
add("A Storm Of Swords").
add("A Feast For Crows").
add("A Dance With Dragons").
add("The Winds of Winter").
add("A Dream of Spring");
hi.show();

How to overwrite strings within an if-loop in Swift

I have a few variables that I create within code for a view controller (basically, I'm just checking the values of segmented controls), but when I try to write into the string within the loops (shown below), nothing is written, and all strings remain "nil."
var textTypeVideo:String?
var textMultipleAgents:String?
var textAdditionalRooms:String?
var textMultipleVideos:String?
var textTurnaround:String?
Here are the functions that check to see where the segmented controls are:
#IBAction func typeOfVideoAction(sender: AnyObject) {
if typeOfVideoControl.selectedSegmentIndex == 0 {
textTypeVideo = "Standard Home Video"
} else {
textTypeVideo = "Standard CV Video"
}
}
#IBAction func mulitpleAgentScenesAction(sender: AnyObject) {
if multipleAgentScenesControl.selectedSegmentIndex == 0 {
textMultipleAgents = "Multiple Agent Scenes Desired"
} else {
textMultipleAgents = "No Multiple Agent Scenes"
}
}
#IBAction func additionalRoomsAction(sender: AnyObject) {
if additionalRoomsFeaturesControl.selectedSegmentIndex == 0 {
textAdditionalRooms = "Additional Rooms & Features Desired"
} else {
textAdditionalRooms = "No Additional Rooms & Features"
}
}
#IBAction func multipleVideosAction(sender: AnyObject) {
if multipleVideoCopiesControl.selectedSegmentIndex == 0 {
textMultipleVideos = "Second Video Copy Requested"
} else {
textMultipleVideos = "No Second Video Copy"
}
}
#IBAction func turnaroundAction(sender: AnyObject) {
if turnaroundControl.selectedSegmentIndex == 0 {
textTurnaround = "No Quick Turnaround"
} else if turnaroundControl.selectedSegmentIndex == 1 {
textTurnaround = "24 Hour Turnaround Desired"
} else if turnaroundControl.selectedSegmentIndex == 2 {
textTurnaround = "2 Business Day Turnaround Desired"
} else if turnaroundControl.selectedSegmentIndex == 3 {
textTurnaround = "3 Business Day Turnaround Desired"
} else {
textTurnaround = "5 Business Day Turnaround Desired"
}
}
Finally, this is what I want to fill in and print in an email:
let messageBody = "\(textTypeVideo) and \(textMultipleAgents) and \(textAdditionalRooms) and \(textMultipleVideos) and \(textTurnaround)"
mailComposerVC.setMessageBody(messageBody, isHTML: false)
Any help is greatly appreciated! I just can't seem to fill in the top variables with what they're supposed to be, based on the segmented controls! Thanks.

Resources