Android Studio
Android Studio
Mai apoi, Google a propus un nou IDE - Android Studio, care are acela i scop(de a permite dezvoltarea de aplica ii mobile), dar ofer mai
multe faciliti n ceea ce privete instalarea mediului de lucru, performana, code completion and refactoring la nivel avansat, etc.
Dac dorii s instalai Android Studio pe laptop-urile personale, este suficient s ave i Java Development Kit (jdk) instalat, iar apoi pute i
descrca Android Studio de pe pagina oficial .
nainte de a testa primul program Hello World, ne vom concentra pe structura unui proiect Android. Aceast etap ne va ajuta s
nelegem rolul fiecrui director i fiier, fr de care nu am putea s dezvoltm o aplicaie Android.
Aadar, n mod implicit(modul Project), n partea din stanga a IDE-ului exist o vedere de ansamblu a ntregului proiect:
2
3
n Android Studio exist mai multe moduri de vizualizare a unui proiect, printre care i modul Android. Odat selectat aceast op iune,
Android Studio organizeaz fiierele n funcie de cele mai importante pr i ale unei aplica ii Android (fi iere java, ressources, scripturi
gradle). n funcie de nevoile i preferinele vostre, acest mod de afiare poate fi destul de practic:
Aadar:
fiierele java - sunt fiierele pe care le vei foloi probabil cel mai des, deoarece fiecare func ionalitate va fi
implementat n clasa corespunztoare
directorul res - unde sunt organizate toate resursele unei aplicaii. Aici putem gsi mai multe directoare, fiecare
coninnd n general fiere de tip .xml i imagini, precum:
4
n directorul drawable: se gsesc imagini(de tip .png, .jpg sau .gif) i/sau fiiere de tip .xml n care poate fi
definit o anumit form/culoare
n directorul layout: se gsesc fiiere .xml care definesc afiajul(interfaa grafic) i poziionarea diferitelor
elemente pe ecran.
n directorul menu: se gsesc fiiere .xml n care putem customiza meniul unei aplicaii
directorul mimap : este rezervat diferitelor iconie folosite ntr-o aplicaie. Dat fiind faptul c dispozitivele Android
sunt de diferite tipuri i mrimi, o imagine nu se poate adapta tuturor ecranelor existente, de aceea dimensiunile
acesteia trebuie s varieze.
values: n fiierele .xml din acest director se pot gsi/personaliza diferite elemente ale aplica iei. De exemplu,
putei defini un text(strings.xml), o anumit culoare(colors.xml), care s fie mai apoi folosite oriunde n cod. n
acest fel, dac avei nevoie s facei o modificare al unuia dintre aceste elemente, o vei face o singur dat.
gradle scripts: verific faptul c toate elementele necesare proiectului sunt disponibile; asigur asamblarea tuturor
dependenelor necesare.
Android Manifest
Pe lnge aceste fiiere i directoare (prezentate mai sus), la rdcina fiecrui proiect exist un fi ier numit AndroidManifest.xml. Acest
fiier conine detalii eseniale despre aplicaie, cum ar fi permisiunile i versiunea acesteia.
n etapa urmtoare vom face cteva setri simple. n fereastra de mai sus, introducei numele aplicaiei, HelloWorld.
Cmpul Company Domain identific n mod unic aplicaia. Astfel, dou aplicaii pot avea acela i nume, dar se vor diferen ia prin
domeniul companiei(dac exist), scris invers. n mod implicit, acest cmp este completat automat cu un domeniu fictiv.
6
Next!
Fereastra de mai sus simplific alegerea versiunii de Android - aceasta poate fi schimbat mai apoi n fi ierul build.gradle. Pentru
moment, nu vom modifica nimic aici. Next!
7
Pentru a ne uura munca, Android Studio propune diferite schelete de aplica ie. Pentru aplica ia noastr, HelloWorld, vom
alege BlankActivity.
8
Vom afla mai multe despre ce este o activitate( Activity) n cursul/laboratorul urmtor. Pentru moment, putem considera c o activitate
este asociat ecranului aplicaiei.
n fereastra urmtoare, putem s customizm felul n care vom numi fiierele .xml asocitae activitii noastre:
Finish!
9
1. nainte de a testa aplicaia pe dispozitivul mobil(sau pe simulator), explorai proiectul(n special fi ierele din
directorul res)
2. Schimbai modul de afiare al proiectului(Project, Android, etc.) i observai diferitele tipuri de afiaj.
Pentru a lansa aplicaia pe dispozitivul Android, tastai Shift+ f10 (sau click pe butonul Run). Ar trebui s se afieze urmtoarea
fereastr:
10
Observai c Android Studio detecteaz automat dispozitivul mobil. Dac nu dispune i de unul, pute i alege varianta
simulatorului(Launch Emulator).
Rezultat:
11
For fun
android:textColor="@color/$numeCuloare"
Laborator 02 - Activiti
Activiti
In sistemul Android ferestrele se numesc activitati. Din punct de vedere al programarii, acestea sunt clase care extind clasa Activity. Spre
deosebire de alte sisteme in care un program contine mai multe ferestre afisate simultan, in Android, ecranul este mereu ocupat de o
singura fereastra. Mai mult, ferestrele sunt conectate prin simplul fapt ca o fereastra da nastere mai multor ferestre. Fereastra care apare
pe ecran in momentul in care aplicatia este pornita este considerata fereastra principala, din ea pornind toate celelalte. Pentru a crea o
activitate, vom crea o clasa ce extinde clasa Activity. La pornire, programul o va genera, iar noi putem interactiona cu fereastra prin
evenimente. Unele dintre cele mai importante evenimente sunt: onCreate si onPause.
public class MainActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onPause()
{
// TODO Auto-generated method stub
super.onPause();
}
13
Nu uitati sa apelati functia parintelui (in exemplul nostru Activity) in interiorul evenimentelor!
onCreate
Evenimentul este apelat in momentul in care se creaza activitate. Aici vom initializa compentele ferestrei. Pentru a face elementele de pe
fereastra vizibile, este necesar sa apelam functia setContentView. Exista cazuri in care la pornirea eplicatiei, aceasta trebuie sa revina la
o stare anterioara (ex: dupa o oprire fortata). Astfel, este recomandat ca in acest aveniment sa se verifice daca fereastra este una noua
sau nu, adica daca variabila de tip Bundle pasata ca parametru este nula sau nu.
if (savedInstanceState!=null)
{
//fereastra nu e noua si trebuie incarcate anumite date ramase
}
else
{
//fereastra e noua
}
onPause
Cand acest eveniment este apelat, fereastra se pregateste pentru oprire. De aceea este important sa salvam toate schimbarile de care
avem nevoie. Aici vom opri procesele care nu mai sunt necesare cand aplicatia nu ruleaza, cum ar fi elementele video sau audio.
onRestoreInstanceState() - este apelat doar dac exist o stare a activit ii care ar trebui s fie restaurat.
Obiectul de tip Bundle este o form de hash map, n care cheia este ntotdeauna de tip String, iar valorile au tipul android.os.Parcelable
(asemntor cu Serializable din Java, dei acesta nu este un mecanism de serializare n sine).
Starea unei activiti este meninut atta vreme ct ea este activ (deci inclusiv cnd au fost apelate metodele onPause() i onStop()),
aceasta putnd fi restaurat corespunztor. Necesitatea asigurrii consistenei activit ii de ctre programator apare n momentul n care
activitatea este terminat/distrus i apoi (re)pornit. O astfel de situa ie este frecvent n cazul n care se produce o schimbare de
configuraie (se modific orientarea dispozitivului de afiare - portrait vs. landscape, limba, disponibilitatea tastaturii), ntruct de fiecare
dat este necesar s se (re)ncarce resursele specifice pentru valorile respective.
inndu-se cont de faptul c activitatea poate fi terminat/distrus n orice moment dup ce nu se mai gse te n prim-plan / este
ascuns, asigurarea consistenei trebuie realizat de fiecare dat.
15
Salvarea Strii
Metoda onSaveInstanceState() este nainte de metoda onStop() i posibil nainte de metoda onPause(), de i acest lucru nu este garantat.
Ea primete ca parametru un obiect de tip Bundle n care vor fi plasate datele din cadrul activit ii care se doresc a fi salvate, acestea
putnd fi identificate prin intermediul unei chei (de tip String).
Apelul metodei onSaveInstanceState() nu este garantat s fie realizat de fiecare dat ntruct pot fi situa ii n care nu este necesar ca
starea activitii s fie restaurat (utilizatorul a terminat activitatea prin apsarea butonului Back).
n cazul n care se dorete salvarea explicit a coninutului unui obiect EditText, se poate proceda astfel:
@Override
Valoarea introdus de utilizator va fi salvat n obiectul de tip Bundle sub denumirea userNameEditText, acesta fiind men inut i prin
urmare utilizat ntre mai multe instane ale acestei activiti.
Apelarea metodei printe este necesar ntruct API-ul Android furnizeaz o implementare implicit pentru salvarea strii unei activit i,
parcurgnd ierarhia de componente grafice (obiecte de tip View) care au asociat un identificator (android:id), folosit drept cheie n
obiectul Bundle. Astfel, de regul, pentru elementele interfe ei grafice, nu este necesar s se men in starea, acest lucru fiind realizat n
mod automat, cu respectarea condiiei menionate. De aceea, n metoda onSaveInstanceState, va fi realizat salvarea unor informa ii
(obiecte ale clasei) pentru care procesul de salvare a strii nu este apelat. Totu i, asigurarea persisten ei datelor nu se va realiza
niciodat aici (ntruct nu se garanteaz apelarea sa), ci n metoda onPause().
n obiectul de tip Bundle, prin cheia android:viewHierarchyState se va re ine un alt obiect de tip Bundle care re ine starea tuturor
obiectelor de tip View din cadrul activitii (care sunt identificate prin intermediul unui cmp android:id). n cadrul acestuia, prin cheia
android:views se reine un obiect de tip SparseArray (un tip de dat specific Android care realizeaz mapri ntre ntregi i obiecte, mai
eficient dect un hashmap) care conine starea fiecrui obiect de tip View prin intermediul identificatorului su.
}
else {
Log.d("BundleTAG", "No view information was saved!");
}
Prin urmare, dac aplicaia este oprit i apoi pornit din nou, obiectele de tip View vor avea con inutul existent n prealabil. Pentru a
dezactiva aceast opiune, trebuie specificat n fiierul .xml care descrie interfa a grafic a activit ii, n elementul corespunztor
obiectului de tip View proprietatea android:saveEnabled=false.
Restaurarea Strii
ncrcarea coninutului din obiectul de tip Bundle (n vederea restaurrii strii) poate fi realizat:
1. n metoda onCreate()
2. @Override
4. super.onCreate(savedInstanceState);
5. setContentView(R.layout.activity_lifecycle_monitor);
8. usernameEditText.setText(savedInstanceState.getString("myEditText"));
9. }
10. prin intermediul metodei onRestoreInstanceState(), apelat n mod automat ntre metodele onStart() i onResume();
aceast abordare permite separarea dintre codul folosit la crearea ferestrei i codul utilizat la restaurarea strii unei
ferestre
17
11. @Override
13. super.onRestoreInstanceState(savedInstanceState);
16. usernameEditText.setText(savedInstanceState.getString(Constants.MY_EDIT_TEXT));
17. }
@Override
public boolean onCreateOptionsMenu(Menu menu) { ... }
@Override
public boolean onOptionsItemSelected(MenuItem item) { ... }
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello);
TextView helloText = (TextView) findViewById(R.id.textView);
Depanare
Depanarea este foarte importanta in procesul de realizare a aplicatiilor pentru dispozitive mobile. Acest proces este insa putin diferit fata
de depanarea programelor clasice pentru calculator, in primul rand pentru ca ruleaza pe alt dispozitiv. Tocmai din acest motiv, avem
nevoie de programe spcializate pentru a realiza depanarea. De asemenea, fiind vorba de dispozitive mobile, apar si anumite evenimente
specifice, cum ar fi apeluri telefonice, descarcarea bateriei etc., evenimente ce trebuie tratate intr-un fel sau altul. In laboratorul de astazi
vom prezenta programele de depanare existente si modul lor de functionare. De asemenea, ne vom ocupa putin de studierea
evenimentelor ferestrelor.
Logcat - debugging monitor pentru Android. Apeland Log.d(TAG, Text) putem afisa orice informatie ne putem dori. De
asemenea, Log poate avea mai multe prioritati, acestea determinand nivelul de importanta al mesajului si ajutand la
filtrarea mai usoara (In mesajele din logcat apar atat cele de la aplicatia in curs de rulare cat si alte mesaje de log ale
sistemului de operare si ale altor aplicatii care ruleaza in background).
19
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onPause()
{
// TODO Auto-generated method stub
21
super.onPause();
}
}
Nu uitati sa apelati functia parintelui (in exemplul nostru Activity) in interiorul evenimentelor!
onCreate
Evenimentul este apelat in momentul in care se creaza activitate. Aici vom initializa compentele ferestrei. Pentru a face
elementele de pe fereastra vizibile, este necesar sa apelam functia setContentView. Exista cazuri in care la pornirea
eplicatiei, aceasta trebuie sa revina la o stare anterioara (ex: dupa o oprire fortata). Astfel, este recomandat ca in acest
aveniment sa se verifice daca fereastra este una noua sau nu, adica daca variabila de tip Bundle pasata ca parametru este
nula sau nu.
if (savedInstanceState!=null)
{
//fereastra nu e noua si trebuie incarcate anumite date ramase
}
else
{
//fereastra e noua
}
onPause
Cand acest eveniment este apelat, fereastra se pregateste pentru oprire. De aceea este important sa salvam toate
schimbarile de care avem nevoie. Aici vom opri procesele care nu mai sunt necesare cand aplicatia nu ruleaza, cum ar fi
elementele video sau audio.
Gestiunea Starii unei Activitati
Unele dintre metodele care gestioneaz ciclul de via al unei activit i primesc ca parametru un obiect de tip Bundle,
utilizat pentru gestiunea strii n cazul n care activitatea este distrus din lips de memorie:
22
onCreate() - parametrul savedInstance poate s fie null, daca activitatea nu a mai fost rulat anterior, fie este o instan a
unui obiect de tip Bundle n care se gsete starea anterioar (aa cum a fost reinut de metoda onSaveInstanceState());
onSaveInstanceState() - este apelat cnd activitatea urmeaz s fie ascuns i exist posibilitatea ca procesul acesteia s
fie terminat din lips de memorie, pentru a salva starea activitii;
onRestoreInstanceState() - este apelat doar dac exist o stare a activit ii care ar trebui s fie restaurat.
Obiectul de tip Bundle este o form de hash map, n care cheia este ntotdeauna de tip String, iar valorile au tipul
android.os.Parcelable (asemntor cu Serializable din Java, dei acesta nu este un mecanism de serializare n sine).
Starea unei activiti este meninut atta vreme ct ea este activ (deci inclusiv cnd au fost apelate metodele onPause()
i onStop()), aceasta putnd fi restaurat corespunztor. Necesitatea asigurrii consisten ei activit ii de ctre
programator apare n momentul n care activitatea este terminat/distrus i apoi (re)pornit. O astfel de situa ie este
23
frecvent n cazul n care se produce o schimbare de configuraie (se modific orientarea dispozitivului de afi are - portrait
vs. landscape, limba, disponibilitatea tastaturii), ntruct de fiecare dat este necesar s se (re)ncarce resursele specifice
pentru valorile respective.
inndu-se cont de faptul c activitatea poate fi terminat/distrus n orice moment dup ce nu se mai gse te n prim-
plan / este ascuns, asigurarea consistenei trebuie realizat de fiecare dat.
Salvarea Strii
Metoda onSaveInstanceState() este nainte de metoda onStop() i posibil nainte de metoda onPause(), de i acest lucru nu
este garantat. Ea primete ca parametru un obiect de tip Bundle n care vor fi plasate datele din cadrul activit ii care se
doresc a fi salvate, acestea putnd fi identificate prin intermediul unei chei (de tip String).
Apelul metodei onSaveInstanceState() nu este garantat s fie realizat de fiecare dat ntruct pot fi situa ii n care nu este
necesar ca starea activitii s fie restaurat (utilizatorul a terminat activitatea prin apsarea butonului Back).
n cazul n care se dorete salvarea explicit a coninutului unui obiect EditText, se poate proceda astfel:
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
EditText myEditText = (EditText)findViewById(R.id.my_edit_text);
savedInstanceState.putString("myEditText", myEditText.getText());
}
Valoarea introdus de utilizator va fi salvat n obiectul de tip Bundle sub denumirea userNameEditText, acesta fiind
meninut i prin urmare utilizat ntre mai multe instane ale acestei activiti.
Apelarea metodei printe este necesar ntruct API-ul Android furnizeaz o implementare implicit pentru salvarea strii
unei activiti, parcurgnd ierarhia de componente grafice (obiecte de tip View) care au asociat un identificator
(android:id), folosit drept cheie n obiectul Bundle. Astfel, de regul, pentru elementele interfe ei grafice, nu este necesar
s se menin starea, acest lucru fiind realizat n mod automat, cu respectarea condi iei men ionate. De aceea, n metoda
onSaveInstanceState, va fi realizat salvarea unor informaii (obiecte ale clasei) pentru care procesul de salvare a strii nu
24
este apelat. Totui, asigurarea persistenei datelor nu se va realiza niciodat aici (ntruct nu se garanteaz apelarea sa),
ci n metoda onPause().
n obiectul de tip Bundle, prin cheia android:viewHierarchyState se va re ine un alt obiect de tip Bundle care re ine starea
tuturor obiectelor de tip View din cadrul activitii (care sunt identificate prin intermediul unui cmp android:id). n cadrul
acestuia, prin cheia android:views se reine un obiect de tip SparseArray (un tip de dat specific Android care realizeaz
mapri ntre ntregi i obiecte, mai eficient dect un hashmap) care con ine starea fiecrui obiect de tip View prin
intermediul identificatorului su.
Bundle viewHierarchy = savedInstanceState.getBundle("android:viewHierarchyState");
if (viewHierarchy != null) {
SparseArray<? extends Parcelable> views = viewHierarchy.getSparseParcelableArray("android:views");
for (int k=0; k < views.size(); k++) {
Log.d("BundleTAG", views.get(k) + "->" + views.valueAt(k));
}
}
else {
Log.d("BundleTAG", "No view information was saved!");
}
Prin urmare, dac aplicaia este oprit i apoi pornit din nou, obiectele de tip View vor avea con inutul existent n
prealabil. Pentru a dezactiva aceast opiune, trebuie specificat n fiierul .xml care descrie interfa a grafic a activit ii,
n elementul corespunztor obiectului de tip View proprietatea android:saveEnabled=false.
Dezactivarea se poate realiza i programatic, folosind metoda setSaveEnabled(boolean).
Restaurarea Strii
ncrcarea coninutului din obiectul de tip Bundle (n vederea restaurrii strii) poate fi realizat:
n metoda onCreate()
@Override
25
@Override
public boolean onCreateOptionsMenu(Menu menu) { ... }
@Override
public boolean onOptionsItemSelected(MenuItem item) { ... }
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello);
TextView helloText = (TextView) findViewById(R.id.textView);
27
filtrarea mai usoara (In mesajele din logcat apar atat cele de la aplicatia in curs de rulare cat si alte mesaje de log ale
sistemului de operare si ale altor aplicatii care ruleaza in background).
fizice. Cu ajutorul DDMS putem vizualiza parametrii dispozitivului si a programelor ce ruleaza pe acesta.
pentru a rula pana la linia cu pricina, mai intai setam un breakpoint (click in stanga liniei):
29
Realizati o activitate careia ii suprascrieti urmatoarele functii de eveniment. Afisati cate un mesaj de log in fiecare dintre
aceste functii. Pentru a putea citi mai usor mesajele de log afisate de catre programul vostru, o sa creati un filtru de log
dupa tag-ul eveniment.
Log.d("AWESOME_TAG", "??? method was invoked");
onCreate
onRestart
onStart
onResume
30
onPause
onStop
onDestroy
Sa se modifice mesajul din metoda onCreate(), astfel incat sa se indice daca activitatea a mai fost lansata in executie
anterior sau nu (daca exista o stare a activitatii care trebuie restaurata).
Observati ce se intampla cu evenimentele ferestrelor cand:
Primiti un apel telefonic (Hint: utilizati Emulator Control din DDMS)
Se apasa butonul Home
Se tine mult apasat butonul Home
Se apasa butonul de raspundere la convorbire
Se apasa butonul de inchidere al ecranului (este butonul de inchidere a convorbrii)
Adaugati pe fereastra un EditText si un CheckBox. Observati ce se intampla in cazurile de mai sus.
Dezactivati optiunea de salvare a starii, dupa care repetati pasii din exercitiul anterior.
Salvati starea EditBox-ului si a CheckBox-ului in functia de salvare a starii (hint: utilizati putString si putBoolean), fara a
modifica functia onCreate si/sau onRestoreInstanceState, observati ce se intampla in cazurile de mai sus.
BONUS (pentru 10000p) Creati un Empty activity. In MainActivity (in content_main.xml mai exact) creati un EditText in
care sa faceti input pentru nume, urmat de un Buton. Nu va chinuiti sa-l faceti sa arate bine sau ceva, importanta e
functionalitatea. Adaugati logica butonului astfel incat sa permita navigarea la activitatea noua, transmitand numele din
EditText si afisand textul Hello, + numele transmis. (exemplu de sursa puteti gasi aici: myapplication.zip)
31
de asemenea putem adauga si in watch expresii mai complicate (try it out)
Exercitii
1. Realizati o activitate careia ii suprascrieti urmatoarele functii de eveniment. Afisati cate un mesaj de log in fiecare dintre
aceste functii. Pentru a putea citi mai usor mesajele de log afisate de catre programul vostru, o sa creati un filtru de log dupa
tag-ul eveniment.
onCreate
32
onRestart
onStart
onResume
onPause
onStop
onDestroy
2. Sa se modifice mesajul din metoda onCreate(), astfel incat sa se indice daca activitatea a mai fost lansata in executie anterior
sau nu (daca exista o stare a activitatii care trebuie restaurata).
3. Observati ce se intampla cu evenimentele ferestrelor cand:
Primiti un apel telefonic (Hint: utilizati Emulator Control din DDMS)
Se apasa butonul Home
Se tine mult apasat butonul Home
Se apasa butonul de raspundere la convorbire
Se apasa butonul de inchidere al ecranului (este butonul de inchidere a convorbrii)
4. Adaugati pe fereastra un EditText si un CheckBox. Observati ce se intampla in cazurile de mai sus.
5. Dezactivati optiunea de salvare a starii, dupa care repetati pasii din exercitiul anterior.
6. Salvati starea EditBox-ului si a CheckBox-ului in functia de salvare a starii (hint: utilizati putString si putBoolean), fara a
modifica functia onCreate si/sau onRestoreInstanceState, observati ce se intampla in cazurile de mai sus.
7. BONUS (pentru 10000p) Creati un Empty activity. In MainActivity (in content_main.xml mai exact) creati un EditText in care
sa faceti input pentru nume, urmat de un Buton. Nu va chinuiti sa-l faceti sa arate bine sau ceva, importanta e
functionalitatea. Adaugati logica butonului astfel incat sa permita navigarea la activitatea noua, transmitand numele din
EditText si afisand textul Hello, + numele transmis. (exemplu de sursa puteti gasi aici: myapplication.zip)
33
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/hello_world"
tools:context=".MainActivity" />
</RelativeLayout>
Pentru fiecare element de pe fereastra exista un marcaj. Numele marcajului este acelasi cu numele clasei din partea de cod. Elementele
au anumite caracteristici: pozitionarea, dimensiunile, culoarea, textul de pe ele. Pentru setarea fiecarei proprietati se scrie un parametru
in acest mod:
android:proprietate="valoare"
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:text="Buton nou"
/>
34
Observam ca proprietatile layout_width si layout_height au valoarea wrap_content. Luand aceasta valoarea, butonul va avea cele mai
mici dimensiuni posibile. Putem inlocui wrap_content cu fill_parent si vom observa ca butonul va acoperi toata fereastra. Dimensiunile
pot, de asemenea, sa fie absolute, in pixeli. Culoarea butonului poate fi scrisa in format RGB sau aRGB (a reprezinta transparenta).
Layout
Pentru ca pe o fereastra putem avea un singur view, exista view-uri speciale care au rolul de a aranja continutul. Aceste view-uri se
numesc layout-uri si se comporta ca niste containere care aranjeaza elementele din interiorul lor dupa o anumita regula. Exista mai multe
tipuri de layout-uri:
LinearLayout
RelativeLayout
GridLayout
LinearLayout
LinearLayout este un container care aliniaza toate elementele pe care le contine fie vertical, fie orizontal. Selectarea orientarii se face prin
atributul android:orientation. Pentru a face ca cele doua butoane create anterior sa nu se suprapuna putem folosi un layout linear.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:text="Buton nou"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:text="Buton "
/>
</LinearLayout>
35
android:onClick="metodaExecutata"
Daca dorim sa executam o actiune la un alt eveniment si nu la apasarea butonului, vom selecta o alta variabila in loc de onClick.
android:id="@+id/idElement"
Dupa ce elementul poate fi identificat prin id, il putem lega de codul Java.
Button buton=findViewById(R.id.buton1);
Exercitii
1. Pentru urmatoarele exercitii vom avea nevoie de acest proiect. Descarcati-l si asigurati-va ca aveti toate dependintele
necesare pentru a-l rula.
2. In cadrul acestui laborator vom incerca sa dezvoltam o aplicatie care sa aiba cateva din feature-urile unui Dialer. Vom folosi
drept model urmatorul mockup. Pentru acest task, elaborati o structura de views layouturi / ( LinearLayout sau RelativeLayout
) care sa respecte modelul propus. Activitatea prezentata contine:
Un grup de View-uri care simuleaza o tastatura numerica [ 50% din inaltimea totala]
36
Un TextView care sa primeasca input din partea tastaturii [ 10% din inaltimea totala]
O lista de numere care au fost apelate. Lista poate fi scrollata [ 40% din inaltimea totala]
3. Implementati tastatura in fisierul xml dedicat MainActivity. Pentru moment, tastele nu vor prezenta nici o functionalitate.
Hint:
Pentru a implementa delimitatorul dintre coloane am folosit un astfel de view:
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#ff050505"/>
Laborator 04 - Fragmente
n laboratoarele precedente ai nvat despre activiti, cum funcioneaz acestea, i cum le putem conecta ntre ele. Astzi vom lucra cu
Fragmente. n Android, un Fragment este o clas ce reprezint o component independent ce se execut n contextul unei activit i.
De ce folosim fragmente? Fragmentele au fost introduse ncepnd cu Android 3.0 (API level 11), iar scopul lor este de a facilita crearea
de interefee ce se pot adapta diferitelor tipuri de ecrane.
37
Mai pe scurt, un fragment poate fi vzut ca o poriune de interfa ce poate fi refolosit n cadrul mai multor activit i sau pentru o
poziionare diferit a aceleiai interfee - dac folosim alte tipuri de ecrane (exemplu n figura de mai jos).
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.my_first_fragment, container, false);
}
}
n exemplul de mai sus am creat o clas de tip Fragment, n care putem observa c am suprascris metoda onCreateView(). A a cum am
spus mai sus, aceast metod este folosit pentru a crea componentele interfeei(din fiierul .xml) corespunztoare fragmentului.
Exerciii(simple)
40
n urmtorul exerciiu vom nva cum putem manipula fragmentele ntr-o activitate. Pentru aceasta vom lucra cu tab-uri. Scopul acestui
exerciiu este s putem naviga de la un tab la altul, utiliznd fragmente.
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/textFragment1"
android:textSize="40dp" />
</RelativeLayout>
fragment2.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="#FF4081"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/textFragment2"
android:textSize="40dp"
/>
</RelativeLayout>
E4. Adugai apoi componentele corespunzatoare fiierului asociat interfeei activitatii principale:
41
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android:id="@+id/main_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="?attr/colorPrimary"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
<android.support.design.widget.TabLayout
android:id="@+id/layout_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/toolbar"
android:background="?attr/colorPrimary"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="@id/layout_tab"/>
</android.support.design.widget.CoordinatorLayout>
tabLayout.addTab(tabLayout.newTab().setText(SnumeOptiune1))
tabLayout.addTab(tabLayout.newTab().setText(SnumeOptiune2))
Adugai cele dou opiuni, dup care setai poziionarea acestora n actionbar:
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
E7. Pentru a face posibil interschimbarea ntre cele dou fragmente, descrca i fi ierul FragmentAdapter.java i aduga i-l n proiect, n
acelai director cu MainActivity i cu cele dou fragmente. Acest fiier face posibil manipularea celor dou fragmente, i este destul de
simplu de folosit. Vom folosi acest adapter n activitatea principal, pentru a ne uura accesul la cele dou fragmente.
n acest exerciiu, adapter-ul pentru fragmente este deja instaniat n activitatea principal. Cel mai important este s n elege i modul de
funcionare al acestuia, cu siguran v va fi util pe mai departe.
Testai!