Gå til hovedindhold
Version2 it for professionelle
Forsiden

Hovedmenu

  • It-nyheder
  • Blogs
  • It-job
  • It-firmaer
  • Whitepapers
  • Opret bruger
  • Log ind
Du kan logge ind med din e-mail-adresse
Der er forskel på store og små bogstaver i adgangskoden.
Glemt adgangskode?
Emner Java, Android

Android-skolen del 5: Byg tre små robotter sammen til én stor

Sidste ombæring af Android-skolen får koden fra de tidligere afsnit til at spille i én og samme applikation. Kodeordene er faneblade og separate layout-filer til brugergrænsefladen.

Af Mikkel Meister Onsdag, 23. december 2009 - 14:42

Velkommen til femte og sidste lektion i Version2's Android-skole.

Denne gang går vi et spadestik dybere i den måde, androidens grafiske brugergrænseflade bygges op på.

Tanken er at vise, hvordan flere selvstændige applikationer ? eller activities - kan samles i én og samme brugergrænseflade, og det gør vi ganske enkelt ved at hugge koden fra afsnit 2, 3 og 4 af Android-skolen og lægge al funktionaliteten ind i én og samme applikation, adskilt grafisk af tre faneblade.

Denne gang er det altså mere 'skelettet' uden om koden, end selve koden, der fokuseres på.

Foreløbig har vi set på forskellige typer af views og layouts. For eksempel brugte vi et ListView til at vise kontakterne i telefonbogen i Android-skolen del 2, mens Android-skolen del 3 bød på et MapView til vores Google Maps/GPS-applikation.

Under første faneblad placeres telefonbogen fra afsnit 2. Andet faneblad indeholder Google Maps/GPS-applikationen fra afsnit 3, og tredje faneblad viser applikationen fra afnit 4, der demonstrerer trådning af den grafiske brugergrænseflade.

Gæsteunderviser er denne gang atter Klaus Kartou, der er en af hovedudviklerne bag den danske koncertapplikation til Android-platformen, Gigbox.

»Tabs er generelt en god måde at samle forskellig funktionalitet i samme vindue. Det gør det nemt for brugeren at overskue flere activities og skifte imellem dem,« siger Klaus Kartou.

1) Lidt teori om GUI-design med Android

Filen R.java (ligger under projektundermappen 'gen') forbinder vores Java-kildekode med det grafiske layout af brugergrænsefladen, der specificeres i XML-filen main.xml. R.java autogenereres ud fra layoutet i main.xml, og derfor ændrer vi aldrig direkte i den.

I de foregående afsnit har vi holdt os til at definere layoutet i én og samme fil, main.xml, men da vi denne gang skal håndtere flere forskellige slags views i samme brugergrænseflade, skal der flere XML-filer på banen.

Idéen er derfor at oprette nye XML-filer til hvert af de tre faneblade i applikationen. Vi ender derfor med filerne:

  • main.xml: Indeholder det overordnede faneblad-layout.
  • phonebook.xml: Indeholder layoutet af telefonbog-applikationen
  • mapview.xml: Indeholder layoutet af Google Maps/GPS-applikationen
  • progressbar.xml: Indeholder layoutet af trådning-applikationen, der viser en progressbar.

De største ændringer sker i main.xml, idet de andre XML-filer blot indeholder layoutet som angivet i de respektive afsnit af Android-skolen.

2) Opret projekt og klasse-filer

Start Eclipse.

Opret et nyt Android-projekt, ganske som du plejer. Navngiv applikationen som vist nedenfor, eller efter eget valg.

Bemærk, at du skal vælge Google API'et i version 1.6, da faneblad nummer to som nævnt indeholder Google Maps-applikationen.

Du har nu oprettet projektet med selve hovedklassen AndroidSkolenDel5, som er ansvarlig for at oprette faneblade og lægge applikationerne fra afsnit 2, 3 og 4 ind under dem.

Indtil videre indeholder AndroidSkolenDel5 blot en autogenereret onCreate()-metode, og vi lader den stå sådan et øjeblik.

Nu skal du oprette de klasser, der indeholder koden til de tre foregående applikationer. Opret filerne

  • MyPhoneBook.java
  • MyMap.java
  • MyProgressBar.java

og sørg for, at de ligger placeret samme sted som AndroidSkolenDel5.java (underbiblioteket 'src').

Herefter tager du 'indmaden' fra klasserne i de foregående afsnit af Android-skoeln og kopierer koden ind i de nyoprettede filer efter fremgangsmåden:

  • AndroidSkolenDel2.java -> MyPhoneBook.java
  • AndroidSkolenDel3.java -> MyMap.java
  • AndroidSkolenDel4.java -> MyProgressBar.java

Husk at sætte de nye klasser til arve fra de samme klasser og interfaces, som var tilfældet i de 'gamle' klasser.

  • MyPhoneBook.java: extends ListActivity
  • MyMap.java: extends MapActivity implements LocationListener
  • MyProgressBar.java: extends Activity

Dermed ser eksempelvis MyMap.java nu sådan ud (forkortet i bunden):

01 **public class **MyMap **extends **MapActivity **implements **LocationListener { 02   **private **Location location; 03   **private **MapView mapView; 04   **private **MapController mc; 05   **private **LocationManager locationManager; 06  07   **public ****void **onCreate(Bundle savedInstanceState) { 08     **super**.onCreate(savedInstanceState); 09     setContentView(R.layout.main); 10  11     mapView = (MapView) findViewById(R.id.mapview1); 12     mapView.setBuiltInZoomControls(**true**); 13     mc = mapView.getController(); 14   } 15  16   **protected ****void **onResume() { 17     List providers; 18     **super**.onResume(); 19         ...

3) Definer layouts i XML-filer

Som nævnt tidligere skal du oprette nye XML-filer til hver af de tre activities, der skal vises i hver deres faneblad.

  • main.xml: Indeholder det overordnede faneblad-layout.
  • phonebook.xml: Indeholder layoutet af telefonbog-applikationen
  • mapview.xml: Indeholder layoutet af Google Maps/GPS-applikationen
  • progressbar.xml: Indeholder layoutet af trådning-applikationen, der viser en progressbar.

Main.xml er oprettet til os på forhånd. Den lader vi ligge et øjeblik.

Vi går videre med at kopiere layoutet fra filen main.xml i projekterne Android-skolen del 2, 3 og 4 ind i tre nye XML-filer.

  • phonebook.xml
  • mapview.xml
  • progressbar.xml

Filerne oprettes i Eclipse ved at taste ctrl+N og vælge Android XML File under punktet Android.

XML-filerne ser nu ud som følger:

  • phonebook.xml:
01 <?xml version="1.0" encoding="utf-8"?> 02 "http://schemas.android.com/apk/res/android" 03   android:orientation="vertical" android:layout_width="fill_parent" 04   android:layout_height="fill_parent"> 05   "@id/android:list" android:layout_width="fill_parent" 06     android:layout_height="fill_parent" android:layout_weight="1" /> 07   "@+id/name" android:textSize="18px" 08     android:textStyle="bold" android:layout_width="fill_parent" 09     android:layout_height="wrap_content" /> 10   "@+id/phone_number" android:layout_width="fill_parent" 11     android:layout_height="wrap_content" /> 12 

Læg her mærke til, at vi har tilføjet et ListView-tag til phonebook.xml i linje 5-6, da vi ellers får en fejl på runtime.

  • mapview.xml:
01 <?xml version="1.0" encoding="utf-8"?> 02 "http://schemas.android.com/apk/res/android" 03   android:orientation="vertical" android:layout_width="fill_parent" 04   android:layout_height="fill_parent"> 05  06    07     android:id="@+id/mapview1" android:layout_width="fill_parent" 08     android:layout_height="fill_parent" android:enabled="true" 09     android:clickable="true" android:apiKey="0Svjiran6ZYsb5ENaZ-B-_ZNl5p65sLmX87VuSQ" /> 10 
  • progressbar.xml:
01 <?xml version="1.0" encoding="utf-8"?> 02 "http://schemas.android.com/apk/res/android" 03   android:orientation="vertical" android:layout_width="fill_parent" 04   android:layout_height="fill_parent"> 05   "@+id/my_button" android:layout_width="100px" 06     android:layout_height="wrap_content" android:text="foo" /> 07   "@+id/progress_bar" 08     android:layout_width="fill_parent" android:layout_height="wrap_content" 09     style="?android:attr/progressBarStyleHorizontal" /> 10 

Nu har du oprettet XML-filerne og skal derefter blot bede Java-filerne om at hente layoutet derfra, i stedet for i main.xml.

Det gøres ganske enkelt ved at erstatte metodekaldet setContentView(R.layout.main) i linje to af onCreate()-metoden i de tre filer MyPhoneBook.java, MyMap.java og MyProgressBar.java med henholdsvis

  • MyPhoneBook.java: setContentView(R.layout.phonebook)
  • MyMap.java: setContentView(R.layout.mapview)
  • MyProgressBar.java: setContentView(R.layout.progressbar)

Bemærk, at du i MyPhoneBook.java også skal ændre i metodekaldet

cursorAdapter = new SimpleCursorAdapter(this, R.layout.main, c, columns, contacts);

nederst i onCreate()-metoden. Her skal andet argument, R.layout.main, også ændres til R.layout.phonebook.

4) Opret fanebladene

Nu har du oprettet tre nye klasser, som definerer de activities, vi gerne vil afvikle i de tre faneblade i vores layout, og du har samtidig skabt tre nye XML-filer, der indeholder de respektive layouts til de tre activities.

Inden vi skriver kode i selve hovedklassen, AndroidSkolenDel5.java, lægger vi ud med at definere layoutet for klassens activity i main.xml.

01 <?xml version="1.0" encoding="utf-8"?> 02 "http://schemas.android.com/apk/res/android" 03   android:id="@android:id/tabhost" android:layout_width="fill_parent" 04   android:layout_height="wrap_content" layout_weight="1"> 05   "vertical" 06     android:layout_width="fill_parent" android:layout_height="fill_parent"> 07     "@android:id/tabs" 08       android:layout_width="fill_parent" android:layout_height="wrap_content" /> 09     "@android:id/tabcontent" 10       android:layout_width="fill_parent" android:layout_height="fill_parent"> 11      12    13 

Vi har her defineret en TabHost, der indeholder hele layoutet for vores activity. En TabHost skal indeholde en TabWidget og et FrameLayout som underelementer, og vi sørger for at layoute dem ordenligt i et LinearLayout. Framelayoutet er der, vi opbevarer det indhold, der skal være i et faneblad.

Med layoutet på plads i main.xml retter vi nu opmærksomheden mod vores hovedklasse, AndroidSkolenDel5.java. Her skal du nu oprette fanebladene og fylde dem ud med indholdet af de tre activities.

Det gøres ved at oprette en såkaldt TabHost og fortælle den, hvad du gerne vil have puttet ind i de enkelte faneblade.

Begynd med at sætte AndroidSkolenDel5.java til at arve fra TabActivity i stedet for Activity.

Dernæst fylder vi onCreate()-metoden ud med kode som følger:

01 **public class **AndroidSkolenDel5 **extends **TabActivity { 02  03   **private **TabHost mTabHost; 04  05   **public ****void **onCreate(Bundle savedInstanceState) { 06     **super**.onCreate(savedInstanceState); 07     setContentView(R.layout.main); 08  09     mTabHost = getTabHost(); 10  11     Context ctx = getApplicationContext(); 12      13     Intent phoneBook = **new **Intent(ctx, MyPhoneBook.**class**); 14     Intent map = **new **Intent(ctx, MyMap.**class**); 15     Intent progressBar = **new **Intent(ctx, MyProgressBar.**class**); 16      17     mTabHost.addTab(mTabHost.newTabSpec("tab_test1").setIndicator("Fane 1") 18         .setContent(phoneBook)); 19     mTabHost.addTab(mTabHost.newTabSpec("tab_test2").setIndicator("Fane 2") 20         .setContent(map)); 21     mTabHost.addTab(mTabHost.newTabSpec("tab_test3").setIndicator("Fane 3") 22         .setContent(progressBar)); 23      24     mTabHost.setCurrentTab(0); 25   } 26 }

Vi tager den ét skridt ad gangen.

I linje 9 benytter vi metodekaldet getTabHost() til at hente en reference til den TabHost, vi har defineret i layoutet i main.xml.

I linje 11 henter vi den kontekst, vores applikation har lige nu, med kaldet getApplicationContext().

Det bruges som argument til de tre Intents, vi definerer i linje 13-15. Et Intent er en abstraktion over en handling, vi gerne vil udføre ? i dette tilfælde telefonbogen, kortapplikationen og trådapplikationen ? som vi efterfølgende giver med som argument til metodekaldene i linje 17-22, der tilføjer tre faneblade med indhold til vores TabHost.

»TabActivity benytter Intents til at specificere, hvilken activity der er knyttet til en given tab. Når brugeren klikker på en tab, startes den pågældende activity, og dens tilhørende vindue indsættes i TabActivitiens tab-contentview,« siger Klaus Kartou.

I linje 24 slutter vi af med at sætte det første faneblad som den aktuelle fane og dermed den første fane, brugeren ser, når applikationen startes op.

5) Sæt permissions og activities i manifestet

Sidste punkt på listen, inden vi kan køre vores nye applikation, er at sætte de permissions, vi skal bruge, i AndroidManifest.xml.

Det drejer sig om de fem uses-permission-tags vist i linje 4-10 herunder:

01 <?xml version="1.0" encoding="utf-8"?> 02 "http://schemas.android.com/apk/res/android" 03   **package**="dk.version2.as5" android:versionCode="1" android:versionName="1.0"> 04   "android.permission.ACCESS_FINE_LOCATION"> 05    06   "android.permission.ACCESS_COARSE_LOCATION"> 07    08   "android.permission.INTERNET"> 09   "android.permission.READ_CONTACTS"> 10   "android.permission.CALL_PHONE"> 11   "@drawable/icon" android:label="@string/app_name" 12     android:debuggable="true"> 13     "com.google.android.maps" /> 14     ".AndroidSkolenDel5" android:label="@string/app_name"> 15     ...

, der giver os lov til at bruge både GPS og triangulering og tilgå dataforbindelsen til Google Maps/GPS-applikationen, samt læse kontakterne fra telefonens adressebog og ringe dem op i telefonbog-applikationen.

Samtidig har vi defineret i linje 13, at vores applikation bruger Google Maps.

Som det ser ud lige nu, har vi kun defineret AndroidSkolenDel5.java som en activity i manifestet. For at kunne afvikle de tre foregående applikationer i fanebladene, skal vi også definere dem som activities i manifestet.

Det gøres ved at tilføje tre activities efter activity'en AndroidSkolenDel5:

1     ...   2      3     ".MyPhoneBook" android:label="@string/app_name"> 4      5     ".MyMap" android:label="@string/app_name"> 6      7     ".MyProgressBar" android:label="@string/app_name"> 8      9     ...

Dermed kommer det samlede manifest til at se således ud:

01 <?xml version="1.0" encoding="utf-8"?> 02 "http://schemas.android.com/apk/res/android" 03   **package**="dk.version2.as5" android:versionCode="1" android:versionName="1.0"> 04   "android.permission.ACCESS_FINE_LOCATION"> 05    06   "android.permission.ACCESS_COARSE_LOCATION"> 07    08   "android.permission.INTERNET"> 09   "android.permission.READ_CONTACTS"> 10   "android.permission.CALL_PHONE"> 11   "@drawable/icon" android:label="@string/app_name" 12     android:debuggable="true"> 13     "com.google.android.maps" /> 14     ".AndroidSkolenDel5" android:label="@string/app_name"> 15        16         "android.intent.action.MAIN" /> 17         "android.intent.category.LAUNCHER" /> 18        19      20     ".MyPhoneBook" android:label="@string/app_name"> 21      22     ".MyMap" android:label="@string/app_name"> 23      24     ".MyProgressBar" android:label="@string/app_name"> 25      26    27   "4" /> 28 

Gem projektet og oversæt og kør det med ctrl+b efterfulgt af ctrl+F11.

Nu kan du vælge mellem applikationerne fra de foregående afsnit af Android-skolen i de tre faneblade:

Hermed er du færdig med den femte og sidste undervisningstime i Android-skolen.

»Ønsker man at ændre radikalt på funktionaliteten eller udseendet af tabs, er det desværre ikke helt ligetil. Da TabActivity er en specialisering af klassen ActivityGroup, kan man i stedet implementere sin egen ActivityGroup. I Gigbox har vi lagt tabs i bunden og indført vores eget tab-layout netop via denne metode,« siger Klaus Kartou.

Et skræddersyet faneblad-layout i Gigbox-applikationen. Her er de tre tabs placeret i bunden af skærmbilledet med egne ikoner. (Grafik: Gigbox).

»Et godt råd er at gennemtænke layoutet af ens activity, inden man går igang. Tegn eventuelt en tegning på et stykke papir og overvej, hvilke GUI-komponenter, der kan bruges til at indfri den,« siger Klaus Kartou.

Litteratur: [1] http://developer.android.com

Skab Danmarks bedste Android-applikation og vind en eksklusiv tur med alt betalt til verdens største mobilmesse i Barcelona. Deadline er 11. januar 2010. Læs mere på http://www.version2.dk/android

Send Tweet
Udskriv

IT-job & karriere

  • Se alle it-job
  • Importer din kompetenceprofil fra LinkedIn
Java udviklere – backend – gerne med Oracle erfaring
Udgivet 16. jun 2011 14.38
Java udviklere – Web-frontend
Udgivet 16. jun 2011 14.21
Java EE/Web Developer (7261)
Udgivet 7. maj 15.02
Mobility arkitekt
Udgivet 7. dec 2011 13.13

Tilføj kommentar

Opret en konto eller log ind for at følge indhold på Version2 - og bliv opdateret via e-mail eller rss

Følg kommentarer
Log ind herunder eller opret en bruger for at skrive kommentarer
Du kan logge ind med din e-mail-adresse
Der er forskel på store og små bogstaver i adgangskoden.
Glemt adgangskode?

Seneste nyt

GOTO Copenhagen dag 2 i billeder: Op med hænderne!

Udgivet 22. maj 16.02Opdateret 22. maj 17.02

Staten køber hardware for 1,2 milliarder - her er de syv heldige

Udgivet 22. maj 15.37Opdateret 22. maj 15.37

Firmaer leder efter ’ninjaer’ - men skriv det ikke på CV’et

Udgivet 22. maj 14.54Opdateret 22. maj 15.48

Ny Linux-kerne giver højere sikkerhed og bedre grafikkort-understøttelse

Udgivet 22. maj 14.13Opdateret 22. maj 14.13

Nu skal Google Chrome indtage iPhone og iPad

Udgivet 22. maj 13.20Opdateret 22. maj 13.20

Flere it-nyheder »

Tilmeld dig Version2's it-nyhedsbrev og vind den nye iPad.

Whitepapers

Kick-start your master data management initiative

Affecto Denmark

Affecto Data Quality Assessment: Er din indsigt og beslutning baseret på validt data?

Affecto Denmark

Framework til datamigrering i SAP miljøer - spar op til 50% på dine Data Migration udgifter

Affecto Denmark

Få et Data Warehouse (DW) review hos Affecto

Affecto Denmark

Ressourcehåndtering

Projectplace
  • Flere whitepapers

Branchenyheder

Konica Minoltas stand på drupa 2012 slog besøgsrekord

Konica Minolta Business Solutions Denmark

Komplex it er blevet Brocade Premier Partner

Komplex IT

Øg din effektivitet og produktivitet med bizhub C654/C754

Konica Minolta Business Solutions Denmark

Brugerfjendtlige it-løsninger gør brugerne til en sikkerhedstrussel

Projectplace

Athena IT-Group A/S med solid indtjening

Athena IT-Group

Seneste debat

  1. Cisco kan være en dyr netværksreligion

    14 comments.
    Last update 6 timer 19 minutter
    Skrevet af Jens Jönsson
  2. Microsoft fjerner umoderne bling-effekter i Windows 8

    35 comments.
    Last update 6 timer 57 minutter
    Skrevet af Chano Klinck Andersen
  3. Finansminister afliver teori om NemID som spionsoftware

    22 comments.
    Last update 7 timer 8 minutter
    Skrevet af Niels Elgaard Larsen
  4. Datamatikere i Skive får gratis smartphone til .Net-udvikling

    3 comments.
    Last update 7 timer 21 minutter
    Skrevet af Martin Slot
  5. Dart: Dynamisk Statisk Programmering

    11 comments.
    Last update 7 timer 51 minutter
    Skrevet af Casper Bang
  6. Partner solgte Netgroups 'test-platform' med overskriften 'fuld redundans'

    16 comments.
    Last update 8 timer 12 minutter
    Skrevet af Jacob Bach Pedersen
  7. To psykologiske årsager til at IT-projekter går galt

    15 comments.
    Last update 8 timer 19 minutter
    Skrevet af Robert Voje
  8. Staten køber hardware for 1,2 milliarder - her er de syv heldige

    4 comments.
    Last update 9 timer 3 minutter
    Skrevet af Thomas Hansen

Mere debat »

It-virksomheder

Relation House
|
Mobile Advisor
|
Ciklum
|
Avenida
|
Visma
|
Omada
|
Nhouse
|
Simpelt Regnskab
|
Cbrain
|
Rehfeld
|
Queue-IT
|
BEC
 

Information

  • Kontakt redaktionen
  • Job- og annoncesalg
  • Teknisk support
  • Om Version2
  • Brugerbetingelser
  • Privatlivspolitik

Aktuelle emner

  • Agil udvikling
  • Android
  • Bruttolønsordning
  • Business Intelligence
  • Cloud computing
  • Download Windows 8
  • HTML5
  • Harddisk-priser
  • IE9
  • Intranet
  • It-sikkerhed
  • Kindle Fire
  • Multimedieskat
  • NemID
  • OS X Mountain Lion
  • Open source CMS
  • Projektledelse
  • Scrum
  • Sharepoint intranet
  • Storage
  • Ubuntu 11.10
  • Virtualisering
  • Windows 8
  • Windows Phone 7
  • iOS 5
  • iPhone 4S

Tjenester

  • Android-app
  • iPhone-app
  • RSS-feeds
Følg @version2dk
Tilmeld dig Version2's it-nyhedsbrev og vind den nye iPad.

Version2 udgives af

  • Mediehuset Ingeniøren A/S work Skelbækgade 4 1717 København V
  • Tlf. work 33265300