{"id":31843,"date":"2019-10-31T21:43:27","date_gmt":"2019-10-31T18:43:27","guid":{"rendered":"https:\/\/prohoster.info\/blog\/sozdanie-kalkulyatora-chaevyh-na-kotlin-kak-eto-rabotaet\/"},"modified":"2019-10-31T21:43:27","modified_gmt":"2019-10-31T18:43:27","slug":"sozdanie-kalkulyatora-chaevyh-na-kotlin-kak-eto-rabotaet","status":"publish","type":"post","link":"https:\/\/prohoster.info\/da\/blog\/news\/sozdanie-kalkulyatora-chaevyh-na-kotlin-kak-eto-rabotaet","title":{"rendered":"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?\" src=\"\/wp-content\/uploads\/2019\/04\/faaae0beaf023f1c11bb9102312fe429.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nVi forklarer, hvordan man opretter en simpel applikation til beregning af tip i Kotlin. Mere pr\u00e6cist, Kotlin 1.3.21, Android 4, Android Studio 3. Artiklen vil v\u00e6re interessant, is\u00e6r for dem, der starter deres rejse inden for Android-applikationsudvikling. Den giver en forst\u00e5else for, hvordan og hvad der fungerer inde i applikationen. <\/p>\n<p>En s\u00e5dan lommeregner vil v\u00e6re nyttig, n\u00e5r man skal beregne tips fra en gruppe, der har besluttet at tilbringe tid p\u00e5 en restaurant eller caf\u00e9. Selvf\u00f8lgelig giver ikke alle og ikke altid drikkepenge til tjenere, det er mere en vestlig tradition, men udviklingen af en s\u00e5dan applikation er uanset hvad interessant. <br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<blockquote><p><b>Vi minder om:<\/b> <i>til alle l\u00e6sere af 'Habr' \u2014 rabat p\u00e5 10.000 rubler ved tilmelding til et hvilket som helst Skillbox-kursus med rabatkoden 'Habr'.<\/i><\/p>\n<p><b>Skillbox anbefaler:<\/b> Praktisk kursus <noindex><a rel=\"nofollow\" href=\"https:\/\/skillbox.ru\/agima\/?utm_source=skillbox.media&amp;utm_medium=habr.com&amp;utm_campaign=AGIMA&amp;utm_content=articles&amp;utm_term=kotlintips\">Mobiludvikler PRO<\/a><\/noindex>.\n<\/p><\/blockquote>\n<p>\nS\u00e5dan ser applikationen ud under drift:<\/p>\n<p><img decoding=\"async\" alt=\"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?\" src=\"\/wp-content\/uploads\/2019\/04\/fa375744a4ca5d07667ec494db38648b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nDu indtaster \u00f8nsket procentdel af det samlede bel\u00f8b, antallet af deltagere og f\u00e5r resultatet \u2014 tipbel\u00f8bet, som b\u00f8r gives.<\/p>\n<h3>Lad os begynde<\/h3>\n<p>\nDet fulde interface af applikationen ser s\u00e5ledes ud:<br \/>\n<img decoding=\"async\" alt=\"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?\" src=\"\/wp-content\/uploads\/2019\/04\/e95058f09c4a6c151b6c5500ae549c0e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\n<img decoding=\"async\" alt=\"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?\" src=\"\/wp-content\/uploads\/2019\/04\/ac31c73ade24640078c76d71700de0b4.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nDen f\u00f8rste handling \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lawreyios\/tipcalculator\/tree\/starter_project\">indl\u00e6sning af projektets grundstruktur<\/a><\/noindex>. \u00c5bn den i Android Studio 3.0 eller nyere. Byg og k\u00f8r projektet, og du ser en hvid sk\u00e6rm. Alt er normalt, s\u00e5dan skal det v\u00e6re.<\/p>\n<p><img decoding=\"async\" alt=\"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?\" src=\"\/wp-content\/uploads\/2019\/04\/f4e3361ddc45d56794cc5c7c36d8b206.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\n<img decoding=\"async\" alt=\"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?\" src=\"\/wp-content\/uploads\/2019\/04\/7828c10dcb3936eb095f5110094ea8bf.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nBrugerens handlinger er skrevet i projektet i kronologisk r\u00e6kkef\u00f8lge, s\u00e5 alt er forst\u00e5eligt. For at se dem \u00e5bner du View -&gt; Tool Windows -&gt; TODO.<\/p>\n<p>Lad os unders\u00f8ge projektet og \u00e5bne colors.xml for at vurdere farvepaletten. I strings.xml er tekstdataene (etiketter) placeret, og styles.xml indeholder flere skrifttype-maler.<\/p>\n<h3>Udvikling af udgiftsafsnittet<\/h3>\n<p>\n\u00c5bn activity_main.xml og tilf\u00f8j koden nedenfor til LinearLayout (#1):<\/p>\n<pre><code class=\"kotlin\"><\/code><\/pre>\n<p>\nNu kan vi justere stilen i values-mappen eller lege med farverne ved hj\u00e6lp af <noindex><a rel=\"nofollow\" href=\"https:\/\/material.io\/tools\/color\/#!\/?view.left=0&amp;view.right=0&amp;primary.color=37474F\">v\u00e6rkt\u00f8jet material.io<\/a><\/noindex>.<\/p>\n<p>Nu ser projektet s\u00e5dan ud:<\/p>\n<p><img decoding=\"async\" alt=\"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?\" src=\"\/wp-content\/uploads\/2019\/04\/ab47023cafd97fdbd171a9d9a1c35dd5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i> Som du kan se, beregnes udgiften ud fra de data, som brugeren indtaster. <\/i><\/p>\n<h3>Udvikling af regningsafsnittet<\/h3>\n<p>\nTilf\u00f8j koden, der er angivet nedenfor, til LinearLayout efter Expense Section (#2):<\/p>\n<pre><code class=\"kotlin\">&lt;! \u2014 TODO #3: Byg Bill Sektion \u2192\n \n\u2026<\/code><\/pre>\n<p>\nVi afslutter LinearLayout efter TODO-listen og tilf\u00f8jer derefter ny kode, som placeres inden for LinearLayout (#3):<\/p>\n<pre><code class=\"kotlin\"><\/code><\/pre>\n<p>\nDa appens hovedopgave er at beregne individuelle omkostninger for hver deltager i restaurantbes\u00f8get, er costPerPersonTextView af stor betydning. <\/p>\n<p>EditText begr\u00e6nser dataindsamlingen til \u00e9n linje, og denne parameter skal have v\u00e6rdien NumberDecimal inputType.<\/p>\n<p><img decoding=\"async\" alt=\"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?\" src=\"\/wp-content\/uploads\/2019\/04\/7dc4e90d8188a08933e7a92b119472ee.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i> Vi k\u00f8rer projektet til test og indtaster parametrene for det samlede tab (knuste kopper, tallerkener osv.)<\/i><\/p>\n<h3>Udvikling af sektionen 'Mennesker og drikkepenge'<\/h3>\n<p>\nFor at tilf\u00f8je valg af drikkepenge, inds\u00e6tter vi den f\u00f8lgende kode i den nye sektion LinearLayout (#4):<\/p>\n<pre><code class=\"kotlin\"><\/code><\/pre>\n<p>\nDette kodeafsnit er n\u00f8dvendigt for n\u00f8jagtigt at beregne bel\u00f8bet for drikkepenge. Standardv\u00e6rdien for teksten er 20. ImageButtons er udstyret med ikoner i en mappe med skrivebeskyttelse.<\/p>\n<p>Vi kopierer hele sektionen og tilf\u00f8jer f\u00f8lgende (#5):<\/p>\n<ul>\n<li> ImageButton ids (subtractPeopleButton, addPeopleButton)<\/li>\n<li> TextView ids (numberOfPeopleStaticText, numberOfPeopleTextView)<\/li>\n<li> DefaultText for numberOfPeopleTextView (skal v\u00e6re 4).<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?\" src=\"\/wp-content\/uploads\/2019\/04\/df99acfb33c3d27126db807b805c9c87.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nN\u00e5r appen startes, er det nu muligt at tilf\u00f8je bel\u00f8bet for regningen, og knapperne 'Tilf\u00f8j\/'Tr\u00e6k fra' fungerer, men indtil videre sker der intet.<\/p>\n<h3>Vi tilf\u00f8jer Views<\/h3>\n<p>\nVi \u00e5bner MainActivity.kt og tilf\u00f8jer dette til funktionen initViews (#6):<\/p>\n<pre><code class=\"kotlin\">private fun initViews() {\n        expensePerPersonTextView = findViewById(R.id.expensePerPersonTextView)\n        billEditText = findViewById(R.id.billEditText)\n \naddTipButton = findViewById(R.id.addTipButton)\n        tipTextView = findViewById(R.id.tipTextView)\n        subtractTipButton = findViewById(R.id.subtractTipButton)\n \naddPeopleButton = findViewById(R.id.addPeopleButton)\n        numberOfPeopleTextView = findViewById(R.id.numberOfPeopleTextView)\n        subtractPeopleButton = findViewById(R.id.subtractPeopleButton)\n \n\/\/TODO #8: Bind Buttons to Listener\n \n\/\/TODO #16: Bind EditText to TextWatcher\n \n}<\/code><\/pre>\n<p><\/p>\n<h3>F\u00e6rdigg\u00f8r knapperne<\/h3>\n<p>\nFor at tilf\u00f8je klikunderst\u00f8ttelse til knapperne implementerer vi View.OnClickListener p\u00e5 klassens niveau (#7):<\/p>\n<p>class MainActivity: AppCompatActivity(), View.OnClickListener {<\/p>\n<p>Det vil ikke v\u00e6re muligt at kompilere projektet lige nu, vi skal udf\u00f8re nogle flere handlinger (#8):<\/p>\n<pre><code class=\"kotlin\">override fun onClick(v: View?) {\n        when (v?.id) {\n            R.id.addTipButton -&gt; incrementTip()\n            R.id.subtractTipButton -&gt; decrementTip()\n            R.id.addPeopleButton -&gt; incrementPeople()\n            R.id.subtractPeopleButton -&gt; decrementPeople()\n        }\n    }<\/code><\/pre>\n<p>\nAng\u00e5ende knapperne og switchene er alt organiseret rigtig godt i Kotlin! Vi tilf\u00f8jer nedenst\u00e5ende kode til alle funktionerne increment og decrement<br \/>\n (#9\u200a\u2013#12):<\/p>\n<pre><code class=\"kotlin\">private fun incrementTip() {\n        if (tipPercent != MAX_TIP) {\n            tipPercent += TIP_INCREMENT_PERCENT\n            tipTextView.text = String.format(\"%d%%\", tipPercent)\n        }\n    }\n \nprivate fun decrementTip() {\n        if (tipPercent != MIN_TIP) {\n            tipPercent -= TIP_INCREMENT_PERCENT\n            tipTextView.text = String.format(\"%d%%\", tipPercent)\n        }\n    }\n \nprivate fun incrementPeople() {\n        if (numberOfPeople != MAX_PEOPLE) {\n            numberOfPeople += PEOPLE_INCREMENT_VALUE\n            numberOfPeopleTextView.text = numberOfPeople.toString()\n        }\n    }\n \nprivate fun decrementPeople() {\n        if (numberOfPeople != MIN_PEOPLE) {\n            numberOfPeople -= PEOPLE_INCREMENT_VALUE\n            numberOfPeopleTextView.text = numberOfPeople.toString()\n        }\n    }<\/code><\/pre>\n<p>\nHer beskytter koden for\u00f8gelserne mod de maksimale v\u00e6rdier (MAX_TIP &amp; MAX_PEOPLE). Desuden beskytter koden for reduktionerne mod de minimale v\u00e6rdier (MIN_TIP &amp; MIN_PEOPLE).<\/p>\n<p>Nu binder vi knapperne til lytterne i funktionen initViews (#13):<\/p>\n<pre><code class=\"kotlin\">private fun initViews() {\n \n...\n \naddTipButton.setOnClickListener(this)\n        subtractTipButton.setOnClickListener(this)\n \naddPeopleButton.setOnClickListener(this)\n        subtractPeopleButton.setOnClickListener(this)\n \n\/\/TODO #15: Bind EditText to TextWatcher\n}<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?\" src=\"\/wp-content\/uploads\/2019\/04\/73e7477d4b02548aad7c2112c6be5d80.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nNu kan vi tilf\u00f8je samlet skade, drikkepenge og antallet af deltagere til m\u00f8det. Og nu det vigtigste\u2026<\/p>\n<h3>Afsnit til udgiftsberegning<\/h3>\n<p>Denne kode beregner udgifterne (#14):<\/p>\n<pre><code class=\"kotlin\">private fun calculateExpense() {\n \nval totalBill = billEditText.text.toString().toDouble()\n \nval totalExpense = ((HUNDRED_PERCENT + tipPercent) \/ HUNDRED_PERCENT) * totalBill\n        val individualExpense = totalExpense \/ numberOfPeople\n \nexpensePerPersonTextView.text = String.format(\"$%.2f\", individualExpense)\n \n}<\/code><\/pre>\n<p>\nOg her kaldes funktionen, som g\u00f8r det muligt at tage h\u00f8jde for antallet af personer i selskabet og beregne drikkepengene (#15):<\/p>\n<pre><code class=\"kotlin\">private fun incrementTip() {\n \n\u2026\n \n}\n \nprivate fun decrementTip() {\n \n\u2026\n \n}\n \nprivate fun incrementPeople() {\n \n\u2026\n \n}\n \nprivate fun decrementPeople() {\n \n\u2026\n \n}<\/code><\/pre>\n<p>\nVi starter applikationen. Den ser godt ud og fungerer godt. Men det kan v\u00e6re endnu bedre.<\/p>\n<p>Hvis du fors\u00f8ger at fjerne bel\u00f8bet fra regningen og derefter \u00f8ge antallet af tips eller venner, vil applikationen crashe, da der endnu ikke er nogen kontrol for nulv\u00e6rdien af omkostninger. Desuden vil omkostningerne ikke opdateres, hvis du fors\u00f8ger at \u00e6ndre bel\u00f8bet for regningen.<\/p>\n<h3>Afsluttende trin<\/h3>\n<p>\nVi tilf\u00f8jer TextWatcher (#16):<\/p>\n<p>class MainActivity: AppCompatActivity(), View.OnClickListener, TextWatcher {<\/p>\n<p>Derefter integrerer vi lytteren billEditText (#17):<\/p>\n<p>billEditText.addTextChangedListener(this)<\/p>\n<p>Desuden tilf\u00f8jer vi kode til at udf\u00f8re TextWatcher (#18):<\/p>\n<pre><code class=\"kotlin\">override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {\n        if (!billEditText.text.isEmpty()) {\n            calculateExpense()\n        }\n    }\noverride fun afterTextChanged(s: Editable?) {}\n\n    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?\" src=\"\/wp-content\/uploads\/2019\/04\/623256a43c969d8b3a434d10a357c1a0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nOg nu fungerer alt perfekt! Tillykke, du har skrevet din egen \"Tip Calculator\" i Kotlin.<\/p>\n<p><img decoding=\"async\" alt=\"Oprettelse af en tipsberegner i Kotlin: hvordan fungerer det?\" src=\"\/wp-content\/uploads\/2019\/04\/5650bfecfadf3fd56785b7d6ac72ed87.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<blockquote><p><b>Skillbox anbefaler:<\/b><\/p>\n<ul>\n<li>To\u00e5rigt praktisk kursus <noindex><a rel=\"nofollow\" href=\"https:\/\/iamwebdev.skillbox.ru\/?utm_source=skillbox.media&amp;utm_medium=habr.com&amp;utm_campaign=WEBDEVPRO&amp;utm_content=articles&amp;utm_term=kotlintips\">\u00abJeg er Web-udvikler PRO\u00bb<\/a><\/noindex>.<\/li>\n<li>Online kursus <noindex><a rel=\"nofollow\" href=\"https:\/\/skillbox.ru\/c-sharp\/?utm_source=skillbox.media&amp;utm_medium=habr.com&amp;utm_campaign=CSHDEV&amp;utm_content=articles&amp;utm_term=kotlintips\">\"C#-udvikler\"<\/a><\/noindex>.<\/li>\n<li>Praktisk \u00e5rs kursus <noindex><a rel=\"nofollow\" href=\"https:\/\/skillbox.ru\/php\/?utm_source=skillbox.media&amp;utm_medium=habr.com&amp;utm_campaign=PHPDEV&amp;utm_content=articles&amp;utm_term=kotlintips\">\"PHP-udvikler fra 0 til PRO\"<\/a><\/noindex>.\n<\/li>\n<\/ul>\n<\/blockquote>\n<p>Kilde: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/skillbox\/blog\/448582\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0420\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u0447\u0430\u0435\u0432\u044b\u0445 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 Kotlin. \u0415\u0441\u043b\u0438 \u0442\u043e\u0447\u043d\u0435\u0435, \u0442\u043e Kotlin 1.3.21, Android 4, Android Studio 3. \u0421\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0439, \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0441\u0432\u043e\u0439 \u043f\u0443\u0442\u044c \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 Android-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041e\u043d\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0438 \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u043e\u0439 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0441\u0443\u043c\u043c\u0443 \u0447\u0430\u0435\u0432\u044b\u0445 \u0441 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":23712,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[702],"tags":[],"class_list":["post-31843","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0420\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/da\/blog\/news\/sozdanie-kalkulyatora-chaevyh-na-kotlin-kak-eto-rabotaet\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0447\u0430\u0435\u0432\u044b\u0445 \u043d\u0430 Kotlin: \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442? | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0420\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/da\/blog\/news\/sozdanie-kalkulyatora-chaevyh-na-kotlin-kak-eto-rabotaet\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:43:27+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:43:27+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Oprettelse af en tip calculator i Kotlin: hvordan fungerer det? | ProHoster","description":"Vi forklarer, hvordan man laver en simpel.","canonical_url":"https:\/\/prohoster.info\/da\/blog\/news\/sozdanie-kalkulyatora-chaevyh-na-kotlin-kak-eto-rabotaet","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0447\u0430\u0435\u0432\u044b\u0445 \u043d\u0430 Kotlin: \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442? | ProHoster","og:description":"\u0420\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0435.","og:url":"https:\/\/prohoster.info\/da\/blog\/news\/sozdanie-kalkulyatora-chaevyh-na-kotlin-kak-eto-rabotaet","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:43:27+00:00","article:modified_time":"2019-10-31T18:43:27+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"31843","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 08:07:20","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:10:45","updated":"2026-01-21 08:07:20","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/31843","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=31843"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/31843\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/23712"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=31843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=31843"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=31843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}