Thursday, February 21, 2019

Ruler swift app

We will make a Swift ios ruler.
Create a new class name ruler, it is a subclass of UIView.

We draw lines to mimic a ruler here.

Declare variables.
Copy to above overridefunc drawRect
var x=0.0// inch screen
var den=0
var diem=0
var dem=0
let r = UIScreen.mainScreen().bounds.size.width
let c = UIScreen.mainScreen().bounds.size.height
var l = CGPointZero
var f = CGPointZero
overridefunc touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
iflet touch = touches.first {
f   = touch.locationInView(self)
l = f
setNeedsDisplay()
        }
    }
overridefunc touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
iflet touch = touches.first {
l = touch.locationInView(self)
setNeedsDisplay()
        }
    }
overridefunc touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
iflet touch = touches.first {
l = touch.locationInView(self)
setNeedsDisplay()
        }
    }


This variables use to change dimension when user choose cm or inch.
Function override touch get co-ordinate user finger touch.
Now, how to draw exactly 1cm ?
We need to know screen size in inch, calculate how many pixels equal 1cm .
Variable x mean inch number, we calculate like this.
Copy in to drawRect.
let tcanh=r*r+c*c
var so=x*25.4
        so=so*so;
let socann=Double(tcanh)/so;
let socan = sqrt(socann)
let context = UIGraphicsGetCurrentContext()
CGContextSetLineWidth(context, 0.5)
var socanb=socan
ifden%2==1{
            socanb=socan/2.54
        }

Command if mean when user choose inch, we divide to2.54 to get true ratio.
Copy round function to above last close bracket.
func round2(a:Double)->Double{
let mu = pow(10.0,2.0)
let r=round(a*mu)/mu
return r
    }
Now we draw the lines
Copy continue in to drawRect.
for i in0..<250 {
if(i%5==0){
let kl=i/5;
if(kl%2==0){
CGContextMoveToPoint(context, r-CGFloat(socanb*Double(7)),CGFloat(socan*Double(i)))
/* And end it at this point */
CGContextAddLineToPoint(context, r,CGFloat(socan*Double(i)))
                }
else{
CGContextMoveToPoint(context, r-CGFloat(socanb*Double(5)),CGFloat(socan*Double(i)))
/* And end it at this point */
CGContextAddLineToPoint(context, r,CGFloat(socan*Double(i)))
                }
            }
else{

CGContextMoveToPoint(context, r-CGFloat(socanb*Double(3)),CGFloat(socan*Double(i)))
/* And end it at this point */
CGContextAddLineToPoint(context, r,CGFloat(socan*Double(i)))
            }
        }
for i in1..<25 {
let string =   String(i)
            string.drawAtPoint(CGPointMake(r-70, CGFloat(10*socan*Double(i))-10),
                               withAttributes: [NSFontAttributeName : UIFont(name: "Arial", size: 24.0)!])
        }
UIColor.blackColor().set()
CGContextStrokePath(context)
In command for i in 0..<250 we draw three type of lines. We devide to 5 to know what line mean half of cm, what mean 1 cm, and the rest will be normal lines.
Command for i in1..<25 {  draw numbers from 1-25, we can draw to 30,40 but no actual device has long dimension like this, even ipad pro, so let draw to 25.
Now we wan to have a red line when app open. Copy to below for.
if l.y == 0 {
let conn = UIGraphicsGetCurrentContext()
UIColor.redColor().set()
CGContextSetLineWidth(conn, 0.5)
CGContextMoveToPoint(conn, 0, c/2)
//draw line
CGContextAddLineToPoint(conn, r, c/2)
UIColor.redColor().set()
CGContextStrokePath(conn)
        }
l.y == 0 mean no touch, when open app.
Now when user touch screen, we draw line move along with finger and show cm dimension.
Copy continue to drawRect.
if l.y>0{
let con = UIGraphicsGetCurrentContext()
UIColor.redColor().set()
/* Set the color that we want to use to draw the line */
CGContextMoveToPoint(con, 0, l.y)
/* And end it at this point */
CGContextAddLineToPoint(con, r, l.y)
CGContextStrokePath(con)
let pa=CGPathCreateMutable()
CGContextAddPath(context, pa)
CGContextDrawPath(context, CGPathDrawingMode(rawValue: 1)!)
if den%2==0{
let cm = Double(l.y)/socan
let cc=round2(cm)
let tring =   String(cc) + " mm"
                tring.drawAtPoint(CGPointMake(r/6, l.y ), withAttributes: [NSForegroundColorAttributeName: UIColor.redColor(), NSFontAttributeName: UIFont(name: "HelveticaNeue", size: 27.0)!])
            }
else{
// inch
let cm = Double(l.y)/socan
let cc=round2(cm/10)
let tring =   String(cc) + " inch"
                tring.drawAtPoint(CGPointMake(r/6, l.y ), withAttributes: [NSForegroundColorAttributeName: UIColor.redColor(), NSFontAttributeName: UIFont(name: "HelveticaNeue", size: 27.0)!])
            }
        }
l.y>0 mean user touching screen, we draw line using l.y, to make it move along with finger.
In if command, when count value even, draw dimension in mm, uneven, draw in inch.
If want to draw line along width screen, use l.x.
Now go to clas ViewController, class main, we draw button, show everything.
Copy variables to above viewDidLoad.
var bu: UIButton!
var bu2: UIButton!
var denn=0
var diem=0
var x=0.0
var ik=0.0
var gv=0
   var scale:CGFloat?
let c = UIScreen.mainScreen().bounds.size.height
let ruler = ruler()
Copy to below viewDidLoad
scale = UIScreen.mainScreen().scale;
if c<500{
x = 3.5
        }
else if c<600&&c>500{
x = 4
        }
else if c<700&&c>600{
x = 4.7
        }
else if c<800&&c>700{
x = 5.5
        }
else if c==812{
x = 5.8
        }

else if c<1030&&c>800{
ifscale==1.0{
x = 7.9
            }
else{
x = 9.7
            }
        }
else{

x = 12.9
        }
ik=x




We use screen height and scale to know device inch. You can update for next iphone.
Copy to below ik=x
bu = UIButton(frame: CGRect(x: -20, y: 50, width: 80, height: 40))
let a=NSMutableAttributedString(string: "Cm->Inch", attributes: [NSForegroundColorAttributeName: UIColor.blueColor(), NSFontAttributeName: UIFont(name: "Georgia", size: 16.0)!])
bu.setAttributedTitle(a, forState: .Normal)
bu2 = UIButton(frame: CGRect(x: 3, y: Int(c-34), width: 50, height: 42))
bu2.setTitle("Quit",forState: .Normal)
bu2.setTitleColor(UIColor.grayColor(), forState: .Normal)
We draw button change cm->inch and Quit, color titles.
Copy to continue.
ruler.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: c)
ruler.backgroundColor = UIColor.whiteColor()
if gv%2==1{
diem=2
denn=1
ik=x/2.54
  }
else{
ik=x
  }
ruler.den=denn
ruler.x=ik
UIView.animateWithDuration(0.0, animations: {
self.bu.transform = CGAffineTransformMakeRotation(CGFloat(90) * CGFloat(M_PI)/180)
        })
view.addSubview(ruler)
view.addSubview(bu)
view.addSubview(bu2)
bu.addTarget(self, action: #selector(cmin(_:)), forControlEvents: UIControlEvents.TouchUpInside)
bu2.addTarget(self, action: #selector(quit(_:)), forControlEvents: UIControlEvents.TouchUpInside)

We set screen value to x variable, rotate button cm->inch 90 degrees.
Add to view and set function for button.
Copy function to outside viewDidLoad.
func cmin(sender: UIButton){
denn=denn+1
ifdenn%2==1{
diem=2
ik=ik/2.54
        }
else{
diem=1
ik=ik*2.54
        }
ruler.den=denn
ruler.x=ik
ruler.setNeedsDisplay()
    }
func quit(sender: UIButton){
write2("","save.txt")
write(String(denn),fileName: "save.txt")
exit(0)
    }
Function cmin() of button cm->inch to draw things in cm or inch.
Now we want to remember user last choose cm or inch, when reopen, we show the same.
We use a count variable, value even mean inch, odd mean cm. When quit app, we write value of denn in to save.txt. We do this in func quit.
Copy functions write in to class.
func write(content: String, fileName: String) {
let contentToAppend = content
let filePath = NSHomeDirectory() + "/Documents/" + fileName
//Check if file exists
if let fileHandle = NSFileHandle(forWritingAtPath: filePath) {
//Append to file
            fileHandle.seekToEndOfFile()     fileHandle.writeData(contentToAppend.dataUsingEncoding(NSUTF8StringEncoding)!)
        }
else {
//Create new file
do {
try contentToAppend.writeToFile(filePath, atomically: true, encoding: NSUTF8StringEncoding)
            } catch {
print("Error creating \(filePath)")
            }
        }
    }
func write2(content: String,_ fileName: String) {
let contentToAppend = content
let filePath = NSHomeDirectory() + "/Documents/" + fileName
//Check if file exists
iflet fileHandle = NSFileHandle(forWritingAtPath: filePath) {
//Append to file
//  fileHandle.seekToEndOfFile()
// fileHandle.writeData(contentToAppend.dataUsingEncoding(NSUTF8StringEncoding)!)
do {
try content.writeToFile(filePath, atomically: false, encoding: NSUTF8StringEncoding)
            } catch {
print("Error creating \(filePath)")
            }
        }
else {
//Create new file
do {
try contentToAppend.writeToFile(filePath, atomically: true, encoding: NSUTF8StringEncoding)
            } catch {
print("Error creating \(filePath)")
            }
        }
    }
func doc()->Int{
let documentsPath2 = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] asNSString
let path2 = documentsPath2.stringByAppendingPathComponent("save.txt")
var rea2 : String = ""
var t2="g"
var t3=10
do {
try rea2 = NSString(contentsOfFile: path2, encoding: NSUTF8StringEncoding) asString
var ar = rea2.componentsSeparatedByString("\n")
            t2=ar[0]
            t3=Int(t2)!
        }
catchlet error asNSError {
// print("ERROR : reading from file \(fileName) : \(error.localizedDescription)")
        }
return t3
    }
Copy this line in to viewDidLoad, below set position lines.
gv = doc()

We read file save.txt to get value, let us know what should show, cm or inch. The first time open app, value = 0 mean draw in cm.
Run to see result, press cm->inch to change.


1 comment:

  1. Your Dropbox, OneDrive and Google Drive, are just the tip of the iceberg. In 2021, we can expect to see the new, cutting-edge apps that run directly in the cloud, and they take up very little space in your mobile phone storage. Data-teaching will work. originally us mobile app developer

    ReplyDelete