Android
Cristobal Raya Giner
Programació de Dispositius Mòbils (PDMO)
Carpetes
Un projecte Android està format pel fitxer AndroidManifest.xml que és un descriptor de l’aplicació, el codi Font en Java i uns fitxers de recursos. Cada element es troba en una carpeta específica.
Carpetes
• src: Carpeta que conté el codi font de l’aplicació. Els fitxers s’emmagatzemen en un espai de noms o paquet.
• gen: Carpeta que conté el codi generat de forma automàtica pel SDK. MAI s’han de modificar de forma manual aquests fitxers.
– BuildConfig.java: Defineix la constant DEBUG per que des de Java puguis saber si l’aplicació està en fase de desenvolupament.
– R.java: Defineix una classe que associa els recursos de l’aplicació amb identificadors. Així es podrà accedir als recursos des de Java.
Carpetes
• Android x.x: Codi JAR, l’API d’Android segons la versió seleccionada.
• Android Dependencies: Llibreries associades al projecte.
• assets: Carpeta que pot contenir fitxers o carpetes que podran ser utilitzats per l’aplicació (fitxers de dades, fonts,…). A diferencia de la carpeta res, mai es modifica el contingut dels fitxers d’aquesta carpeta ni se les associarà un identificador.
• bin: En aquesta carpeta es compila el codi i es genera el .apk, fitxer comprimit que conté l’aplicació final llista per instal·lar.
• libs: Codi JAR amb les llibreries que es vulguin utilitzar al projecte. S’ha afegit una llibreria android-support que afegeix noves funcionalitats que no apareixien en el nivell de API 4 i que van aparèixer en versions més noves del SDK.
Carpetes
• res: Aquesta carpeta conté els recursos utilitzats per l’aplicació. Les subcarpetes poden tenir un sufix si es vol que el recurs es carregui només en funció d’una. Per exemple –ldpi significa que només ha de utilitzar els recursos de la carpeta quan el dispositiu on s’instal·la l’aplicació té una densitat gràfica baixa (~120dpi); -v14
significa que el recurs només solo ha de carregar en un dispositiu amb nivell de API 14 (v4.0).
– drawable: En aquesta carpeta s'emmagatzemen els fitxers d’ imatges (JPG o PNG) i descriptors d’imatges en XML.
– layout: Conté fitxers XML amb les vistes (views) de l’aplicació. Les vistes ens permetran configurar les diferents pantalles que componen la interfície d’usuari de l’aplicació.
– menu: Fitxers XML amb els menús de cada activitat.
– values: Utilitza fitxers XML per a indicar valors del tipus string, color o estil. Així podrem canviar els valors sense necessitat de modificar el codi font. Per exemple, canviar d’idioma.
– anim, animator: Conté fitxers XML amb animacions.
– xml: Altres fitxers XML requerit per l’aplicació.
– raw: Fitxers addicionals que no és troben en format XML.
Carpetes
• AndroidManifest.xml: Aquest fitxer descriu l’aplicació Android. S’indiquen les activitats, intents, serveis i proveïdors de contingut de l’aplicació. Es declaren els permisos que requerirà l’aplicació. S’indica les versions d’Android per a executar-la, el paquet Java, etc.
• ic_launcher-web.png: Icona gran de l’aplicació per a utilitzar-se en pàgines Web. El nombre pot variar en el procés de creació del projecte. Ha de tenir una resolució de 512x512.
• proguard-project.txt: Fitxer de configuració de l’eina ProGuard, que
permet optimitzar i amagar el codi generat, i s’obté un .apk més petit per a dificultar d’enginyeria inversa.
• default.properties: Fitxer generat automàticament per el SDK. No s’ha de modificar. S’utilitza per a comprovar la versió del API i altres
característiques quan s’instal·la l’aplicació al terminal.
Activitats (Activities)
Una Activitat és un component de l’aplicació que proporciona una pantalla amb la que els usuaris poden interactuar per a fer alguna activitat com veure una pàgina web, fer una foto, trucar, etc... Cada activitat té una interfície d’usuari en una finestra que normalment omple la pantalla, o que pot ser menor que la pantalla i encabir-se en altres finestres, i un codi en java amb el programa associat a la activitat.
Una aplicació consisteix generalment en múltiples activitats unides entre sí.
Normalment hi ha una activitat principal (MainActivity) que es presenta a l’iniciar l’aplicació. Cada activitat es pot iniciar des de una altra activitat per tal de realitzar diferents accions.
Les activitats es creen com a subclasses de la classe Activity:
public class MainActivity extends Activity { } Aquest és l’arbre de parentesc de la classe Activity:
java.lang.Object
↳ android.content.Context
↳android.content.ContextWrapper
↳ android.view.ContextThemeWrapper
↳ android.app.Activity
Clase View
La classe View (vista) representa el bloc de construcció bàsic per als components de la interfície d’usuari de les activitats. És un objecte que ocupa un àrea rectangular a la pantalla, es pot dibuixar i és la classe base per al components interactius de la interfície d’usuari o “widgets” (botons, imatges, text,...). Per exemple la classe per a mostrar text s’anomena TextView, i és una subclasse de la classe View.
java.lang.Object
↳ android.view.View
↳ android.widget.TextView
Android facilita la creació de les pantalles associades a les activitats mitjançant Layouts en format XML. Una vegada creat fitxer amb el layout de l’activitat, aquest s’ha d’associa a la vista de l’activitat en el codi java. Per exemple per a associar un layout anomenat “activity_main” s’afegeix el codi:
setContentView(R.layout.activity_main);
LAYOUTS
Cristobal Raya Giner
Programació de Dispositius Mòbils (PRDM)
Layouts Bàsics
• LinearLayout: Disposa elements en una fila o columna
• TableLayout: Distribueix en forma de taula
• RelativeLayout: Disposa en relació a altre o al pare
• AbsoluteLayout: Posiciona de forma absoluta
• FrameLayout: Permet el canvi dinàmic el
elements.
Paràmetres del Layout
• Gravity, indica l’alineació de l’element en el contenidor:
Esquerra, dreta, centrat, a dalt, a baix, ….
• Width / Height: Ajusta l’ample / alt de l’element
– Match_parent (Fill_parent): L’element s’ajusta a la mida del contenidor pare
– Wrap_content: L’element s’ajusta al contingut
• Margins: Indica els marges de l’element respecte al
contenidor en forma numèrica (px, mm, in, pt, dp, dip, sp)
Botó Hora Actual – activity_main.xml
<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"
tools:context=".MainActivity" >
<Button
android:id="@+id/button"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/boton" />
</RelativeLayout>
Crearem un botó que al polsar actualitzarà l’hora.
Primer creem un Layout am un botó que ocupi tota la pantalla dins d’un RelativeLayout (o altre Layout):
Botó Hora Actual – MainActivity.java
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android .view.View;
import android.widget.Button;
import java.util.Date;
public class MainActivity extends Activity { Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(Button)findViewById(R.id.button);
actualitzaTemps();
btn.setOnClickListener(new View.OnClickListener() { public void onClick(View view) {
actualitzaTemps();
};
});
}
private void actualitzaTemps() {
btn.setText(new Date().toString());
}
Afegim el codi corresponent al fitxer .java principal de l’activitat:
http://developer.android.com/reference/java/util/Date.html
Format de l’hora
import java.text.SimpleDateFormat;
import java.util.Date;
private void actualitzaTemps() {
SimpleDateFormat sdf = new SimpleDateFormat("EEEE dd/MM/yyyy, HH:mm:ss");
String DataFormatada = sdf.format(new Date());
btn.setText(DataFormatada);
}
Per a modificar el format de la data i hora, podem canviar el format.
Amb el següent codi el formatem per a que es vegi com:
Dimecres 11/Setembre/2013, 17:14:00
http://developer.android.com/reference/java/text/SimpleDateFormat.html
Dos botons
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView Texte=(TextView)findViewById(R.id.vistatext);
Button btn1=(Button)findViewById(R.id.button1);
Button btn2=(Button)findViewById(R.id.button2);
btn1.setOnClickListener(new View.OnClickListener() { public void onClick(View view) {
Texte.setText("Has polsat el primer botó");
};
});
btn2.setOnClickListener(new View.OnClickListener() { public void onClick(View view) {
Texte.setText("Has polsat el segon botó");
};
});
}
Primer crea un Layout vertical amb un text i 2 botons:
Dos Botons Alternatiu 1
public class MainActivity extends Activity{
Button btn1,btn2;
TextView Texte;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Texte=(TextView)findViewById(R.id.vistatext);
btn1=(Button)findViewById(R.id.button1);
btn1.setOnClickListener(Escoltador);
btn2=(Button)findViewById(R.id.button2);
btn2.setOnClickListener(Escoltador);
}
View.OnClickListener Escoltador = new View.OnClickListener() { public void onClick(View v) {
if(((Button)v).getId()== btn1.getId() ) {
Texte.setText("Has polsat el primer botó");
}
else if(v.getId()==findViewById(R.id.button2).getId()) {
Texte.setText("Has polsat el segon botó");
} }
};
Amb el mateix layout, utilitzem només un mètode OnClickListener :
Dos Botons Alternatiu 2
public class MainActivity extends Activity implements OnClickListener { Button btn1,btn2;
TextView Texte;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Texte=(TextView)findViewById(R.id.vistatext);
View btn1=findViewById(R.id.button1);
btn1.setOnClickListener(this);
View btn2=findViewById(R.id.button2);
btn2.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if(v.getId()==findViewById(R.id.button1).getId()) {
Texte.setText("Has polsat el primer botó");
}
else if(v.getId()==findViewById(R.id.button2).getId()) {
Texte.setText("Has polsat el segon botó");
} }
Amb el mateix layout, ara s’implementa OnClickListener en la mateixa activitat:
Alternativa Botons
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity { TextView texte;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
texte=(TextView)findViewById(R.id.textView1);
}
public void boto_pulsat(View v){
texte.setText("Botó polsat");
} }
Hi ha una altre alternativa a la pulsació dels botons, cridant a un mètode per a un objecte View, mitjançant la propietat On Click del botó :
Demanar Text
http://developer.android.com/reference/android/widget/EditText.html
Crearem un layout amb almenys 3 camps de entrada de text del tipus EditText, un de tipus TextView, i un botó. L’activitat ens permetrà introduir per separat el nom i els dos cognoms, i al polsar el botó mostrarà el nom complert.
Demanar Text
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.view.View;
public class MainActivity extends Activity { Button btn;
TextView nomcomplert;
EditText nom, cognom1,cognom2;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nom=(EditText) findViewById(R.id.editnom);
cognom1=(EditText) findViewById(R.id.editcognom1);
cognom2=(EditText) findViewById(R.id.editcognom2);
nomcomplert=(TextView) findViewById(R.id.nomcomplert);
btn=(Button) findViewById(R.id.button1);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
String nomjunt=nom.getText().toString()+" "+cognom1.getText().toString()+“ “ +
cognom2.getText().toString();
nomcomplert.setText(nomjunt);
} });
}
Proveu canviar el paràmetre InputType de algún EditText, per exemple a textPassword
CheckBox
public class CheckBoxDemo extends Activity implements CompoundButton.OnCheckedChangeListener { CheckBox cb;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_check_box_demo);
cb=(CheckBox)findViewById(R.id.check);
cb.setOnCheckedChangeListener(this);
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { // TODO Auto-generated method stub
if (isChecked) {
cb.setText(“El checkbox està: Activat");
} else {
cb.setText(" El checkbox està: Desactivat ");
} } }
Creem un layout només amb un widget Checkbox.
RadioButton
import android.widget.RadioButton;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
public class MainActivity extends Activity { RadioButton rb;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rb=(RadioButton) findViewById(R.id.RadioButton1);
rb.setOnCheckedChangeListener(new OnCheckedChangeListener(){
public void onCheckedChanged(CompoundButton arg0, boolean arg1) { if (arg1) {
rb.setText("Está activado");
} else{
rb.setText("Está desactivado");
} }
});
}
Creem un layout només amb un widget RadioButton
Radio Group (1)
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
public class MainActivity extends Activity {
RadioButton radio0,radio1,radio2,radio3;
TextView textpolsat;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
radio0=(RadioButton)findViewById(R.id.radio0);
radio1=(RadioButton)findViewById(R.id.radio1);
radio2=(RadioButton)findViewById(R.id.radio2);
radio3=(RadioButton)findViewById(R.id.radio3);
textpolsat = (TextView)findViewById(R.id.textView);
radio1.setChecked(true);
textpolsat.setText("Inicialment polsat el segon");
final RadioGroup radioGroup = (RadioGroup) findViewById(R.id.radioGroup1);
………
Creem un LinearLayout vertical només amb un widget RadioGroup amb 4 RadioButtons, i un TextView.
Radio Group (2)
………
final RadioGroup radioGroup = (RadioGroup) findViewById(R.id.radioGroup1);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) { int id = radioGroup.getCheckedRadioButtonId();
switch (id){
case -1:
case R.id.radio0:
textpolsat.setText("Polsat primer");
break;
case R.id.radio1:
textpolsat.setText("Polsat segon");
break;
case R.id.radio2:
textpolsat.setText("Polsat tercer");
break;
case R.id.radio3:
textpolsat.setText("Polsat quart");
break;
} }
});
}
Radio Group (3)
public void onCheckedChanged(RadioGroup group, int checkedId) { int id = radioGroup.getCheckedRadioButtonId();
switch (id){
case -1:
case R.id.radio0:
textpolsat.setText("Canvi a orientació horitzontal");
radioGroup.setOrientation(LinearLayout.HORIZONTAL);
break;
case R.id.radio1:
textpolsat.setText("Canvi a orientació vertical");
radioGroup.setOrientation(LinearLayout.VERTICAL);
break;
case R.id.radio2:
textpolsat.setText("Canvi a gravetat centrat horitzontal");
radioGroup.setGravity(Gravity.CENTER_HORIZONTAL);
break;
case R.id.radio3:
textpolsat.setText("Canvi a gravetat dreta");
radioGroup.setGravity(Gravity.RIGHT);
break;
} }
Modifica les accions del switch per a modificar paràmetres de col·locació del RadioGroup
Llista de selecció amb ListActivity (1)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/seleccio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice" >
</ListView>
Important!!!
El id ha de ser list que ja està definit a android
Creem un Layout amb un TextView i un ListView
Per a que quedi marcada la selecció s’ha d’indicar singleChoice al
choicemode
Llista de selecció amb ListActivity (2)
import android.app.ListActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends ListActivity {
String[] llista={"SIOP","SIAC","DIAP","MCME","XACO","PRDM","SINS","ROVI","ECUS"};
TextView seleccio;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
seleccio=(TextView)findViewById(R.id.seleccio);
setListAdapter(new ArrayAdapter <String>
(this,android.R.layout.simple_list_item_single_choice,llista));
}
public void onListItemClick(ListView parent, View v, int position,long id){
seleccio.setText(llista[position]);
};
}
Ampliació de ListActivity
Codi Java:
Llista de selecció en Activity (1)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/seleccio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<ListView
android:id="@+id/llistat"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Ara el id pot ser lliure
Creem un Layout amb un TextView i un ListView
Llista de selecció en Activity (2)
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
String[] llista={"SIOP","SIAC","DIAP","MCME","XACO","PRDM","SINS","ROVI","ECUS"};
TextView seleccio;
ListView vistallistat;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vistallistat=(ListView)findViewById(R.id.llistat);
vistallistat.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
seleccio=(TextView)findViewById(R.id.seleccio);
vistallistat.setAdapter(new ArrayAdapter <String>
(this,android.R.layout.simple_list_item_single_choice,llista));
vistallistat.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) { seleccio.setText("Has seleccionat: "+llista[arg2]+" pos:"+arg2);
} });
} }
Codi Java:
Forma alternativa d’indicar
singleChoice al choicemode en el codi
Llista de selecció en recursos (1)
Com a alternativa a la definició de la llista, podem crear-la als recursos en lloc del codi. Aprofitant el programa anterior, primer obrim el fitxer strings.xml de la carpeta /res/values, i afegim un String Array i li posem el nom:
<string-array name="assignatures">
<item >SIOP</item>
<item >SIAC</item>
<item >DIAP</item>
<item >MCME</item>
<item >XACO</item>
<item name="PRD Mobils">PRDM</item>
<item >SINS</item>
<item >ROVI</item>
<item >ECUS</item>
</string-array>
Seleccionat el Array, afegim Items:
Afegits tots els elements, podem afegir alguns paràmetres com un nom de referència:
*
Llista de selecció en recursos (1)
En el codi, creem el array d’String i utilitzem getResources().getStringArray per a assignar les dades de l’array:
public class MainActivity extends Activity {
//String[] llista={"SIOP","SIAC","DIAP","MCME","XACO","PRDM","SINS","ROVI","ECUS"};
String[] llista;
TextView seleccio;
ListView vistallistat;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
llista=getResources().getStringArray(R.array.assignatures);
vistallistat=(ListView)findViewById(R.id.llistat);
vistallistat.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
seleccio=(TextView)findViewById(R.id.seleccio);
vistallistat.setAdapter(new ArrayAdapter <String>
(this,android.R.layout.simple_list_item_single_choice,llista));
vistallistat.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) { seleccio.setText("Has seleccionat: "+llista[arg2]+" pos:"+arg2);
} });
} }
S’assigna dins del mètode onCreate, ja que no es pot fer una crida a cap mètode (getResources()) en la definició de la classe, sinó dins d’un mètode.
Lista desplegable – Spinner (1)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Spinner
android:id="@+id/spinner1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Creem un Layout amb un TextView i un Spinner
Lista desplegable – Spinner (2)
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
public class MainActivity extends Activity {
String[] llista={"SIOP","SIAC","DIAP","MCME","XACO","PRDM","SINS","ROVI","ECUS"};
TextView seleccio;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
seleccio=(TextView)findViewById(R.id.textView1);
Spinner spin=(Spinner)findViewById(R.id.spinner1);
ArrayAdapter<String> adaptallista=new
ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,llista);
//adaptallista.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spin.setAdapter(adaptallista);
spin.setOnItemSelectedListener(new OnItemSelectedListener(){
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { seleccio.setText(llista[arg2]);
}
@Override
public void onNothingSelected(AdapterView<?> arg0) { seleccio.setText("Res seleccionat");
} });
}
Codi Java:
Després de provar el codi, afegeix aquesta línia i prova l’efecte
TableLayout
Un TableLayout, ens permet crear un Layout en forma de Taula, afegint files amb TableRow, i en cada fila afegint els widgets que volguem, creant les columnes de la taula. S’ha de tenir en
compte que si no s’indiquen mides, les files i columnes s’ajusten a la mida del widget més gran de la fila o columna.
TableLayout
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:stretchColumns="*" android:background="#000000">
<TableRow android:layout_margin="2dp" android:background="#ffffff">
<TextView android:text="Cel·la 1.1" />
<TextView android:text="Cel·la 1.2" />
<TextView android:text="Cel·la 1.3" />
</TableRow>
<TableRow android:layout_margin="2dp" >
<TextView android:background="#ffffff" android:layout_margin="2dp" android:text="Cel·la 2.1" />
<TextView android:background="#ffffff" android:layout_margin="2dp" android:text="Cel·la 2.2" />
<TextView android:background="#ffffff" android:layout_margin="2dp" android:text="Cel·la 2.3" />
</TableRow>
<TableRow >
<TextView
android:layout_margin="2dp"
android:layout_span="2"
android:background="#ffffff"
android:gravity="center_horizontal"
android:text="Cel·la 3.1" />
<TextView android:layout_margin="2dp" android:background="#ffffff" android:text="Cel·la 3.2" />
</TableRow>
</TableLayout>
Un TableLayout serveix per a crear taules amb files i columnes. Permet crear cel·les que ocupin més d’una columna o fila.
FrameLayout
public class MainActivity extends Activity { Button boto;
TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
boto = (Button) findViewById (R.id.button1);
text = (TextView) findViewById (R.id.textView1);
boto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) { text.setVisibility(View.VISIBLE);
boto.setVisibility(View.INVISIBLE);
} });
text.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { text.setVisibility(View.INVISIBLE);
boto.setVisibility(View.VISIBLE);
} });
} }
Un FrameLayout apila tots els controls o widgets al vèrtex superior esquerra del contenidor FrameLayout, un a sobre de l’altre. En l’exemple posem un botó i un text en un FrameLayout, i fem que al polsar el botó aparegui el text i a l’inrevés.
Imatges
Per a poder utilitzar imatges, aquestes han d’estar a la carpeta /res/drawable del projecte d’Android. Si no existís la carpeta, es crea la carpeta polsant el botó dret a la carpeta /res, i seleccionant New Folder.
Per a afegir la imatge, polsem el botó dret sobre la carpeta /drawable, i seleccionem import General File System
Les imatges han d’estar en format PNG, JPG o GIF, i només poden contenir caràcters de a-z, 0-9 i _.
No podem tenir dos imatges amb el mateix nom, encara que siguin diferent format.
Això es degut a que una vegada estan les imatges a la carpeta del projecte, s’assigna automàticament el recurs @drawable/nom_imatge per a accedir a elles, i no es té en compte l’extensió del fitxer.
ImageView
Creem una aplicació amb dos botons que al polsar canviï la imatge de un ImageView.
Inseriu dos imatges a la carpeta drawable, i afegiu al layout una vista ImageView. Al afegir el ImageView, us apareixerà una pantalla per a que seleccioneu la imatge a mostrar.
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:src="@drawable/llunatics" />
La imatge seleccionada els mostra:
ImageView imatge=(ImageView)findViewById(R.id.imageView1);
imatge.setImageResource(R.drawable.llunatics);
Per a modificar la imatge en el codi, utilitzem el mètode .setImageResource:
ImageView
Creem un layout amb un TextView, els dos Buttons, i un ImageView. El podem posar en un TableLayout per a facilitar la organització.
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends Activity { TextView nom;
ImageView imatge;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imatge=(ImageView)findViewById(R.id.imageView1);
nom=(TextView)findViewById(R.id.textView1);
Button btn1=(Button)findViewById(R.id.button1);
Button btn2=(Button)findViewById(R.id.button2);
btn1.setOnClickListener(new View.OnClickListener() { public void onClick(View view) {
imatge.setImageResource(R.drawable.llunatics);
nom.setText("Imatge Llunatics");
};
});
btn2.setOnClickListener(new View.OnClickListener() { public void onClick(View view) {
imatge.setImageResource(R.drawable.logos);
nom.setText("Imatge Logos");
};
});
}
El codi:
ImageView
Pestanyes: TabHost
El TabHost és l’element principal del layout i porta l’identificador @android:id/tabhost. El TabHost és un contenidor de dos elements principals i configurables: el TabWidget que correspon a la part on apareixeran les pestanyes i porta l’identificador @android:id/tabs, i un segon element de tipus FrameLayout amb l’identificador @android:id/tabcontent, que és on es trobarà el contingut de cadascuna de les pestanyes. Per a facilitar l’organització, el TabWidget i el FrameLayout poden estar continguts en un LinearLayout.
TabHost Id:@android:id/tabhost LinearLayout
TabWidget Id:@android:id/tabs tab1 tab2 tab3 Tab1tab4
FrameLayout Id:@android:id/tabcontent
LinearLayout Id:@android:id/tab1
LinearLayout Id:@android:id/tab2
LinearLayout Id:@android:id/tab3
LinearLayout Id:@android:id/tab4
Pestanyes: TabHost
Crearem un primer exemple simple, amb quatre pestanyes on el contingut de la pestanya serà un text que es troba al propi Layout.
Configurem el següent Layout per a l’activitat principal:
Pestanyes: TabHost
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabHost tabs=(TabHost)findViewById(android.R.id.tabhost);
tabs.setup();
TabHost.TabSpec spec;
spec=tabs.newTabSpec("eltab1");
spec.setContent(R.id.tab1);
spec.setIndicator("Primer");
tabs.addTab(spec);
spec=tabs.newTabSpec("eltab2");
spec.setContent(R.id.tab2);
spec.setIndicator("Segon");
tabs.addTab(spec);
spec=tabs.newTabSpec("eltab3");
spec.setContent(R.id.tab3);
spec.setIndicator("Tercer");
tabs.addTab(spec);
spec=tabs.newTabSpec("eltab4");
spec.setContent(R.id.tab4);
spec.setIndicator("Quart");
tabs.addTab(spec);
tabs.setCurrentTab(0);
……… segueix pàgina següent ……….
En el codi s’enllaça un objete TabHost amb el Layout, i es configuren les diferents pestanyes amb el mètode setup() i un objecte TabHost.TabSpec. En aquest cas indiquem el text a mostrar:
Pestanyes: TabHost
... ve de pàgina anterior ....
spec=tabs.newTabSpec("eltab4");
spec.setContent(R.id.tab4);
spec.setIndicator("Quart");
tabs.addTab(spec);
tabs.setCurrentTab(0);
tabs.setOnTabChangedListener(new OnTabChangeListener() {
@Override
public void onTabChanged(String tabId) { missatge(tabId);
} });
}
public void missatge(String tabId){
Toast toastsimple= Toast.makeText(this, "S'ha polsat: "+tabId, Toast.LENGTH_SHORT);
toastsimple.show();
};
}
Podem aprofitar els events del TabHost com OnTabChanged d’un TabHost, com per a exemple mostrar un missatge:
Pestanyes: TabHost amb icones
TabHost tabs=(TabHost)findViewById(android.R.id.tabhost);
tabs.setup();
TabHost.TabSpec spec;
spec=tabs.newTabSpec("eltab1");
spec.setContent(R.id.tab1);
// spec.setIndicator("EPSEVG",getResources().getDrawable(R.drawable.logo_epsevg));
spec.setIndicator("",getResources().getDrawable(R.drawable.logo_epsevg));
tabs.addTab(spec);
spec=tabs.newTabSpec("eltab2");
spec.setContent(R.id.tab2);
// spec.setIndicator("UPC",getResources().getDrawable(R.drawable.logo_upc));
spec.setIndicator("",getResources().getDrawable(R.drawable.logo_upc));
tabs.addTab(spec);
spec=tabs.newTabSpec("eltab3");
spec.setContent(R.id.tab3);
// spec.setIndicator("GREC",getResources().getDrawable(R.drawable.logogrec));
spec.setIndicator("",getResources().getDrawable(R.drawable.logogrec));
tabs.addTab(spec);
spec=tabs.newTabSpec("eltab4");
spec.setContent(R.id.tab4);
//
spec.setIndicator("VNG",getResources().getDrawable(R.drawable.logo_ajvilanova));
spec.setIndicator("",getResources().getDrawable(R.drawable.logo_ajvilanova));
tabs.addTab(spec);
tabs.setCurrentTab(0);
Si en lloc de text volem que apareguin imatges, aquestes han d’estar a la carpeta /res/drawable, i es referencien amb setIndicator. Es pot indicar el text i la imatge, però segons la versió de la API, només apareix el text i per a que aparegui la imatge s’ha de deixar en blanc el text. Modifica el codi anterior per aquest:
Pestanyes: TabHost amb Tabactivity
Si volem mostrar una activitat externa al polsar la pestanya, s’utilitza una subclasse de Activity que es diu TabActivity. Actualment està en desús a favor de ActionBar des de la API 11, però segueix essent una forma molt senzilla de cridar activitats.
Creem un TabHost amb dos Tabs:
També creem dues activitats més amb el seu Layout corresponent:
Ens assegurem que s’han afegit les noves activitats en l’apartat Application del fitxer AndroidManifest.xml:
Pestanyes: TabHost amb Tabactivity
public class MainActivity extends TabActivity {
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabHost tabs=(TabHost)findViewById(android.R.id.tabhost);
tabs.setup();
TabHost.TabSpec spec;
spec=tabs.newTabSpec("eltab1");
spec.setContent(new Intent(MainActivity.this,Activitat_tabhost.class));
spec.setIndicator("Primer");
tabs.addTab(spec);
Intent i = new Intent();
i.setClass(MainActivity.this,Segona_activitat.class);
spec=tabs.newTabSpec("eltab2");
spec.setContent(i);
spec.setIndicator("Segon");
tabs.addTab(spec);
tabs.setCurrentTab(0);
} }
En el codi de l’activitat principal, canviem Activity per TabActivity. Per a cridar les activitats corresponents a les pestanyes, es creen els Intents corresponents, i s’associen amb el mètode TabHost.TabSpec.setContent()
• http://www.androidcurso.com/
• http://www.sgoliver.net
• http://yoandroido.blogspot.com.es/
• http://www.javaya.com.ar/androidya/index.p hp?inicio=
• http://elbauldelprogramador.com/curso-
programacion-android/
INTENTS
Crida a altres activitats o aplicacions
Cristobal Raya Giner
Programació de Dispositius Mòbils (PRDM)
Elements principals
Hi ha varis elements importants a tenir en compte al desenvolupar aplicacions en Android
• Activity (Activitats): Són els blocs bàsics d’una aplicació, que solen representar les pantalles d’interfície d’usuari (UI)
• Intent (Intents): Representa la intenció de cridar a una altra aplicació, de la qual es pot rebre una resposta. Per exemple, visualitzar una pàgina web amb el navegador.
• Service (Serveis): És un procés que s’executa en segon pla, sense necessitat de cap interacció amb l’usuari. Ex: servidor Web
• Content Providers (Proveïdors de Contingut): Proveeixen l’accés per a la compartició de dades per les aplicacions. Ex: Agenda de Contactes
• Broadcast Receiver: Detecta i reacciona a missatges o events globals del sistema. Ex. Bateria baixa
Crida a nova activitat (1)
Creem un nou projecte amb una activitat, i afegim una nova activitat. En la carpeta Layout premem el botó dret i seleccionem NewÆ Android XML File.
Afegim un LinearLayout al nou layout, i acceptem les següents finestres fins finalitzar la creació del Layout.
Apareixen els dos Layouts a la carpeta, i ara afegim un botó en cada Layout.
Crida a nova activitat (2)
Crida a nova activitat (3)
Per a crear el codi de la segona activitat, premem el botó dret en la carpeta del package del projecte en /src, i creem una nova classe:
Posem el nom, i li indiquem que hereta la classe Activity, del paquet d’android a l’apartat Superclass:
Android.app.Activity
També podem crear nova Activitat i ens crea també el Layout i modifica el fitxer AndroidManifest.xml, i realitza els passos de les següents diapositives automàticament.
Crida a nova activitat (4)
Falta sobreescriure el mètode onCreate al codi. Podem escriure-ho directament, o bé ajudar-nos amb l’apartat de Override/Implement Methods… del menu Source.
Crida a nova activitat (5)
Per a acabar d’enllaçar el codi amb el corresponent layout, afegim el mètode setContentView:
package edu.example.crida_novaactivitat;
import android.app.Activity;
import android.os.Bundle;
public class Segona_activitat extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.segona_activitat);
} }
Crida a nova activitat (6)
Només falta registrar la nova activitat al fitxer AndroidManifest.xml afegint-la a l’apartat Application
Per acabar, afegim el nom del fitxer .java amb el codi de l’activitat
Crida a nova activitat (7)
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button boto1=(Button)findViewById(R.id.button);
boto1.setOnClickListener(new View.OnClickListener() { public void onClick(View view) {
obrir(view);
};
});
}
public void obrir(View view) {
Intent i = new Intent(this, Segona_activitat.class );
startActivity(i);
} }
Creem el codi de l’activitat principal, creant un nou Intent
Podem obviar el paràmetre View de obrir: obrir()
Crida a nova activitat (7bis)
public void obrir() {
Intent i = new Intent();
i.setClass(MainActivity.this, Segona_activitat.class);
startActivity(i);
}
Com a alternativa creem un Intent, i després li indiquem per separat la classe origen, indicant que correspon a la que estem (***.this) i la clase destí (***.class):
Crida a nova activitat (8)
public class Segona_activitat extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.segona_activitat);
Button boto2=(Button)findViewById(R.id.button);
boto2.setOnClickListener(new View.OnClickListener() { public void onClick(View view) {
tancar(view);
};
});
}
public void tancar(View view) { finish();
} }
Creem el codi de la segona activitat, fent que es tanqui al polsar el botó
Podem obviar el paràmetre View de tancar: tancar()
Crida a activitat amb paràmetres (1)
Crearem dos activitats entre les que es passaran paràmetres. En el primer layout afegim un botó i un EditText on escribirem un text que passarem a la segona activitat, i en el segon layout afegim un botó i un TextView on es mostrarà el text enviat des de la primera activitatp
<TextView
android:id="@+id/textprimer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Primera activitat" />
<EditText
android:id="@+id/entradatext1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" >
<requestFocus />
</EditText>
<Button
android:id="@+id/boto1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Prem per la segona" />
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Segona Activitat" />
<Button
android:id="@+id/boto2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Torna a primera" />
<TextView
android:id="@+id/dadesrebudes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dades Rebudes"
android:textAppearance="?android:attr/textAppearance Large" />
Crida a activitat amb paràmetres (2)
En el codi de la primera activitat afegim el mètode putExtra() al Intent abans de cridar a la segona activitat per a afegir el text a compartir.
public class MainActivity extends Activity { EditText textdades;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button boto1=(Button)findViewById(R.id.boto1);
textdades=(EditText) findViewById(R.id.entradatext1);
boto1.setOnClickListener(new View.OnClickListener() { public void onClick(View view) {
obrir();
};
});
}
public void obrir() {
Intent i = new Intent();
i.setClass(MainActivity.this, Segona_activitat.class );
i.putExtra("escrit", textdades.getText().toString());
startActivity(i);
} }
Crida a activitat amb paràmetres (3)
En el codi de la segona activitat afegim el mètode getIntent().getExtras() per a llegir el text enviat per la primera activitat
public class Segona_activitat extends Activity { TextView rebut;
String dades;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.segona_activitat);
Button boto2=(Button)findViewById(R.id.boto2);
rebut=(TextView)findViewById(R.id.dadesrebudes);
Bundle bundle = getIntent().getExtras();
dades=bundle.getString("escrit");
rebut.setText(dades);
boto2.setOnClickListener(new View.OnClickListener() { public void onClick(View view) {
tancar();
};
});
}
public void tancar() { finish();
} }