Common Android Views Cheat Sheet http labs udacity
Common Android Views Cheat Sheet http: //labs. udacity. com/images/Common-Android-Views-Cheat-Sheet. pdf 23/10/2021 igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android 6
Υποδοχέας Relative. Layout <Relative. Layout xmlns: android="http: //schemas. android. com/apk/res/android" android: layout_width="match_parent" android: layout_height="match_parent"> <Text. View android: id="@+id/lyla_text_view" // ορίζει το όνομα android: layout_align. Parent. Bottom="true" android: layout_align. Parent. Left="true" android: text. Size="24 sp" android: text="Lyla" /> <Text. View android: id="@+id/me_text_view" android: layout_align. Parent. Bottom="true" android: layout_to. Right. Of="@id/lyla_text_view"//αναφορά στην όψη android: text. Size="24 sp" android: text="Me" /> <Text. View android: id="@+id/ben_text_view" android: layout_align. Parent. Top="true" android: layout_center. Horizontal="true" android: text. Size="24 sp" android: text="Ben" /> <Text. View android: id="@+id/kunal_text_view" android: layout_align. Parent. Top="true" android: layout_to. Left. Of="@id/ben_text_view" android: text. Size="24 sp" android: text="Kunal" /> </Relative. Layout> 23/10/2021 igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android Για να προσδιορίσεις μια όψη της δίνεις μοναδικό όνομα με το android: id="@+id/view_name" Το @+id προσθέτει νέο όνομα στην περιοχή ονομάτων που πλέον μπορεί να χρησιμοποιείται ως προσδιοριστικό του αντικειμένου. Το όνομα πρέπει να είναι μοναδικό. Για να αναφερθείς στο αντικείμενο, η σύνταξη είναι "@id/view_name" χωρίς το +. Ποιος το σκέφτηκε αυτό! Στον υποδοχέα Relative. Layout η τοποθέτηση (Top, Bottom, Left, Right) γίνεται με σχέση με το γονιό. Ακόμα, μπορούμε να τοποθετήσουμε σε σχέση με τα αδέρφια (to. Right. Of, to. Left. Of, above, below), χρησιμοποιώντας τα ονόματά τους. Μια όψη περικλείει ερμητικά τα περιεχόμενά της αν θέσουμε width και height στην τιμή wrap_content. Για να δώσουμε χώρο γύρω από τα περιεχόμενα, μπορούμε να ορίσουμε την ιδιότητα padding. Εξ ορισμού, δυο όψεις ακουμπούν όταν τοποθετούνται πλάι-πλάι. Για να μην εφάπτονται, μπορούμε να ορίσουμε layout_margin έξω από όλες τις πλευρές (Left, Right, Top, Bottom). 8
Ευχετήρια κάρτα Φτιάχνουμε μια app που προβάλει μια φωτό με ευχές και τον αποστολέα; Χρειάζεται ένα Image. View για τη φωτό και δύο Text. View για τα κείμενα. Στη σχεδίαση του παρουσιαστικού με XML εξοικειωθείτε με τις δυνατότητες που δίνουν τα παράθυρα 'Palette', 'Component Tree', 'Properties' για να βλέπεις και να αλλάζεις την XML. <? xml version="1. 0" encoding="utf-8"? > <Relative. Layout xmlns: android="http: //schemas. android. com/apk/res/android" xmlns: tools="http: //schemas. android. com/tools" android: id="@+id/activity_main" android: layout_width="match_parent" android: layout_height="match_parent" tools: context="com. mycomp. myapplication. Main. Activity"> Λόγω της τοποθέτησης στα άκρα προτιμούμε να τα εντάξουμε σε ένα υποδοχέα Relative. Layout. Δείτε το όνομα που του δίνει και τις διαστάσεις που καλύπτουν όλη την οθόνη. <Image. View android: id="@+id/img. Card" android: layout_width="match_parent" android: layout_height="match_parent" android: scale. Type="center. Crop" android: src="@drawable/mydino" /> Τοποθετούμε το Image. View, του δίνουμε όνομα, ορίζουμε διαστάσεις για να εκτείνεται σε όλο τον υποδοχέα. <Text. View android: id="@+id/efhes" android: layout_width="wrap_content" android: layout_height="wrap_content" android: layout_align. Parent. Top="true" android: layout_center. Horizontal="true" android: text="Καλό καρναβάλι" android: text. Size="40 dp" /> Αποθηκεύουμε μια φωτό στο φάκελο drawable του έργου και προσθέτουμε την ιδιότητα android: src να δείχνει στο αρχείο της φωτό, χωρίς την κατάληξη. Εισάγουμε τα δυο κείμενα μέσα στον υποδοχέα. Πρέπει να είναι μετά την εικόνα (γιατί; ). Τοποθετούμε με τις κατάλληλες ιδιότητες align και λοιπά διακοσμητικά (μέγεθος, χρώμα). 23/10/2021 <Text. View android: id="@+id/ypografi" android: layout_width="wrap_content" android: layout_height="wrap_content" android: layout_align. Parent. Bottom="true" android: layout_align. Parent. Right="true" android: text="Ο δεινόσαυρος" android: text. Color="#FFFFFF" android: text. Size="40 dp" /> </Relative. Layout> igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android 17
Σκορ μπάσκετ: πρόγραμμα package com. mycomp. mybasket; import android. os. Bundle; android. support. v 7. app. App. Compat. Activity; android. view. View; android. widget. Text. View; public class Main. Activity extends App. Compat. Activity { int i. Skor. A = 0; //τοπικές μεταβλητές για τα σκορ int i. Skor. B = 0; public void syn 3 B(View v){ i. Skor. B += 3; //τρίποντο display. B(); } public void syn 2 B(View v){ i. Skor. B += 2; //δίποντο display. B(); } 2 public void syn 1 B(View v){ i. Skor. B ++; //ελεύθ. βολές display. B(); } @Override protected void on. Create(Bundle saved. Instance. State) { super. on. Create(saved. Instance. State); set. Content. View(R. layout. activity_main); } public void midenise(View v){ //για το κουμπί Μηδένισε! i. Skor. A = 0; public void syn 3 A(View v){ display. A(); i. Skor. A += 3; //τρίποντο i. Skor. B = 0; display. A(); display. B(); } } public void syn 2 A(View v){ private void display. A(){ i. Skor. A += 2; //δίποντο Text. View tv. Skor. A = (Text. View) find. View. By. Id(R. id. txt. Skor. A); display. A(); tv. Skor. A. set. Text("" + i. Skor. A); } } public void syn 1 A(View v){ private void display. B(){ i. Skor. A ++; //ελεύθ. βολές Text. View tv. Skor. B = (Text. View) find. View. By. Id(R. id. txt. Skor. B); display. A(); tv. Skor. B. set. Text("" + i. Skor. B); } } 1 3 } //end class 23/10/2021 igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android 19
Επόπτης ιστοσελίδων (browser) Νέο έργο. Στο Edit. Box θα εισάγουμε μια διεύθυνση και πατώντας το Button θα προβάλει το περιεχόμενο της ιστοσελίδας. package com. mycomp. mybrowser; import import android. os. Bundle; android. support. v 7. app. App. Compat. Activity; android. view. View; android. webkit. Web. View. Client; android. widget. Button; android. widget. Edit. Text; public class Main. Activity extends App. Compat. Activity { @Override protected void on. Create(Bundle saved. Instance. State) { super. on. Create(saved. Instance. State); set. Content. View(R. layout. activity_main); et. Url = (Edit. Text) find. View. By. Id(R. id. edt. Url); bt. Go = (Button) find. View. By. Id(R. id. btn. Go); wv. Othoni = (Web. View) find. View. By. Id(R. id. web. Othoni); wv. Othoni. set. Web. View. Client(new Web. View. Client()); } Πίσω wv. Othoni. go. Back() Μπρος wv. Othoni. go. Forward() Προσθέσετε κουμπιά Edit. Text et. Url; Button bt. Go; Web. View wv. Othoni; public void go. To. Page(View v) { String s. Url = et. Url. get. Text(). to. String(); wv. Othoni. load. Url("http: //" + s. Url); } } Υλοποιήσετε 'Αγαπημένα'. Πχ πληκτρολογώντας '1' να προβάλει 'http: //www. imdb. gr' 23/10/2021 igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android 22
Δικαιώματα και εικονίδιο Στο αρχείο manifests/Android. Manifest. xml δηλώνουμε τα δικαιώματα που πρέπει να έχει η εφαρμογή για να λειτουργεί σωστά. Για να προσπελάσει το Internet, η εφαρμογή χρειάζεται το δικαίωμα: <uses-permission android: name="android. permission. INTERNET" /> (Διακοσμητικό) Για να μη βάζει ως εικονίδιο της εφαρμογής το άσχημο ανθρωποειδές (Android): • Αποθηκεύουμε στο φάκελο res/drawable ένα png αρχείο. • Στο Android. Manifest. xml στην ενότητα application προσθέτουμε την ιδιότητα android: icon να δείχνει προς το όνομα του αρχείου με το νέο εικονίδιο <? xml version="1. 0" encoding="utf-8"? > <manifest xmlns: android="http: //schemas. android. com/apk/res/android" package="com. mycomp. mybrowser"> <uses-permission android: name="android. permission. INTERNET" /> <application android: allow. Backup="true" android: icon="@drawable/doggy" android: label="@string/app_name" android: round. Icon="@mipmap/ic_launcher_round" android: supports. Rtl="true" android: theme="@style/App. Theme"> <activity android: name=". Main. Activity"> <intent-filter> <action android: name="android. intent. action. MAIN" /> <category android: name="android. intent. category. LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 23/10/2021 igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android 23
Παραγγελία καφέδων Θα εξελίξουμε την εφαρμογή με περισσότερες επιλογές, πχ καφές με σαντιγί. public class Main. Activity extends App. Compat. Activity { final double timi. Kafe = 1. 6; // σταθερές final double timi. Santigy = 0. 5; int posotita = 0; //μεταβλητή κλάσης Θα υπολογίζει πόσο κάνουν οι καφέδες και θα τυπώνει ανάλογο μήνυμα. @Override protected void on. Create(Bundle saved. Instance. State) {. . . } public void anevase(View view) {. . . } public void katevase(View view) {. . . } txt. Posotita public void parageile(View view) { double axia; Check. Box cb. Extra = (Check. Box) find. View. By. Id(R. id. chk. Extra); String s. Extras; if (cb. Extra. is. Checked()) { s. Extras = "Με σαντιγύ"; axia = posotita * (timi. Kafe + timi. Santigy); } else { s. Extras = "Χωρίς σαντιγύ"; axia = posotita * timi. Kafe; } String s. Paraggelia = "Ποσότητα: " + posotita + "n" + s. Extras + "nΑξία: " + Number. Format. get. Currency. Instance(). format(axia) + "nΕυχαριστώ πολύ!"; chk. Extra paraggeile txt. Paraggelia Για να μετακινείται κατακόρυφα η οθόνη σε περίπτωση που δεν χωράνε όλες οι όψεις στην οθόνη (ή γυρίσουμε σε οριζόντια διάταξη), τυλίγουμε όλες τις όψεις της διεπαφής στον υποδοχέα Scroll. View. 23/10/2021 Όπου. . . δες τον κώδικα στη διαφάνεια 'UI και κώδικας για παραγγελία' Text. View tv. Paraggelia = (Text. View) find. View. By. Id(R. id. txt. Paraggelia); tv. Paraggelia. set. Text(s. Paraggelia); } public void display. Posotita() {. . . } } igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android 24
Σκορ ντόμινο: πόροι <? xml version="1. 0" encoding="utf-8"? > <manifest xmlns: android="http: //schemas. android. com/apk/res/android" package="com. mycomp. domino"> Ορίζει νέο σχήμα που χρησιμοποιείται ως φόντο από κάποιες όψεις. <application android: allow. Backup="true" Παραπέμπει σε αρχείο android: icon="@drawable/domino_icon" με το εικονίδιο. android: label="@string/app_name" android: supports. Rtl="true" android: theme="@style/App. Theme. No. Action. Bar"> <activity Ορίζει το όνομα android: name=". Main. Activity" της εφαρμογής. android: label="@string/app_name" android: theme="@style/App. Theme. No. Action. Bar"> <intent-filter> <action android: name="android. intent. action. MAIN"/> <category android: name="android. intent. category. LAUNCHER"/> </intent-filter> </activity> </application> </manifest> Είναι στο res/drawable. <shape xmlns: android=". . . " android: shape="rectangle"> <corners android: radius="20 dp"/> <padding android: bottom="10 dp" android: left="10 dp" android: right="10 dp" android: top="10 dp"/> <solid android: color="#e 1 bee 7"/> </shape> 23/10/2021 Ορίζει στιλ που μπορούν να χρησιμοποιούν οι όψεις της διεπαφής. Κάτι σαν τα CSS για την HTML. Είναι στο res/values. <resources> Διαφάνεια <style name="layout. Style"> <item name="android: alpha">0. 7</item> <item name="android: background">#cddc 39</item> </style> </resources> igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android 33
Σκορ ντόμινο: διεπαφή Layout της activity Αποτελείται από υποδοχείς Linear. Layout που οργανώνουν σε ομάδες Edit. Text, Text. View, Button. <Linear. Layout. . . android: background="@drawable/domino_back" android: orientation="vertical"> Εικόνα παρασκηνίου Παραπέμπει σε στιλ για ομοιομορφία. <Edit. Text android: id="@+id/omada 1" style="@style/live. Text. Style" android: input. Type="text" Μία γραμμή κειμένου android: text="Ομάδα Α"/> <Text. View android: id="@+id/partida 1" Για ισοκατανομή style="@style/text. Style" android: layout_width="0 dp" android: layout_height="wrap_content" android: layout_weight="1" Για ισοκατανομή android: background="#11 EE 11" android: on. Click="anevase 1" Μέθοδος που android: text="0"/> εκτελείται στο κλικ 23/10/2021 <Edit. Text Δεκαδικός αριθμός android: id="@+id/orio" style="@style/live. Text. Style" android: input. Type="number. Decimal" android: text="31"/> igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android 34
Αποσπάσματα κώδικα (Snippets) Check. Box cb = (Check. Box) find. View. By. Id(R. id. is. Ok); String s; if (cb. is. Checked()) { s = "Εντάξει"; } else { s = "Πρόβλημα"; } //Τοποθέτηση κειμένου σε Text. View tv. Etos = (Text. View) find. View. By. Id(R. id. txt. Etos); tv. Etos. set. Text("2017"); //Ανάγνωση κειμένου από Edit. Text et. Xora = (Edit. Text) find. View. By. Id(R. id. edt. Hora); String s = et. Hora. get. Text(). to. String(); //Αποστολή email Intent i = new Intent(Intent. ACTION_SENDTO); i. set. Data(Uri. parse("mailto: ")); i. put. Extra(Intent. EXTRA_SUBJECT, "Γεια"); if (i. resolve. Activity(get. Package. Manager()) != null) start. Activity(i); //Άνοιγμα οθόνης με όνομα activity Othoni 2. java Intent i = new Intent(this, Othoni 2. class); start. Activity(i); Το σ ν ο κ 23/10/2021 ι κ ά … //Στιγμιαία ειδοποίηση import android. widget. Toast; Toast. make. Text(get. Application. Context(), "Γεια χαρά. . . ", Toast. LENGTH_SHORT). show(); //Παίζει τραγουδάκι από το αρχείο /res/raw/a. Song. mp 3 import android. media. Media. Player; Media. Player mp = Media. Player. create(this, R. raw. a. Song); mp. start(); Video. View vv = (Video. View) find. View. By. Id(R. id. vid_frame); //δέσιμο XML και Java String p = "android. resource: //" + get. Package. Name() + "/" + R. raw. some. Video; vv. set. Video. URI(Uri. parse(p)); //το πλήρες όνομα του αρχείου που θα προβληθεί vv. start(); //ξεκινά να παίζει το βίντεο igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android 37
Δικαιώματα αρχείου ΒΔ Του είπαμε να αποθηκεύσει τη ΒΔ στο φάκελο Android/data/όνομα. του. πακέτου/files/. Για σιγουριά πρέπει να δώσουμε στην εφαρμογή δικαιώματα προσπέλασης στην external memory. Αυτό γίνεται προσθέτοντας στο Android. Manifest. xml τις <uses-permission android: name="android. permission. WRITE_EXTERNAL_STORAGE" /> <uses-permission android: name="android. permission. READ_EXTERNAL_STORAGE" /> Για το Android το "φυσιολογικό" είναι να δημιουργούμε τη ΒΔ με την εντολή super(context, DB_NAME, null, DB_VERSION); που αποθηκεύει το αρχείο στον προστατευμένο φάκελο για τις βάσεις δεδομένων της κάθε εφαρμογής /data/όνομα. του. πακέτου/databases/, όπου απαγορεύεται να τον προσπελάζουμε, παρά μόνον μέσα από την εφαρμογή! Για να το δεις με διαχειριστή αρχείων, πχ για να το αντιγράψεις πρέπει: 1. Να δηλώσεις στην ενότητα <application> του Android. Manifest. xml την android: debuggable="true" 2. Να αλλάξεις τα δικαιώματα του αρχείου με το εργαλείο ADB από ένα command prompt. Αν η συσκευή που τρέχει η εφαρμογή είναι rooted, μπορείς να πάρεις τη ΒΔ ακόμη κι αν δεν είναι debuggable η εφαρμογή, ακόμη κι αν δεν πειράξεις τα δικαιώματα του αρχείου. Ασφάλεια τρυπητήρι, δηλαδή. . . 23/10/2021 Microsoft Windows [Version 6. 1. 7601] Copyright (c) 2009 Microsoft Corporation. Ο Ted Codd θα έφριττε! All rights reserved. C: UsersUser>cd App. DataLocalAndroidsdkplatform-tools C: UsersUserApp. DataLocalAndroidsdkplatform-tools> adb shell@kenzo: / $ run-as com. mycomp. myapplication shell@kenzo: /data/com. mycomp. myapplication $ cd databases shell@kenzo: /data/com. mycomp. myapplication/databases $ ls -l -rw-rw---- u 0_a 232 16384 2017 -05 -29 00: 57 Zografies. db -rw------- u 0_a 232 8720 2017 -05 -29 00: 57 Zografies. db-journal shell@kenzo: /data/com. mycomp. myapplication/databases $ chmod 666 Petama 1. db shell@kenzo: /data/com. mycomp. myapplication/databases $ ls -al -rw-rw-rw- u 0_a 232 16384 2017 -05 -29 00: 57 Zografies. db -rw------- u 0_a 232 8720 2017 -05 -29 00: 57 Zografies. db-journal shell@kenzo: /data/com. mycomp. myapplication/databases $ exit igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android 41
Προσθήκη εγγραφών Για να προσθέσουμε νέα εγγραφή στον πίνακα χρησιμοποιούμε έναν κουβά από την κλάση Content. Values. Η insert. Data() κάνει τη δουλειά. public long insert. Data(String zografos, String pinakas, int etos, boolean prototipo, int idioktisia) { Content. Values content. Values = new Content. Values(); content. Values. put("zografos", zografos); content. Values. put("pinakas", pinakas); Προσθήκη στο Database. Helper. java content. Values. put("etos", etos); content. Values. put("prototipo", prototipo); content. Values. put("idioktisia", idioktisia); return mydb. insert("erga", null, content. Values); // κωδικός της νέας εγγραφής, ή -1 αν αποτύχει } Εναλλακτικά, αντί του Content. Values, θα μπορούσαμε να εκτελέσουμε μια εντολή SQL της μορφής με my. Db. exec. SQL("INSERT INTO erga VALUES (. . . )"); Η μέθοδος καλείται όταν πατηθεί το πλήκτρο "Προσθήκη" από τη βασική οθόνη. Στη μεταβλητή epilogi είναι ο κωδικός της ιδιοκτησίας, μετά από σαράντα κύματα. Μετά την κλήση της insert. Data() ελέγχουμε ότι η εισαγωγή εκτελέστηκε, γιατί μπορεί πχ τα δεδομένα που ρουφάει από την οθόνη να παραβιάζουν τους κανόνες ακεραιότητας. public void prosthiki(View v) { int epilogi = idioktisia. index. Of. Child(idioktisia. find. View. By. Id(idioktisia. get. Checked. Radio. Button. Id())); long pri_key = my. Db. insert. Data(zografos. get. Text(). to. String(), pinakas. get. Text(). to. String(), Integer. parse. Int(etos. get. Text(). to. String()), Προσθήκη στο prototipo. is. Checked(), Main. Activity. java epilogi); // 0=Αγορά, 1=Δανεικό, 2=Δωρεά if (pri_key == -1) Toast. make. Text(this, "Αποτυχία στην προσθήκη", Toast. LENGTH_LONG). show(); else Toast. make. Text(this, "Κωδικός νέας εγγραφής " + pri_key, Toast. LENGTH_LONG). show(); } 23/10/2021 igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android 42
Προβολή εγγραφών Για να προβάλουμε όλες τις εγγραφές του πίνακα, χρησιμοποιούμε έναν δρομέα από την κλάση Cursor. Με την SQL μπορούμε να ταξινομήσουμε, ή φιλτράρουμε τις εγγραφές. public Cursor get. All. Data() { return mydb. raw. Query("SELECT * FROM erga", null); } Προσθήκη στο Database. Helper. java Η μέθοδος εκτελείται όταν πατηθεί το πλήκτρο "Όλα". Παίρνει το δρομέα και τον ξεψαχνίζει. Συσσωρεύει σε μια String. Buffer όλες τις πληροφορίες και τις προβάλει με μια βοηθητική μέθοδο show. Message(). public void ola(View v) { Προσθήκη στο Main. Activity. java Cursor cursor = my. Db. get. All. Data(); if (cursor. get. Count() == 0) show. Message("Δεδομένα στον πίνακα", "Δεν βρέθηκε τίποτα. "); else { String. Buffer buffer = new String. Buffer(); while (cursor. move. To. Next()) { buffer. append("Κωδικός: " + cursor. get. String(0) + "n"); buffer. append("Ζωγράφος: " + cursor. get. String(1) + "n"); buffer. append("Πίνακας: " + cursor. get. String(2) + "n"); buffer. append("Έτος: " + cursor. get. String(3) + "n"); buffer. append("Πρωτότυπο: " + ((cursor. get. String(4). equals("0")) ? "Όχι" : "Ναι") + "n"); String s. Idioktisia = ""; public void show. Message(String title, switch (cursor. get. String(5)) { String message) { case "0": s. Idioktisia = "Αγορά"; break; Alert. Dialog. Builder builder = new case "1": s. Idioktisia = "Δανεικό"; break; Alert. Dialog. Builder(this); case "2": s. Idioktisia = "Δωρεά"; break; builder. set. Cancelable(true); } builder. set. Title(title); buffer. append("Ιδιοκτησία: " + s. Idioktisia + "nn"); builder. set. Message(message); } //end while builder. show(); show. Message("Δεδομένα στον πίνακα", buffer. to. String()); } } //end else } 23/10/2021 igaviotis@gmail. com - Ανάπτυξη εφαρμογών Android 43
- Slides: 46