Kadrs un robežas operētājsistēmā iOS

Šis raksts ir repost no atbildes, ko es uzrakstīju par kaudze pārpildes.

Īss apraksts

  • rāmis = skata atrašanās vieta un lielums, izmantojot vecāku skata koordinātu sistēmu (svarīgi skata novietošanai vecākos)
  • robežas = skata atrašanās vieta un lielums, izmantojot savu koordinātu sistēmu (svarīgi, lai skata saturs vai apakšskati tiktu ievietoti sevī)

Sīkāka informācija

Lai palīdzētu man atcerēties rāmi, es domāju par sienas rāmīti. Attēla rāmis ir kā skata robeža. Es attēlu var pakārt pie sienas visur, kur es gribu. Tādā pašā veidā vecāku skatā es varu ievietot skatu visur, kur es gribu (to sauc arī par supervisu skatu). Vecāku skats ir kā siena. Koordinātu sistēmas izcelsme iOS ir augšējā kreisajā stūrī. Mēs varam pievērst mūsu skatu supervisa rašanās sākumam, iestatot skata rāmja x-y koordinātas uz (0, 0), kas ir līdzīgi kā pakarināt mūsu attēlu sienas augšējā kreisajā stūrī. Lai to pārvietotu pa labi, palieliniet x, lai pārvietotu uz leju, palieliniet y.

Lai palīdzētu man atcerēties robežas, es domāju par basketbola laukumu, kur dažreiz basketbols tiek izsists no robežām. Jūs grozāt bumbu visā basketbola laukumā, bet jums nav īsti vienalga, kur atrodas pati tiesa. Tas varētu būt sporta zālē vai ārpus vidusskolas, vai jūsu mājas priekšā. Tam nav nozīmes. Jūs vienkārši vēlaties spēlēt basketbolu. Tādā pašā veidā skata robežu koordinātu sistēma rūpējas tikai par pašu skatu. Tas neko nezina par to, kur skats atrodas vecāku skatā. Robežu izcelsme (pēc noklusējuma punkts (0, 0)) ir skata augšējais kreisais stūris. Visi šī viedokļa pakārtotie punkti ir izklāstīti saistībā ar šo punktu. Tas ir tāpat kā aizvest basketbolu laukuma priekšējā kreisajā stūrī.

Tagad rodas neskaidrības, kad mēģināt salīdzināt kadru un robežas. Tomēr patiesībā tas nav tik slikti, kā šķiet sākumā. Izmantosim dažus attēlus, lai palīdzētu mums saprast.

Rāmis vs robežas

Pirmajā attēlā pa kreisi mums ir skats, kas atrodas vecāku skata augšējā kreisajā stūrī. Dzeltenais taisnstūris attēlo skata rāmi. Labajā pusē atkal redzam skatu, bet šoreiz vecāku skats netiek parādīts. Tas ir tāpēc, ka robežas nezina par vecāku skatu. Zaļais taisnstūris apzīmē skata robežas. Sarkanais punkts abos attēlos norāda kadra vai apmales izcelsmi.

Rāmis
    izcelsme = (0, 0)
    platums = 80
    augstums = 130
 
 Robežas
    izcelsme = (0, 0)
    platums = 80
    augstums = 130

Tātad rāmis un robežas šajā attēlā bija tieši tādi paši. Apskatīsim piemēru, kur tie ir atšķirīgi.

 Rāmis
     izcelsme = (40, 60) // Tas ir, x = 40 un y = 60
     platums = 80
     augstums = 130
 
 Robežas
     izcelsme = (0, 0)
     platums = 80
     augstums = 130

Tātad jūs varat redzēt, ka, mainot rāmja x-y koordinātas, tas tiek pārvietots vecāku skatā. Bet pats skata saturs joprojām izskatās tieši tāds pats. Robežām nav nojausmas, ka kaut kas ir savādāk.

Līdz šim gan rāmja, gan robežu platums un augstums bija tieši vienāds. Tomēr tas ne vienmēr ir taisnība. Paskatieties, kas notiek, ja skatu pagriežam par 20 grādiem pulksteņrādītāja virzienā. (Rotācija tiek veikta, izmantojot transformācijas. Lai iegūtu papildinformāciju, skatiet dokumentāciju un šos skata un slāņa piemērus.)

Rāmis
   izcelsme = (20, 52) // Tās ir tikai aptuvenas aplēses.
   platums = 118
   augstums = 187
 
Robežas
   izcelsme = (0, 0)
   platums = 80
   augstums = 130

Var redzēt, ka robežas joprojām ir vienādas. Viņi joprojām nezina, ka kaut kas ir noticis! Tomēr kadru vērtības ir mainījušās.

Tagad ir nedaudz vieglāk pamanīt atšķirību starp kadru un robežām, vai ne? Rakstā jūs, iespējams, nesaprotat kadrus un robežas, skata rāmis tiek definēts kā

… Šī skata mazākā robeža ar vecākiem
koordinātu sistēma, ieskaitot visas pārmaiņas, kas tiek piemērotas šim skatam.

Ir svarīgi ņemt vērā: ja skatu pārveidojat, rāmis kļūst nedefinēts. Tātad dzeltenā rāmja, ko es uzzīmēju ap augšējā attēlā redzamajām pagrieztajām zaļajām robežām, nekad nav. Tas nozīmē, ja pagriežat, mērogojat vai veicat kādu citu transformāciju, jums vairs nevajadzētu izmantot kadru vērtības. Tomēr jūs joprojām varat izmantot robežu vērtības. Apple dokumenti brīdina:

Svarīgi: ja skata pārveidošanas īpašumā nav identitātes pārveidošanas, šī skata rāmis nav definēts, tāpat kā tā automātiskās mainīšanas uzvedības rezultāti.

Diezgan žēl par automātisko mainīšanu…. Tomēr ir kaut kas, ko jūs varat darīt.

Apple dokumentu statuss:

Pārveidojot sava skata pārveidošanas īpašību, visas pārvērtības tiek veiktas attiecībā pret skata centru.

Tātad, ja pēc pārveidošanas ir jāpārvieto skats vecākos, varat to izdarīt, mainot view.center koordinātas. Tāpat kā rāmis, centrs izmanto vecāku skata koordinātu sistēmu.

Labi, atbrīvosimies no mūsu rotācijas un koncentrēsimies uz robežām. Līdz šim robežu izcelsme vienmēr ir palikusi (0, 0). Tomēr tas nav obligāti. Ko darīt, ja mūsu skatam ir liels apakšskats, kas ir pārāk liels, lai visu uzreiz parādītu? Mēs to padarīsim par UIImageView ar lielu attēlu. Šeit ir atkal mūsu otrais attēls no augšas, bet šoreiz mēs redzēsim, kā izskatīsies viss mūsu skata apakšskata saturs.

Rāmis
    izcelsme = (40, 60)
    platums = 80
    augstums = 130
 
Robežas
    izcelsme = (0, 0)
    platums = 80
    augstums = 130

Tikai attēla augšējais kreisais stūris var ietilpt skata malās. Tagad paskatieties, kas notiek, ja mainām robežu sākuma koordinātas.

Rāmis
    izcelsme = (40, 60)
    platums = 80
    augstums = 130
 
Robežas
    izcelsme = (280, 70)
    platums = 80
    augstums = 130

Rāmis nav pārvietots superview, bet saturs rāmja iekšpusē ir mainījies, jo robežu taisnstūra izcelsme sākas citā skata daļā. Šī ir visa UIScrollView ideja, un tā ir apakšklases (piemēram, UITableView). Plašāku skaidrojumu skatiet sadaļā UIScrollView izpratne.

Kad lietot rāmi un kad izmantot robežas

Tā kā rāmis ir saistīts ar skata atrašanās vietu tā vecāku skatā, jūs to izmantojat, veicot izmaiņas uz āru, piemēram, mainot tā platumu vai atrodot attālumu starp skatu un tā vecāku skata augšdaļu.

Izmantojiet robežas, kad veicat iekšējas izmaiņas, piemēram, zīmējat lietas vai sakārtojat apakšskatu skatā. Izmantojiet arī robežas, lai iegūtu skata lielumu, ja esat to nedaudz pārveidojis.

Raksti turpmākai izpētei:

Apple dokumenti

  • Skata ģeometrija
  • Skati
  • Skatu un logu arhitektūra

Citi resursi

  • Jūs, iespējams, nesaprotat kadrus un robežas
  • iOS pamati: rāmji, robežas un CGGeometrija
  • CS193p 5. lekcija - skati, zīmēšana, animācija

Praktizējiet sevi

Papildus iepriekš minēto rakstu lasīšanai tas man ļoti palīdz izveidot testa lietotni. Jūs varētu vēlēties mēģināt izdarīt kaut ko līdzīgu. (Ideja man radās no šī video kursa, bet diemžēl tā nav bezmaksas.)

Šeit ir jūsu atsauces kods:

importēt UIKit
 
   klases ViewController: UIViewController {
 
 
    @IBOutlet vājš var myView: UIView!
 
    // Etiķetes
    @IBOutlet vājš var frameX: UILabel!
    @IBOutlet vājš var frameY: UILabel!
    @IBOutlet vājš var frameWidth: UILabel!
    @IBOutlet vājš var frameHeight: UILabel!
    @IBOutlet vājas var robežasX: UILabel!
    @IBOutlet vāja var robežaY: UILabel!
    @IBOutlet vājas var robežasPlatums: UILabel!
    @IBOutlet vājas var robežasAugstums: UILabel!
    @IBOutlet vājš var centerX: UILabel!
    @IBOutlet vāja var centrY: UILabel!
    @IBOutlet vāja var rotācija: UILabel!
 
    // Bīdītāji
    @IBOutlet vāja var frameXSlider: UISlider!
    @IBOutlet vājš var frameYSlider: UISlider!
    @IBOutlet vāja var frameWidthSlider: UISlider!
    @IBOutlet vāja var frameHeightSlider: UISlider!
    @IBOutlet vāja var robežaXSlider: UISlider!
    @IBOutlet vāja var boundsYSlider: UISlider!
    @IBOutlet vāja var boundsWidthSlider: UISlider!
    @IBOutlet vājas var robežasHeightSlider: UISlider!
    @IBOutlet vājš var centerXSlider: UISlider!
    @IBOutlet vājš var centreYSlider: UISlider!
    @IBOutlet vāja var rotationSlider: UISlider!
 
    // Slīdņa darbības
    @IBAction func frameXSliderChanged (sūtītājs: AnyObject) {
        myView.frame.origin.x = CGFloat (frameXSlider.value)
        updateLabels ()
    }
    @IBAction func frameYSliderChanged (sūtītājs: AnyObject) {
        myView.frame.origin.y = CGFloat (frameYSlider.value)
        updateLabels ()
    }
    @IBAction func frameWidthSliderChanged (sūtītājs: AnyObject) {
        myView.frame.size.width = CGFloat (frameWidthSlider.value)
        updateLabels ()
    }
    @IBAction func frameHeightSliderChanged (sūtītājs: AnyObject) {
        myView.frame.size.height = CGFloat (frameHeightSlider.value)
        updateLabels ()
    }
    @IBAction func boundsXSliderChanged (sūtītājs: AnyObject) {
        myView.bounds.origin.x = CGFloat (robežasXSlider.vērtība)
       updateLabels ()
    }
    @IBAction func boundsYSliderChanged (sūtītājs: AnyObject) {
        myView.bounds.origin.y = CGFloat (boundsYSlider.value)
        updateLabels ()
    }
    @IBAction func boundsWidthSliderChanged (sūtītājs: AnyObject) {
        myView.bounds.size.width = CGFloat (boundsWidthSlider.value)
        updateLabels ()
    }
    @IBAction func boundsHeightSliderChanged (sūtītājs: AnyObject) {
        myView.bounds.size.height = CGFloat (boundsHeightSlider.value)
        updateLabels ()
    }
    @IBAction func centreXSliderChanged (sūtītājs: AnyObject) {
        myView.center.x = CGFloat (centerXSlider.value)
        updateLabels ()
    }
    @IBAction func centreYSliderChanged (sūtītājs: AnyObject) {
        myView.center.y = CGFloat (centreYSlider.value)
        updateLabels ()
    }
    @IBAction func rotationSliderChanged (sūtītājs: AnyObject) {
        let rotation = CGAffineTransform (rotationAngle: CGFloat (rotationSlider.value))
        myView.transform = rotācija
        updateLabels ()
    }
 
    privāts func updateLabels () {
 
        frameX.text = “kadrs x = \ (Int (myView.frame.origin.x))”
        frameY.text = “kadrs y = \ (Int (myView.frame.origin.y))”
        frameWidth.text = “kadra platums = \ (Int (myView.frame.width))”
        frameHeight.text = “kadra augstums = \ (Int (myView.frame.height))”
        boundsX.text = “robežas x = \ (Int (myView.bounds.origin.x))”
        boundsY.text = “ierobežo y = \ (Int (myView.bounds.origin.y))”
        boundsWidth.text = “robežas platums = \ (Int (myView.bounds.width))”
        boundsHeight.text = “robežu augstums = \ (Int (myView.bounds.height))”
        centerX.text = “centrs x = \ (Int (myView.center.x))”
        centerY.text = “centrs y = \ (Int (myView.center.y))”
        rotation.text = “rotation = \ ((rotationSlider.value))”
 
    }
 
}