https://manuais.iessanclemente.net/api.php?action=feedcontributions&user=Angelfg&feedformat=atomManuais Informática - IES San Clemente. - Contribuciones del usuario [es]2024-03-19T11:25:54ZContribuciones del usuarioMediaWiki 1.36.2https://manuais.iessanclemente.net/index.php?title=Usuario:Angelfg&diff=57688Usuario:Angelfg2015-12-08T20:24:50Z<p>Angelfg: </p>
<hr />
<div>[[Imagen:Angel_Fernandez_Gonzalez.png|200px]]<br />
<br />
<br />
Ángel Daniel Fernández González<br />
<br />
Correo: mailto:angelfg@cifprodolfoucha.es<br />
<br />
Profesor de Informática do<br />
<br />
[http://www.cifprodolfoucha.es/ CIFP Rodolfo Ucha Piñeiro] <br />
+34 981 321565<br />
<br />
Ferrol - A Coruña<br />
<br />
'''Máis información:'''<br />
<br />
* http://www.about.me/angeldfg<br />
* Blog: http://angelfernandezgonzalez.blogspot.com.es/<br />
* Twitter: https://twitter.com/angeldfg<br />
* Facebook: https://www.facebook.com/angel.fernandez.9085790<br />
* Pinterest: https://www.pinterest.com/angel_fer_gon/</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Archivo:Angel_Fernandez_Gonzalez.png&diff=57588Archivo:Angel Fernandez Gonzalez.png2015-11-18T18:45:42Z<p>Angelfg: Angelfg subió una nueva versión de «Archivo:Angel Fernandez Gonzalez.png»</p>
<hr />
<div></div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Curso_Platega:_Desenvolvemento_de_aplicaci%C3%B3ns_para_dispositivos_m%C3%B3biles_con_Android._Avanzado&diff=57566Curso Platega: Desenvolvemento de aplicacións para dispositivos móbiles con Android. Avanzado2015-11-15T16:35:33Z<p>Angelfg: /* Licenza do curso */</p>
<hr />
<div>=='''Licenza do curso'''==<br />
<br><br />
<div style="margin:0; background:#E6ECFF; font-size:100%; border:1px solid #cccccc; text-align:left; padding:0.2em 0.4em; -moz-border-radius:6px">http://i.creativecommons.org/l/by-nc-sa/3.0/es/88x31.png<br />
<br>Este manual de '''Programación avanzada de aplicacións para dispositivos móbiles con Android''' é creado e editado por [[Usuario:angelfg| Ángel D. Fernandez González]] e [[Usuario:Carrion| Carlos Carrión Álvarez]] baixo a licenza [http://creativecommons.org/licenses/by-nc-sa/3.0/es/ Creative Commons 3.0:] <br />
<br />
:*Copiar, distribuír e comunicar publicamente a obra, sempre mencionando ós autores.<br />
:*Uso non comercial. <br />
:*Compartir as modificacións baixo a mesma licenza. <br />
<br />
Para calquera outro tipo de uso non contemplado na licenza anterior consulte ó autor: [[Usuario:angelfg| Ángel D. Fernández González]].<br />
<br />
</div><br />
<br />
Estes apuntes se fixeron para o curso de formación do profesorado: [https://www.edu.xunta.es/fprofe/procesaConsultaPublica.do?DIALOG-EVENT-ver=ver&cod_actividade=61014 Programación avanzada de aplicacións para dispositivos móbiles con Android]<br />
<br />
<br />
<br><br />
<br />
=='''UNIDADE 0: Coñecementos de partida, observacións sobre o material, Máquina Virtual de Android en VirtualBox e práctica a entregar'''==<br />
<br />
----<br />
<br />
*[[PDM_Avanzado Android: Coñecementos previos]]<br />
*[[Material vivo]]<br />
*[[PDM_Avanzado_Observacións | Observacións á edición 2014-2015 do curso]]<br />
*[[PDM_Avanzado_Xeración de apuntes off-line | Xeración de apuntes off-line]]<br />
*[[PDM_Avanzado_Preparación Máquina Virtual | Preparación da Máquina Virtual ou AVD]]<br />
*[[PDM_Avanzado_Práctica a entregar | Práctica a entregar]]<br />
<br />
<br><br />
<br />
=='''UNIDADE 1: Datos Persistentes'''==<br />
*[[PDM_Avanzado Obxectivos e escenarios da UNIDADE 1 | Obxectivos e escenarios da UNIDADE 1]]<br />
*[[PDM_Avanzado Datos Persistentes Preferencias | Preferencias]]<br />
*[[PDM_Avanzado Datos Persistentes Arquivos | Ficheiros]]<br />
*[[PDM_Avanzado Datos Bases de datos | Bases de datos]]<br />
<br />
=='''UNIDADE 2: Multimedia'''==<br />
*[[PDM_Avanzado Obxectivos e escenarios da UNIDADE 2 | Obxectivos e escenarios da UNIDADE 2]]<br />
*[[PDM_Avanzado Reprodución de Audio | Reprodución de Audio]]<br />
*[[PDM_Avanzado Captura de Audio | Captura de Audio]]<br />
*[[PDM_Avanzado Captura de Vídeo / Imaxes | Captura e Reprodución de Vídeo / Imaxes]]<br />
<br />
=='''UNIDADE 3: Threads e AsyncTask'''==<br />
<br />
*[[PDM_Avanzado Obxectivos e escenarios da UNIDADE 3 | Obxectivos e escenarios da UNIDADE 3]]<br />
*[[PDM_Avanzado Threads | Threads]]<br />
*[[PDM_Avanzado AsyncTask | AsyncTask]]<br />
<br />
<br />
=='''UNIDADE 4: Arquivos XML: análise e procesamento dun arquivo xml.'''==<br />
*[[PDM_Avanzado Obxectivos e escenarios da UNIDADE 4 | Obxectivos e escenarios da UNIDADE 4]]<br />
*[[PDM_Avanzado Procesar arquivos XML | Procesar arquivos XML]]<br />
<br />
<br />
=='''UNIDADE 5: Comunicación: Descarga de arquivos.'''==<br />
*[[PDM_Avanzado Obxectivos e escenarios da UNIDADE 5 | Obxectivos e escenarios da UNIDADE 5]]<br />
*[[PDM_Avanzado Comunicacion Descarga de arquivos | Descarga de arquivos]]<br />
<br />
<br />
=='''UNIDADE 6: Xeolocalización e aplicación sobre Google Maps.'''==<br />
*[[PDM_Avanzado Obxectivos e escenarios da UNIDADE 6 | Obxectivos e escenarios da UNIDADE 6]]<br />
*[[PDM_Avanzado Xeolocalización | Xeolocalización]]<br />
*[[PDM_Avanzado GoogleMaps | GoogleMaps]]<br />
<br />
=='''UNIDADE 7: Empaquetado e distribución. Xeración de arquivos APK.'''==<br />
*[[PDM_Avanzado Obxectivos e escenarios da UNIDADE 7 | Obxectivos e escenarios da UNIDADE 7]]<br />
*[[PDM_Avanzado Empaquetado e distribución | Empaquetado e distribución]]<br />
<br />
<br />
=='''UNIDADE 8: Actualizacións en base ás versións da API Android.'''==<br />
<br />
*[[PDM_Avanzado Obxectivos e escenarios da UNIDADE 8 | Obxectivos e escenarios da UNIDADE 8]]<br />
*[[PDM_Avanzado Permisos AndroidManifiest.xml | Permisos AndroidManifiest.xml]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Spinner_a_trav%C3%A9s_de_adaptador&diff=57551Spinner a través de adaptador2015-11-09T14:21:18Z<p>Angelfg: /* Usando un array estático en Java */</p>
<hr />
<div>==Introdución==<br />
*Xa vimos na unidade 2 como crear un [[Spinner]], pero o enlace dos datos co Spinner facíase a través dun atributo XML na definición do Spinner no Layout: '''android:entries'''.<br />
*Agora imos facer o mesmo pero usando un adaptador.<br />
*Colleremos os datos dende un array no código e logo dende un recurso XML.<br />
<br />
==Caso práctico==<br />
*Crear o proxecto: '''U4_02_SpinnerAdapter'''.<br />
<br />
<gallery caption="Aplicación Diálogos" widths="350" heights="300px" perrow="2"><br />
Image:Android_2014_U4_02_SpinnerAdapter_01.jpg<br />
Image:Android_2014_U4_02_SpinnerAdapter_02.jpg<br />
</gallery><br />
<br />
*Cada ítem do Spinner é tratado como unha '''View''', neste caso de tipo '''TextView'''.<br />
<br />
===O XML do layout===<br />
*Observar como a vista Spinner non ten a entrada '''android:entries'''.<br />
<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Selecciona unha froita" /><br />
<br />
<Spinner<br />
android:id="@+id/spin_froitas"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
==Usando un array estático en Java==<br />
*Ao final do código explícase como se enlaza a fonte de datos co adaptador e este co spinner.<br />
*Observar as liñas marcadas.<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="23,26,29,32,35,38,39" ><br />
package com.example.u4_02_spinneradapter;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.TextView;<br />
import android.widget.AdapterView;<br />
import android.widget.AdapterView.OnItemSelectedListener;<br />
import android.widget.ArrayAdapter;<br />
import android.widget.Spinner;<br />
import android.widget.Toast;<br />
<br />
public class U4_02_SpinnerAdapter extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u4_02__spinner_adapter);<br />
<br />
Spinner spinFroitas = (Spinner) findViewById(R.id.spin_froitas);<br />
<br />
// Fonte de datos<br />
String[] froitas = new String[] { "Pera", "Mazá", "Plátano" };<br />
<br />
// Enlace do adaptador cos datos<br />
ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, froitas);<br />
<br />
// Opcional: layout usuado para representar os datos no Spinner<br />
adaptador.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);<br />
<br />
// Enlace do adaptador co Spinner do Layout.<br />
spinFroitas.setAdapter(adaptador);<br />
<br />
// Escoitador<br />
spinFroitas.setOnItemSelectedListener(new OnItemSelectedListener() {<br />
@Override<br />
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {<br />
//Toast.makeText(getBaseContext(), "Seleccionaches: " + parent.getItemAtPosition(pos), Toast.LENGTH_LONG).show();<br />
Toast.makeText(getBaseContext(), "Seleccionaches: " + ((TextView) view).getText(), Toast.LENGTH_LONG).show();<br />
<br />
}<br />
<br />
@Override<br />
public void onNothingSelected(AdapterView<?> arg0) {<br />
// TODO Auto-generated method stub<br />
}<br />
}); // Fin da clase anónima<br />
<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u4_02__spinner_adapter, menu);<br />
return true;<br />
}<br />
<br />
}<br />
<br />
</syntaxhighlight><br />
*'''Liña 23''': Definimos a fonte de datos, neste caso un array estático.<br />
*'''Liña 26''': Definimos o adaptador de tipo ArrayAdapter. Pasámoslle como parámetros:<br />
**Contexto,<br />
**O int, identificador de recurso de layout que se vai usar para representar a Vista de Selección, neste caso usamos un predefinido. O usuario pode experimentar con outros tipos (android.R.layout.... CTRL+ESPAZO) e ver que outras formas hai de presentar os datos nun Spinner.<br />
**Un array de obxectos, neste caso de Strings.<br />
**Para ver outros construtores e métodos: http://developer.android.com/reference/android/widget/ArrayAdapter.html<br />
*'''Liña 29''': ''setDropDownViewResource(int)'', indica como se vai representar cada un dos ítems do Spinner. Usamos un layout xa predefinido. O usuario pode experimentar usando outros distintos, predefinidos ou propios. <br />
*'''Liña 32''': establece o adaptador que subministra os datos ao Spinner.<br />
*'''Liña 35''': O escoitador é o mesmo que cando non se usaba un adaptador.<br />
*'''Liñas 38,39''': As dúas liñas fan o mesmo, pero no segundo caso observar como recollemos a vista (view) que nos devolve o evento ao premer nun ítem do Spinner. Esa view é do tipo TextView e por iso facemos un cast e logo xa lle podemos aplicar métodos da clase TextView, como getText().<br />
<br />
==Usando un array de recursos XML==<br />
*Usamos o mesmo Layout do exemplo anterior e case o mesmo código, só comentamos a liña de asociación do adaptador coa fonte de datos e engadimos outra sentencia que asocie o adaptador co ficheiro XML.<br />
<br />
===Ficheiro XML para o array===<br />
*En '''res/values/array_froitas.xml'''<br />
*Observar o nome do recurso array: ''froitas''<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="4" ><br />
<?xml version="1.0" encoding="utf-8"?><br />
<resources><br />
<br />
<string-array name="froitas"><br />
<item>Pera</item><br />
<item>Mazá</item><br />
<item>Plátano</item><br />
</string-array><br />
<br />
</resources><br />
</syntaxhighlight><br />
<br />
<br />
===O código Java do programa===<br />
<syntaxhighlight lang="java" line enclose="div" highlight="26,28" ><br />
package com.example.u4_02_spinneradapter;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.AdapterView;<br />
import android.widget.AdapterView.OnItemSelectedListener;<br />
import android.widget.ArrayAdapter;<br />
import android.widget.Spinner;<br />
import android.widget.Toast;<br />
<br />
public class U4_02_SpinnerAdapter extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u4_02__spinner_adapter);<br />
<br />
Spinner spinFroitas = (Spinner) findViewById(R.id.spin_froitas);<br />
<br />
// Fonte de datos. Neste caso obtense dun recurso xml.<br />
//String[] froitas = new String[] { "Pera", "Mazá", "Plátano" };<br />
<br />
// Enlace do adaptador cos datos<br />
// ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, froitas);<br />
<br />
ArrayAdapter<CharSequence> adaptador = ArrayAdapter.createFromResource(this, R.array.froitas, android.R.layout.simple_spinner_item);<br />
<br />
// Opcional: layout usuado para representar os datos no Spinner<br />
adaptador.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);<br />
<br />
// Enlace do adaptador co Spinner do Layout.<br />
spinFroitas.setAdapter(adaptador);<br />
<br />
// Escoitador<br />
spinFroitas.setOnItemSelectedListener(new OnItemSelectedListener() {<br />
@Override<br />
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {<br />
//Toast.makeText(getBaseContext(), "Seleccionaches: " + parent.getItemAtPosition(pos), Toast.LENGTH_LONG).show();<br />
Toast.makeText(getBaseContext(), "Seleccionaches: " + ((TextView) view).getText(), Toast.LENGTH_LONG).show();<br />
<br />
}<br />
<br />
@Override<br />
public void onNothingSelected(AdapterView<?> arg0) {<br />
// TODO Auto-generated method stub<br />
}<br />
}); // Fin da clase anónima<br />
<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u4_02__spinner_adapter, menu);<br />
return true;<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
*'''Liña 26''': Comentamos o anterior construtor e ...<br />
*'''Liña 28''': usamos outro método que nos permita ler un recurso XML: ''createFromResource(this, R.array.froitas, android.R.layout.simple_spinner_item)''<br />
**Contexto,<br />
**Nome do recurso array que contén os ítems,<br />
**O int, identificador de recurso de layout que se vai usar para representar a Vista de Selección, neste caso usamos un predefinido. O usuario pode experimentar con outros tipos (android.R.layout.... CTRL+ESPAZO) e ver que outras formas hai de presentar os datos nun Spinner.<br />
**Para ver outros construtores e métodos: http://developer.android.com/reference/android/widget/ArrayAdapter.html<br />
**No canto de facer cambiar de método puidemos usar o construtor que usamos no primeiro caso:<br />
*** Pero antes recollemos o array XML nun array de Strings de datos: '''String[] froitas = getResources().getStringArray(R.array.froitas);''' <br />
*O resto non varía.<br />
<br />
==Uso dun array dinámico==<br />
*Nos dous casos anteriores o contido do Spinner é estático e defínese en tempo de compilación, non de execución.<br />
*Se usamos arrays dinámicos podemos crear a fonte de datos en tempo de execución antes de pasarlla ao adaptador.<br />
*Así imos poder usar datos de ficheiros, bases de datos, etc e crear unha fonte de datos para un Spinner en tempo de execución.<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="26,28,30-32" ><br />
<br />
package com.example.u4_02_spinneradapter;<br />
<br />
import java.util.ArrayList;<br />
import android.R.string;<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.AdapterView;<br />
import android.widget.AdapterView.OnItemSelectedListener;<br />
import android.widget.ArrayAdapter;<br />
import android.widget.Spinner;<br />
import android.widget.Toast;<br />
<br />
<br />
public class U4_02_SpinnerAdapter extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u4_02__spinner_adapter);<br />
<br />
Spinner spinFroitas = (Spinner) findViewById(R.id.spin_froitas);<br />
<br />
// Fonte de datos<br />
// String[] froitas = new String[] { "Pera", "Mazá", "Plátano" };<br />
<br />
ArrayList<String> froitas = new ArrayList<String>();<br />
<br />
froitas.add("Pera");<br />
froitas.add("Mazá");<br />
froitas.add("Plátano");<br />
<br />
// Enlace do adaptador cos datos<br />
ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, froitas);<br />
<br />
// Opcional: layout usuado para representar os datos no Spinner<br />
adaptador.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);<br />
<br />
// Enlace do adaptador co Spinner do Layout.<br />
spinFroitas.setAdapter(adaptador);<br />
<br />
// Escoitador<br />
spinFroitas.setOnItemSelectedListener(new OnItemSelectedListener() {<br />
@Override<br />
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {<br />
//Toast.makeText(getBaseContext(), "Seleccionaches: " + parent.getItemAtPosition(pos), Toast.LENGTH_LONG).show();<br />
Toast.makeText(getBaseContext(), "Seleccionaches: " + ((TextView) view).getText(), Toast.LENGTH_LONG).show();<br />
}<br />
<br />
@Override<br />
public void onNothingSelected(AdapterView<?> arg0) {<br />
// TODO Auto-generated method stub<br />
}<br />
}); // Fin da clase anónima<br />
<br />
}<br />
<br />
private String[] getStringArray(int froitas) {<br />
// TODO Auto-generated method stub<br />
return null;<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u4_02__spinner_adapter, menu);<br />
return true;<br />
}<br />
<br />
}<br />
<br />
</syntaxhighlight ><br />
<br />
*'''Liñas 23-28''': Neste caso os elementos do array engádense en tempo de execución ao array '''froitas''', que neste caso e do tipo '''ArrayList'''. <br />
*O resto é exactamente igual.<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Observaci%C3%B3ns_%C3%A1_edici%C3%B3n_2015-2016_do_curso&diff=57547Observacións á edición 2015-2016 do curso2015-11-05T19:03:36Z<p>Angelfg: Página creada con «*O material elaborado para esta edición baséase no material elaborado para a edición do curso 2013-2014. *Hai cambios de versións de Eclipse, SDK, APIS, etc respecto ao...»</p>
<hr />
<div>*O material elaborado para esta edición baséase no material elaborado para a edición do curso 2013-2014.<br />
*Hai cambios de versións de Eclipse, SDK, APIS, etc respecto ao do material inicial e estas iranse indicando en todo momento cando difiran da do material.<br />
*Pode que as imaxes non coincidan totalmente da versión do material dos apuntes ás que imos usar nesta edición. Se a imaxe mantén a "filosofía" coa nova versión non será modificada.</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=PDM_Avanzado_Reproduci%C3%B3n_de_Audio&diff=57519PDM Avanzado Reprodución de Audio2015-10-22T14:39:15Z<p>Angelfg: /* Reproducir música */</p>
<hr />
<div>==Introdución==<br />
<br />
No caso da reprodución do audio, teremos que facer uso das clases '''MediaPlayer''' e '''AudioManager'''.<br />
<br />
Clase utilizadas:<br />
[http://developer.android.com/reference/android/media/MediaPlayer.html MediaPlayer]: esta clase é a principal utilizada para reproducir audio – vídeo.<br />
[http://developer.android.com/reference/android/media/AudioManager.html AudioManager]: manexa fontes de audio e gravacións de audio en dispositivos. Nesta parte só imos utilizala para indicar o tipo de audio.<br />
<br />
Permisos necesarios a engadir no arquivo AndroidManifest.xml (nos imos engadir todos):<br />
<br />
* Se o dispositivo necesita conexión a internet (para escoitar música en streaming, por exemplo) temos que engadir o permiso:<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
<uses-permission android:name="android.permission.INTERNET" /><br />
</syntaxhighlight> <br />
<br />
<br />
* Permiso Wake-Lock: no momento no que o S.O. non vexa ‘movemento’ no dispositivo (ou sexa uso) pasará a un estado de modo suspendido. Se queremos que a nosa activity non entre en dito estado podemos facer uso do método MediaPlayer.setWakeMode() e polo tanto necesitaremos o permiso wake_lock:<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
<uses-permission android:name="android.permission.WAKE_LOCK" /><br />
</syntaxhighlight> <br />
<br />
<br />
<br />
* Permiso de escritura na SD Card: Para ter acceso á memoria externa teremos que especificar no arquivo AndroidManifest.xml que a nosa aplicación necesita permiso de lectura/escritura en dicha memoria.<br />
<br />
:*Se imos ler na tarxeta SD:<br />
::* Se a versión do S.O. Android é inferior á 4.1 non precisamos ningún permiso.<br />
::* Se a versión do S.O. Android é superior ou igual á 4.1 debemos engadir o permiso: '''<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>'''<br />
:* Se imos escribir na tarxeta SD:<br />
::* Se a versión do S.O. Android é inferior á 4.4 o permiso é: '''<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> '''.<br />
::* Se a versión do S.O. Android é a 4.4 ou superior. Podemos poñer o mesmo permiso anterior pero as aplicacións dispoñen dun cartafol para escribir na SD (cartafol Android/data/paquete/) sen necesidade de ter o permiso anterior.<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><br />
</syntaxhighlight> <br />
<br />
<br />
<u>Nota:</u> se queremos ter unha música de fondo na nosa aplicación o máis lóxico sería ter un servizo.<br />
<br />
<br />
Para engadir ditos permisos de forma gráfica, nos abrimos o arquivo '''AndroidManifest.xml'''.<br />
<br />
<gallery caption="Proceso para engadir permisos de forma gráfica" widths="350" heights="350px" perrow="2"><br />
Image:PDM_Avanzada_Multimedia_Reprod_01.jpg | Prememos a pestana ‘Permissions’ e prememos o botón Add.<br />
Image:PDM_Avanzada_Multimedia_Reprod_02.jpg| Escollemos a opción '''Uses Permission'''.<br />
Image:PDM_Avanzada_Multimedia_Reprod_03.jpg| Graficamente escollemos os permisos que necesitemos.<br />
</gallery><br />
<br />
==MediaPlayer==<br />
<br />
Os recursos (arquivos de audio) que podemos utilizar con esta clase poden ser:<br />
<br />
* '''Locais''': arquivos locais gardados no cartafol /res/raw/ (deberemos crear o cartafol /raw/ se non existe).<br />
* '''URIs internas''': unha URI é unha forma de identificar de forma unívoca un recurso (neste caso multimedia). Podemos referenciar arquivos multimedia gardados nas diferentes tarxetas de memoria do dispositivo.<br />
* '''URL Externos (streaming)''': arquivos multimedia que se atopan en Internet.<br />
<br />
<br />
Podedes consultar a lista de formatos de audio – vídeo soportados en http://developer.android.com/guide/appendix/media-formats.html<br />
<br />
<br />
Imos facer unha pequena práctica na que imos reproducir un arquivo multimedia.<br />
Creamos no proxecto de Android - Multimedia un cartafol de nome ‘raw’ dentro do cartafol /res/ do proxecto:<br />
<br />
<br />
===Reproducir música===<br />
<br />
Para cargar un arquivo de audio temos que seguir os seguintes pasos:<br />
<br />
* Crear un obxecto da clase MediaPlayer.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
private MediaPlayer mediaplayer;<br />
.............<br />
mediaplayer = new MediaPlayer();<br />
</syntaxhighlight> <br />
<br />
* Chamar ao método '''setDataSource''' que queiramos (pode dar lugar a varios tipos de excepcións, polo que teremos que usar try catch para cada tipo delas ou ben capturalos cunha clase '''Exception''' aínda que esta forma non é a recomendada). <br />
:No exemplo usamos '''Exception''' para simplificar o código xa que se non teríamos que ter isto:<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
try {<br />
mediaplayer.setDataSource(path);<br />
} catch (IllegalArgumentException e) {<br />
// TODO Auto-generated catch block<br />
e.printStackTrace();<br />
} catch (SecurityException e) {<br />
// TODO Auto-generated catch block<br />
e.printStackTrace();<br />
} catch (IllegalStateException e) {<br />
// TODO Auto-generated catch block<br />
e.printStackTrace();<br />
} catch (IOException e) {<br />
// TODO Auto-generated catch block<br />
e.printStackTrace();<br />
}<br />
</syntaxhighlight> <br />
<br />
Con este método indicamos de onde imos a cargar o audio.<br />
<br />
Podemos ter varias posibilidades:<br />
<br />
:* O arquivo se atopa en /res/raw:<br />
::<syntaxhighlight lang="java" line enclose="div" highlight="4" ><br />
MediaPlayer mediaplayer = new MediaPlayer();<br />
Uri uri = Uri.parse("android.resource://" + getPackageName()+ "/" + R.raw.snowflake_persephone);<br />
try {<br />
mediaplayer.setDataSource(getApplicationContext(), uri);<br />
.....<br />
}<br />
</syntaxhighlight> <br />
<br />
<br />
:* O arquivo provén da tarxeta SD.<br />
:: Temos varias opcións:<br />
:::<syntaxhighlight lang="java" line enclose="div" highlight="4" ><br />
MediaPlayer mediaplayer = new MediaPlayer();<br />
String path=Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator + "snowflake_persephone.mp3";<br />
try {<br />
mediaplayer.setDataSource(path);<br />
.....<br />
}<br />
</syntaxhighlight> <br />
<br />
:::<syntaxhighlight lang="java" line enclose="div" highlight="5" ><br />
MediaPlayer mediaplayer = new MediaPlayer();<br />
String path =Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator + "snowflake_persephone.mp3";<br />
Uri uri = Uri.parse(Uri.encode(path)); <br />
try {<br />
mediaplayer.setDataSource(getApplicationContext(),uri);<br />
.....<br />
}<br />
</syntaxhighlight> <br />
<br />
<br />
:* O arquivo provén de Internet (música en Streaming).<br />
<u>Nota:</u> Se estades a utilizar un dispositivo real ten que ter conexión a Internet para que funcione.<br />
:: Temos varias opcións:<br />
:::<syntaxhighlight lang="java" line enclose="div" highlight="4" ><br />
MediaPlayer mediaplayer = new MediaPlayer();<br />
String url="http://www.mfiles.co.uk/mp3-downloads/edvard-grieg-peer-gynt1-morning-mood.mp3";<br />
try {<br />
mediaplayer.setDataSource(url);<br />
.....<br />
}<br />
</syntaxhighlight> <br />
<br />
<br />
Pode suceder que a dirección da URL teña espazos en branco ou caracteres especiais. Nese caso teremos que 'codificar' antes a url a partires do último carácter '/': <br />
:::<syntaxhighlight lang="java" line enclose="div" highlight="4,6" ><br />
MediaPlayer mediaplayer = new MediaPlayer();<br />
String url="http://www.mfiles.co.uk/mp3-downloads/edvard-grieg-peer-gynt1-morning-mood.mp3";<br />
int pos = url.lastIndexOf('/') + 1;<br />
Uri uri = Uri.parse(url.substring(0, pos) + Uri.encode(url.substring(pos)));<br />
try {<br />
mediaplayer.setDataSource(getApplicationContext(),uri);<br />
.....<br />
}<br />
</syntaxhighlight> <br />
<br />
<br />
<br />
* Chamar ao método '''setAudioStreamType(AudioManager.STREAM_MUSIC)''' para indicarlle que o que imos reproducir será música e poñerá o volume que teña o S.O. (lembrar que en Android podemos cambiar o volume da música, notificacións e alarmas).<br />
* Chamar ao método '''prepare''' (pode lanzar unha excepción IOException).<br />
* Chamar ao método '''start'''.<br />
<br />
Todos estes pasos son necesarios facelos nesta orde xa que o MediaPlayer vai pasar por unha serie de '''estados''' que nos van obrigar a poder facer só unha accións determinadas dependendo do estado no que nos atopemos.<br />
<br />
Vexamos o diagrama de estados do MediaPlayer:<br />
<br />
[[Imagen:PDM_Avanzada_Multimedia_Reprod_07.jpg | 400px |center]]<br />
<center>Gráfico obtido dende http://developer.android.com/reference/android/media/MediaPlayer.html</center><br />
<br />
<br />
Imos analizar dito diagrama.<br />
<br />
Cando instanciamos o MediaPlayer (facemos o new) nos situamos no '''estado idle'''. Dende dito estado so podemos pasar o '''estado initialized''' chamando o método setDataSource.<br />
<br />
Se intentemos chamar a outro método (coma start(),...) daranos unha excepción (IlegalStateException).<br />
Cando estamos a tocar unha canción non podemos cambiar por outra, xa que aínda que chamemos o método stop e pasemos o '''estado de stop''', dende dito estado non podemos chamar ao método setDataSource (mirar diagrama).<br />
<br />
A única forma de cambiar de canción será chamando ao método reset(), que volve ao estado Idle como amosamos neste anaco do diagrama anterior:<br />
<br />
[[Imagen:PDM_Avanzada_Multimedia_Reprod_08.jpg | 300px |center]]<br />
<br />
<br/><br />
<br/><br />
----<br />
Podemos cargar un arquivo de audio sen facer os pasos anteriores da seguinte forma:<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
MediaPlayer mediaPlayer=MediaPlayer.create(this, R.raw.snowflake_persephone);<br />
mediaPlayer.start(); <br />
</syntaxhighlight> <br />
<br />
Sendo R.raw.snowflake_persephone un arquivo de audio que se atopa no cartafol /res/raw.<br />
<br />
Desta forma estamos a pasar directamente ao estado Prepared do diagrama anterior.<br />
No nosa práctica <u>non usaremos</u> esta forma de cargar o audio.<br />
<br />
----<br />
<br/><br />
<br/><br />
<br />
===Caso práctico===<br />
<br />
O obxectivo desta práctica é reproducir un arquivo de música gardado en /res/raw e outro en streaming de Internet.<br/><br />
<u>Nota:</u> Se instalades a aplicación nun dispositivo real tedes que ter conexión a Internet para que funcione a reprodución en streaming.<br />
<br />
[[Imagen:PDM_Avanzada_Multimedia_Reprod_09.jpg |400px | center]]<br />
<br />
<br />
====Preparación====<br />
<br />
* Copiamos o arquivo de audio (ou outro calquera que podades utilizar) ao cartafol /res/raw.<br />
<br />
[[Media:snowflake_persephone.mp3]] . <br />
<br />
'''ATENCIÓN:''' Ao ser un arquivo que vai ser gardado no interior do cartafol /res de Android, o arquivo '''non pode ter letras maiúsculas'''.<br />
<br />
<gallery caption="Copiando arquivo de audio a /res/raw" widths="300" heights="300px" perrow="2"><br />
Image:PDM_Avanzada_Multimedia_Reprod_04.jpg| Creamos o cartafol '''raw''' dentro de /res.<br />
Image:PDM_Avanzada_Multimedia_Reprod_05.jpg | Copiamos o arquivo de audio anterior. TODAS AS LETRAS DEBEN IR EN MINÚSCULAS.<br />
</gallery><br />
<br />
====Creamos a Activity====<br />
<br />
*Nome do proxecto: '''UD2_01_MultimediaReproductor'''<br />
*Nome da activity: '''UD2_01_MultimediaReproductor.java'''<br />
<br />
<br />
'''Código do layout xml'''<br/><br />
<u>Nota:</u> Por motivos de tempo para o alumnado o deseño non fai uso de constantes externas definidas no cartafol values. Queda claro que esta debería ser a opción escollida para o deseño das Interfaces de Usuario.<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:id="@+id/LinearLayout1"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:orientation="vertical" ><br />
<br />
<br />
<TextView<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:gravity="center_horizontal"<br />
android:layout_marginBottom="20dp"<br />
android:text="UD2_01_Multimedia"<br />
android:textSize="20sp" /><br />
<br />
<br />
<TableLayout<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:layout_gravity="bottom" <br />
android:isScrollContainer="true"<br />
><br />
<br />
<TableRow<br />
android:id="@+id/tableRow1"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content" ><br />
<br />
<br />
<Button<br />
android:id="@+id/UD2_01_btnReprLocal"<br />
android:width="0dp"<br />
android:layout_weight="1"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="LOCAL"<br />
android:textSize="10sp"<br />
/><br />
<br />
<Button<br />
android:id="@+id/UD2_01_btnReprInternet"<br />
android:width="0dp"<br />
android:layout_weight="1"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="INTERNET"<br />
android:textSize="10sp"<br />
/><br />
<br />
</TableRow><br />
<br />
<TableRow<br />
android:id="@+id/tableRow2"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content" ><br />
<br />
<Button<br />
android:id="@+id/UD2_02_btnPararRepr"<br />
android:layout_width="0dp"<br />
android:layout_height="wrap_content"<br />
android:layout_weight="1"<br />
android:text="PARAR"<br />
android:textSize="10sp" /><br />
<br />
</TableRow><br />
<TableRow<br />
android:id="@+id/tableRow4"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content" ><br />
<br />
<Button<br />
android:id="@+id/UD2_02_btnSairAplicacion"<br />
android:layout_width="0dp"<br />
android:layout_height="wrap_content"<br />
android:layout_weight="1"<br />
android:text="SAIR"<br />
android:textSize="10sp" <br />
/><br />
<br />
</TableRow><br />
<br />
<br />
</TableLayout><br />
<br />
</LinearLayout><br />
<br />
<br />
</syntaxhighlight> <br />
<br />
<br />
'''Código da clase UD2_01_MultimediaReproductor'''<br/><br />
'''Obxectivo:''' Reproducir e parar música local e de Internet.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="18,19,26-40,48-52,59-64,71-76,106-109,113-124,126-135,142" ><br />
package com.platega.angel.multimedia;<br />
<br />
import java.io.File;<br />
<br />
import android.app.Activity;<br />
import android.media.AudioManager;<br />
import android.media.MediaPlayer;<br />
import android.net.Uri;<br />
import android.os.Bundle;<br />
import android.os.Environment;<br />
import android.util.Log;<br />
import android.view.View;<br />
import android.view.View.OnClickListener;<br />
import android.widget.Button;<br />
<br />
public class UD2_01_MultimediaReproductor extends Activity {<br />
<br />
private MediaPlayer mediaplayer;<br />
private boolean pause; // Indica se o mediaplayer estaba tocando cando cambiamos de aplicación<br />
<br />
<br />
/**<br />
* Cambia a canción no MediaPlayer<br />
* @param uri<br />
*/<br />
private void cambiarCancion(Uri uri){<br />
try {<br />
mediaplayer.reset();<br />
<br />
mediaplayer.setDataSource(getApplicationContext(),uri);<br />
mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);<br />
mediaplayer.prepare();<br />
mediaplayer.start();<br />
} catch (Exception e) {<br />
// TODO Auto-generated catch block<br />
e.printStackTrace();<br />
Log.e("MULTIMEDIA",e.getMessage());<br />
}<br />
<br />
}<br />
<br />
private void xestionarEventos(){<br />
<br />
Button btnLocal = (Button)findViewById(R.id.UD2_01_btnReprLocal);<br />
btnLocal.setOnClickListener(new OnClickListener() {<br />
<br />
@Override<br />
public void onClick(View v) {<br />
// TODO Auto-generated method stub<br />
Uri uri = Uri.parse("android.resource://" + getPackageName()+ "/" + R.raw.snowflake_persephone);<br />
cambiarCancion(uri);<br />
}<br />
});<br />
<br />
Button btnInternet = (Button)findViewById(R.id.UD2_01_btnReprInternet);<br />
btnInternet.setOnClickListener(new OnClickListener() {<br />
<br />
@Override<br />
public void onClick(View v) {<br />
// TODO Auto-generated method stub<br />
String url = "http://www.mfiles.co.uk/mp3-downloads/edvard-grieg-peer-gynt1-morning-mood.mp3";<br />
Uri uri = Uri.parse(Uri.encode(url));<br />
cambiarCancion(uri);<br />
}<br />
});<br />
<br />
Button btnParar = (Button)findViewById(R.id.UD2_02_btnPararRepr);<br />
btnParar.setOnClickListener(new OnClickListener() {<br />
<br />
@Override<br />
public void onClick(View v) {<br />
// TODO Auto-generated method stub<br />
if (mediaplayer.isPlaying())<br />
mediaplayer.stop();<br />
pause=false;<br />
}<br />
});<br />
<br />
Button btnSair = (Button) findViewById(R.id.UD2_02_btnSairAplicacion);<br />
btnSair.setOnClickListener(new OnClickListener() {<br />
<br />
@Override<br />
public void onClick(View v) {<br />
// TODO Auto-generated method stub<br />
finish();<br />
}<br />
});<br />
<br />
<br />
}<br />
<br />
@Override<br />
protected void onPause() {<br />
super.onPause();<br />
<br />
if (mediaplayer.isPlaying()){<br />
mediaplayer.pause();<br />
pause = true;<br />
}<br />
}<br />
<br />
@Override<br />
protected void onResume() {<br />
super.onResume();<br />
<br />
if (pause) {<br />
mediaplayer.start();<br />
pause = false;<br />
}<br />
}<br />
<br />
<br />
@Override<br />
protected void onSaveInstanceState(Bundle estado) {<br />
estado.putBoolean("MEDIAPLAYER_PAUSE", pause);<br />
super.onSaveInstanceState(estado);<br />
}<br />
<br />
@Override<br />
protected void onRestoreInstanceState(Bundle savedInstanceState) {<br />
super.onRestoreInstanceState(savedInstanceState);<br />
savedInstanceState.putBoolean("MEDIAPLAYER_PAUSE", false);<br />
pause = savedInstanceState.getBoolean("MEDIAPLAYER_PAUSE");<br />
}<br />
<br />
@Override<br />
protected void onDestroy() {<br />
super.onDestroy();<br />
<br />
if (mediaplayer.isPlaying()) mediaplayer.stop();<br />
<br />
if (mediaplayer != null) mediaplayer.release();<br />
mediaplayer = null;<br />
<br />
}<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_ud2_01__multimedia_reproductor);<br />
<br />
mediaplayer = new MediaPlayer();<br />
pause = false;<br />
xestionarEventos();<br />
<br />
<br />
}<br />
}<br />
<br />
</syntaxhighlight> <br />
<br />
* Liña 18: Definimos o reprodutor.<br />
* Liña 19: Definimos unha variable booleana que nos indique cando o reprodutor está en estado de PAUSE.<br />
* Liñas 26-40: Cambiamos de canción. Fixarse como sempre chamamos ao método reset() para pasar ao estado que nos permite cambiar a fonte de audio.<br />
* Liñas 48-52: Prememos o botón de LOCAL e definimos a URI para buscar o arquivo en /res/raw.<br />
* Liñas 59-64: Prememos o botón de INTERNET e definimos a URI para buscar o arquivo indicada na URL.<br />
* Liñas 71-76: Prememos o botón de STOP. Comprobamos se o mediaplayer está tocando para paralo.<br />
* Liñas 106-109: Comprobamos se o mediaplayer está tocando para poñelo en pause. Cambiamos o valor da variable pause a true. Isto é necesario xa que non temos forma de saber a través do mediaplayer se este se atopa nese estado.<br />
* Liñas 106-109: Se volvemos á aplicación comprobamos se o mediaplayer estaba tocando (pause=true) e nese caso continuamos tocando a canción. Isto pasará cando cambiemos de aplicación sen pechala.<br />
* Liñas 113-124: Se cambiamos de aplicación recuperamos o estado do mediaplayer. Despois poñemos a false a variable pause por se xiramos o dispositivo estando tocando, para que non recupere o último estado.<br />
* Liñas 126-135: De saímos da aplicación paramos de tocar e liberamos o mediaplayer.<br />
* Liña 142: Instanciamos o mediaplayer.<br />
<br />
==Carga asíncrona==<br />
<br />
Cando poñemos en marcha un arquivo de audio que non se atopa localmente, non é boa idea facelo no fío principal da aplicación, xa que se leva un tempo cargar a música, e a aplicación quedaría bloqueada mentres tanto.<br />
Para evitalo teríamos que crear nós un fío de execución separado do principal, pero este traballo xa o temos feito, se chamamos ao [http://developer.android.com/reference/android/media/MediaPlayer.html#prepareAsync%28%29 método prepareAsync()] . Cando a mediaplayer estea listo, chamará automaticamente ao método onPrepared da interface MediaPlayer.OnPreparedListener. Para asociar dita interface o mediaplayer, faremos uso do método setOnPreparedListener().<br />
<br />
Os pasos serían:<br />
<br />
* Asociar a interface ao mediaplayer:<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
mediaplayer.setOnPreparedListener(new OnPreparedListener(){<br />
<br />
}<br />
);<br />
</syntaxhighlight> <br />
<br />
* Ao definir internamente a clase que xestionará o preparedlistener, é necesario implementar o método da interface dentro da definición:<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
<br />
mediaplayer.setOnPreparedListener(new OnPreparedListener(){<br />
<br />
public void onPrepared(MediaPlayer arg0) {<br />
// TODO Auto-generated method stub<br />
<br />
}<br />
}<br />
);<br />
</syntaxhighlight> <br />
<br />
* Agora xa podemos codificar o método onPrepared que será chamado automaticamente cando o música estea preparada. O único que temos que facer dentro de dito método será unha chamada ao método start() da clase MediaPlayer.<br />
<br />
<br />
<u>Nota:</u> Agora en vez de chamar o método prepare, teremos que chamar o método prepareAsync().<br />
<br />
<br />
===Caso práctico===<br />
<br />
O obxectivo desta práctica é facer o mesmo que na práctica anterior pero chamando ao método '''prepareAsync.<br />
<br />
====Preparación====<br />
<br />
O alumno debe crear unha nova activity de nome '''UD2_02_MultimediaReproductor'''. <br />
<br />
Esta activity ten o mesmo layout que a activity anterior (activity_ud2_01__multimedia_reproductor.xml) xa que non imos facer modificacións no seu aspecto.<br />
<br />
====Creamos a activity====<br />
<br />
*Nome do proxecto: '''UD2_02_MultimediaReproductor'''<br />
*Nome da activity: '''UD2_02_MultimediaReproductor.java'''<br />
<br />
<br />
'''Código da clase UD2_02_MultimediaReproductor'''<br/><br />
'''Obxectivo:''' Amosar como cargar unha canción de forma asíncrona.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="30,42-49" ><br />
package com.platega.angel.multimedia;<br />
<br />
import android.app.Activity;<br />
import android.media.AudioManager;<br />
import android.media.MediaPlayer;<br />
import android.media.MediaPlayer.OnPreparedListener;<br />
import android.net.Uri;<br />
import android.os.Bundle;<br />
import android.util.Log;<br />
import android.view.View;<br />
import android.view.View.OnClickListener;<br />
import android.widget.Button;<br />
<br />
public class UD2_02_MultimediaReproductor extends Activity {<br />
<br />
private MediaPlayer mediaplayer;<br />
private boolean pause; // Indica se o mediaplayer estaba tocando cando cambiamos de aplicación<br />
<br />
<br />
/**<br />
* Cambia a canción no MediaPlayer<br />
* @param uri<br />
*/<br />
private void cambiarCancion(Uri uri){<br />
try {<br />
mediaplayer.reset();<br />
<br />
mediaplayer.setDataSource(getApplicationContext(),uri);<br />
mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);<br />
mediaplayer.prepareAsync();<br />
// mediaplayer.start(); O FACEMOS DE FORMA ASINCRONA<br />
} catch (Exception e) {<br />
// TODO Auto-generated catch block<br />
e.printStackTrace();<br />
Log.e("MULTIMEDIA",e.getMessage());<br />
}<br />
<br />
}<br />
<br />
private void xestionarEventos(){<br />
<br />
mediaplayer.setOnPreparedListener(new OnPreparedListener() {<br />
<br />
@Override<br />
public void onPrepared(MediaPlayer mp) {<br />
// TODO Auto-generated method stub<br />
mediaplayer.start();<br />
}<br />
});<br />
<br />
Button btnLocal = (Button)findViewById(R.id.UD2_01_btnReprLocal);<br />
btnLocal.setOnClickListener(new OnClickListener() {<br />
<br />
@Override<br />
public void onClick(View v) {<br />
// TODO Auto-generated method stub<br />
Uri uri = Uri.parse("android.resource://" + getPackageName()+ "/" + R.raw.snowflake_persephone);<br />
cambiarCancion(uri);<br />
}<br />
});<br />
<br />
Button btnInternet = (Button)findViewById(R.id.UD2_01_btnReprInternet);<br />
btnInternet.setOnClickListener(new OnClickListener() {<br />
<br />
@Override<br />
public void onClick(View v) {<br />
// TODO Auto-generated method stub<br />
String url = Uri.encode("http://www.mfiles.co.uk/mp3-downloads/edvard-grieg-peer-gynt1-morning-mood.mp3");<br />
Uri uri = Uri.parse(Uri.encode(url));<br />
cambiarCancion(uri);<br />
}<br />
});<br />
<br />
Button btnParar = (Button)findViewById(R.id.UD2_02_btnPararRepr);<br />
btnParar.setOnClickListener(new OnClickListener() {<br />
<br />
@Override<br />
public void onClick(View v) {<br />
// TODO Auto-generated method stub<br />
if (mediaplayer.isPlaying())<br />
mediaplayer.stop();<br />
pause=false;<br />
}<br />
});<br />
<br />
Button btnSair = (Button) findViewById(R.id.UD2_02_btnSairAplicacion);<br />
btnSair.setOnClickListener(new OnClickListener() {<br />
<br />
@Override<br />
public void onClick(View v) {<br />
// TODO Auto-generated method stub<br />
finish();<br />
}<br />
});<br />
<br />
<br />
}<br />
<br />
@Override<br />
protected void onPause() {<br />
super.onPause();<br />
<br />
if (mediaplayer.isPlaying()){<br />
mediaplayer.pause();<br />
pause = true;<br />
}<br />
}<br />
<br />
@Override<br />
protected void onResume() {<br />
super.onResume();<br />
<br />
if (pause) {<br />
mediaplayer.start();<br />
pause = false;<br />
}<br />
}<br />
<br />
<br />
@Override<br />
protected void onSaveInstanceState(Bundle estado) {<br />
estado.putBoolean("MEDIAPLAYER_PAUSE", pause);<br />
super.onSaveInstanceState(estado);<br />
}<br />
<br />
@Override<br />
protected void onRestoreInstanceState(Bundle savedInstanceState) {<br />
super.onRestoreInstanceState(savedInstanceState);<br />
savedInstanceState.putBoolean("MEDIAPLAYER_PAUSE", false);<br />
pause = savedInstanceState.getBoolean("MEDIAPLAYER_PAUSE");<br />
}<br />
<br />
@Override<br />
protected void onDestroy() {<br />
super.onDestroy();<br />
<br />
if (mediaplayer.isPlaying()) mediaplayer.stop();<br />
<br />
if (mediaplayer != null) mediaplayer.release();<br />
mediaplayer = null;<br />
<br />
}<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_ud2_02__multimedia_reproductor);<br />
<br />
mediaplayer = new MediaPlayer();<br />
pause = false;<br />
xestionarEventos();<br />
<br />
<br />
}<br />
}<br />
<br />
</syntaxhighlight> <br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2014).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Curso_Platega:_Desenvolvemento_de_aplicaci%C3%B3ns_para_dispositivos_m%C3%B3biles_con_Android&diff=57511Curso Platega: Desenvolvemento de aplicacións para dispositivos móbiles con Android2015-10-21T09:04:07Z<p>Angelfg: /* UNIDADE 2: A interface de usuario. */</p>
<hr />
<div>[[Imagen:00-Android-Developer2.png|left|200px]][[Imagen:Android_2013_olamundo_14.jpg|450px|right]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br><h2 style="margin:0; background:#E6ECFF; font-size:100%; border:1px solid #cccccc; text-align:left; padding:0.2em 0.4em; -moz-border-radius:6px">http://i.creativecommons.org/l/by-nc-sa/3.0/es/88x31.png <br />
<br><br />
<p>Este manual de '''Curso Platega: Programación en dispositivos móbiles: Android''' é creado e editado por [[Usuario:angelfg| Ángel D. Fernandez González]] e [[Usuario:Carrion| Carlos Carrión Álvarez]] baixo a licenza [http://creativecommons.org/licenses/by-nc-sa/3.0/es/ Creative Commons 3.0:] <br />
*Copiar, distribuír e comunicar publicamente a obra, sempre mencionando ós autores.<br />
*Uso non comercial. <br />
*Compartir as modificacións baixo a mesma licenza. <br />
<br />
Para calquera outro tipo de uso non contemplado na licenza anterior consulte ós autores: [[Usuario:angelfg| Ángel D. Fernández González]] ou [[Usuario:Carrion| Carlos Carrión Álvarez]].<br />
</p></h2><br />
<br />
<br />
<br />
Este manual/curso está deseñado para o curso de formación do profesorado: [https://www.edu.xunta.es/fprofe/procesaConsultaPublica.do?DIALOG-EVENT-ver=ver&cod_actividade=54372 Desenvolvemento de aplicacións para dispositivos móbiles con Android.] <br />
<br />
<br> <br />
<br />
Dado que o tema é moi extenso, trátase de abrir un abano das posibilidades que nos ofrece a programación en dispositivos móbiles e en concreto con Android.<br />
<br />
O seu seguimento será realizado a través da plataforma [http://www.edu.xunta.es/platega/login/index.php PLATEGA] da [http://www.edu.xunta.es Consellería de Cultura, Educación e Ordenación Universitaria] da [http://www.xunta.es Xunta de Galicia].<br />
<br />
<br> <br />
<br />
Cada unha das partes do curso comeza indicando os obxectivos que persegue, así como, o escenario necesario para levalo a cabo.<br />
<br />
<br> <br />
<br />
<br />
<br />
=='''UNIDADE 0: Coñecementos de partida e observacións sobre o material'''==<br />
<br />
----<br />
<br />
*[[PDM Android: Coñecementos previos]]<br />
*[[Material vivo]]<br />
<br />
<br><br />
<br />
=='''UNIDADE 1: Instalación JDK, Eclipse e Android SDK. Xestión dispositivos'''==<br />
<br />
----<br />
<br />
*[[PDM: Android. Obxectivos e escenarios do UNIDADE 1]] <br />
*[[Introdución a Android: Versións, APIS e SDK]]<br />
*[[Instalación JDK, Eclipse, Android SDK e ADT Plugin]]<br />
**[[Instalación en Ubuntu]]<br />
**[[Instalación en Windows]]<br />
**[[Instalación en OS X]]<br />
**[[Instalación ADT Bundle]]<br />
*[[Dispositivos Virtuais de Android: AVD]]<br />
*[[Android Debug Bridge: ADB]]<br />
*[[Variables de contorno]]<br />
*[[Dalvik Debug Monitor Server: (DDMS) - Logcat]]<br />
*[[O meu primeiro programa: Ola Mundo]]<br />
<br />
<br />
<br><br />
<br />
=='''UNIDADE 2: A interface de usuario.'''==<br />
<br />
----<br />
*[[PDM: Android. Obxectivos e escenarios do UNIDADE 2]]<br />
*[[Xestión de proxectos en Eclipse]]<br />
**[[Sincronizar cartafoles na nube con Ubuntu One]] ('''Platega Edicción 2015: Non mirar. Obsoleto''')<br />
**[[Xestión de proxectos Eclipse con Ubuntu One (ou non)]] ('''Platega Edicción 2015: Non mirar. Obsoleto''')<br />
*[[Ficheiros e cartafoles dun proxecto Android: Ola Mundo. Activities, Layouts e Múltiples pantallas]]<br />
*[[Interface gráfica (UI - User Interface). Vistas (Views). Atributos básicos.]]<br />
*[[Deseño de pantallas: Layouts]]<br />
**[[FrameLayout]]<br />
**[[LinearLayout]]<br />
**[[RelativeLayout]]<br />
**[[TableLayout]]<br />
*[[Controis]]<br />
**[[TextView. Definición de recursos XML]]<br />
**[[EditText. Control de eventos I]]<br />
**[[Button. ToggleButton. Control de eventos II]]<br />
**[[CheckBox]]<br />
**[[RadioButton]]<br />
**[[Spinner]]<br />
**[[ImageView]]<br />
**[[Chronometer. Cliclo de vida I (finish())]]<br />
**[[Toast]]<br />
*[[Xerar Views nun Layout en tempo de execución. Layout ScrollView]]<br />
*[[Deseños diferentes en función da orientación do dispositivo]]<br />
*[[Internacionalización]]<br />
*[[Estilos e temas]]<br />
*[[Lanzar unha Activity]]<br />
<br />
<br />
<br />
[[Aplicación a desenvolver]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br><br />
<br />
=='''UNIDADE 3: O Ciclo de Vida dunha Actividade. Diálogos. Drag and drop. Animacións.'''==<br />
<br />
----<br />
*[[PDM: Android. Obxectivos e escenarios do UNIDADE 3]]<br />
*[[Ciclo de vida dunha aplicación]]<br />
**[[Xestion de eventos III. onLongClick]]<br />
*[[Ventás de Diálogos]]<br />
*[[Drag & Drop]]<br />
*[[Animacións]]<br />
<br />
<br />
<br><br />
<br />
=='''UNIDADE 4: Multimedia.'''==<br />
----<br />
<br />
<br />
<br><br />
<br />
=='''UNIDADE 5: Preferencias – Arquivos – Bases de datos.'''==<br />
<br />
----<br />
<br />
<br><br />
<br />
=='''UNIDADE 6: Menús. Threads. Comunicación. Empaquetado e distribución.'''==<br />
<br />
----<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2013).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Archivo:PDM_Avanzada_Permisos_2.jpg&diff=57483Archivo:PDM Avanzada Permisos 2.jpg2015-10-17T18:14:28Z<p>Angelfg: Angelfg subió una nueva versión de «Archivo:PDM Avanzada Permisos 2.jpg»</p>
<hr />
<div></div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Archivo:PDM_Avanzada_Permisos_1.JPG&diff=57477Archivo:PDM Avanzada Permisos 1.JPG2015-10-17T16:55:51Z<p>Angelfg: </p>
<hr />
<div></div>Angelfghttps://manuais.iessanclemente.net/index.php?title=PDM_Avanzado_Obxectivos_e_escenarios_da_UNIDADE_8&diff=57476PDM Avanzado Obxectivos e escenarios da UNIDADE 82015-10-17T16:50:19Z<p>Angelfg: Página creada con «Como sabemos o mundo da informática non para, e o que antes se facía dunha forma agora se fai doutra. En Android, para a nosa desgracia paso o mesmo. Nesta entrada imos...»</p>
<hr />
<div>Como sabemos o mundo da informática non para, e o que antes se facía dunha forma agora se fai doutra.<br />
<br />
En Android, para a nosa desgracia paso o mesmo.<br />
<br />
Nesta entrada imos poñer aquelas modificacións que vaian cambiando nas versións seguintes da API Android e que non teñan unha entrada específica nas unidades do curso.<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]]</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Instalaci%C3%B3n_en_Ubuntu&diff=57469Instalación en Ubuntu2015-10-15T14:12:46Z<p>Angelfg: /* Instalación OpenJDK */</p>
<hr />
<div>==Introdución==<br />
*Como xa se dixo, a versión de Ubuntu na que se elaborou o curso é a '''Ubuntu Desktop 13.10 de 64 bits'''. Tamén se probou na versión '''Ubuntu Desktop 14.04 de 64 bits'''<br />
*A razón de instalar cada compoñente por separado é que nos vai permitir ter un maior control de todo canto se precisa e ademais vai poder permitir que cada lector instale os compoñentes que precise en función dos que xa ten instalados.<br />
*Compoñentes:<br />
{| <br />
|- style="height:70px" <br />
| [[Imagen:00_OpenJDK.jpg|70px]]<br />
| O [http://es.wikipedia.org/wiki/OpenJDK OpenJDK] (Java Development Kit), versión libre do JDK liderada por [http://es.wikipedia.org/wiki/Oracle_Corporation Oracle].<br> Como xa se indicou vaise instalar o JDK no canto do JRE (MV de Java), por se alguén desexa programar a maiores en Java en consola ou con outros IDEs.<br>Nesta ocasión vaise facer uso de [http://openjdk.java.net/ OpenJDK] e non do JDK de Oracle, porque xa vén nos repositorios de Ubuntu.<br> Quen o desexe pode descargar o JDK orixinal de Oracle e instalalo seguindo os pasos: http://www.oracle.com/technetwork/java/javase/downloads/index.html.<br />
|- style="height:70px" <br />
| [[Imagen:00_Eclipse.png|70px]]<br />
| O [http://es.wikipedia.org/wiki/Entorno_de_desarrollo_integrado IDE] (Integrated Development Enviroment) de [http://es.wikipedia.org/wiki/Eclipse_%28software%29 Eclipse].<br />
|- style="height:70px" <br />
| [[Imagen:00_android_platform.png|70px]]<br />
| O [http://es.wikipedia.org/wiki/SDK SDK] (Software Development Kit) de [http://es.wikipedia.org/wiki/Android Android]<br />
|- style="height:70px" <br />
| [[Imagen:00_ADT.png|70px]]<br />
| O '''ADT Plugin''' (Android Development Tools) para Eclipse. Permitirá facer uso dende o IDE do SDK de Android.<br />
|}<br />
<br />
*Quen desexe instalar todo isto en Ubuntu con entorno Unity e non se sinta con soltura no seu manexo, na parte III do seguinte curso pode observar como interactuar con Unity: [[Curso Platega: Ubuntu Desktop. Un sistema dual (MS Windows / GNU/Linux)]]<br />
<br />
== Instalación OpenJDK ==<br />
*Vaise instalar a versión 7.<br />
*En http://openjdk.java.net pódese obter máis información sobre esta plataforma.<br />
<br />
<gallery caption="Instalación OpenJDK" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_ubuntu_01.jpg| Unha posibilidade pode ser dende o Centro de Software.<br />
Image:Android_2013_ubuntu_02.jpg| Procurar OpenJDK.<br />
Image:Android_2013_ubuntu_03.jpg| Pódese marcar que se instale o paquete '''icedtea-X-plugin''' que é o plugin para os navegadores Web. Pero ...<br />
Image:Android_2013_ubuntu_04.jpg| ... vaise instalar dende o Terminal. Premer no botón de Inicio, procurar '''Terminal''' e lanzalo.<br />
Image:Android_2013_ubuntu_05.jpg| Con '''apt-cache search openjdk''' vense os paquetes dispoñibles. Entre eles, o mendionado '''icedtea-X-plugin''' e o metapaquete '''default-jdk''', que sempre vai instalar a versión máis recente do JDK de OpenJDK.<br />
Image:Android_2013_ubuntu_06.jpg| Executar '''sudo apt-get install default-jdk icedtea-7-plugin''' para instalar os dous paquetes.<br />
Image:Android_2013_ubuntu_07.jpg| Información sobre o que se vai instalar. Indicar que Si se desexa continuar.<br />
Image:Android_2013_ubuntu_08.jpg| Comprobación das versións do compilador de Java ('''javac -version''') e da MV de Java (JRE) ('''java -version''').<br />
</gallery><br />
<br />
== Instalación do IDE Eclipse ==<br />
*A continuación instalarase o IDE de Eclipse, cuxo proceso de instalación é simplemente descargar e descomprimir un paquete, sen máis.<br />
*En http://eclipse.org/ está o sitio do IDE.<br />
<br />
<br />
<gallery caption="Instalación IDE Eclipse" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_ubuntu_01.jpg| Unha posibilidade sería instalar Eclipse dende o Centro de Software.<br />
Image:Android_2013_ubuntu_09.jpg| Pero a versión do repositorio é a 3.8.1 e ...<br />
Image:Android_2013_ubuntu_10.jpg| En http://www.eclipse.org/downloads/ podemos atopar a última versión. A imaxe amosa a versión 4.3.1. Na actualiadade é a 4.4.1. Neste caso descárgase a versión de 64 bits do '''IDE de Java EE''' (Enterprise Edition) por ser máis completa cá do IDE de Java, pero con esta última tamén sería suficiente. Cada quen que baixe a versión de 64 ou 32 bits en función do seu S.O.<br />
Image:Android_2013_ubuntu_11.jpg| Descomprimir o ficheiro. '''Nota''': na versión 13.10 de Ubuntu dá un erro ao descomprimir este paquete dende o entorno gráfico.<br />
Image:Android_2013_ubuntu_12.jpg| Nese caso descomprimir con '''tar xf eclipse-jee.....'''.<br />
Image:Android_2013_ubuntu_13.jpg| Carpeta '''Eclipse''' que xa contén o IDE, listo ...<br />
Image:Android_2013_ubuntu_14.jpg| ... para traballar. Facer dobre click sobre o executable (asegurarse que teña permisos de execución).<br />
Image:Android_2013_ubuntu_15.jpg| Abríndose o IDE. Versión da imaxe: 4.3.1 (Kepler). Imaxe actual 4.4.1 (Luna)<br />
Image:Android_2013_ubuntu_16.jpg| Pregunta onde se desexan gardar os proxectos. <br />
Image:Android_2013_ubuntu_17.jpg| O IDE funcionando. Pero, pero !!!!! Só está dispoñible para o usuario que o baixou e non para os demais do sistema. Isto non é desexable nunha aula.<br />
</gallery><br />
<br />
===IDE Eclipse para tódolos usuarios===<br />
*Para que o IDE Eclipse estea dispoñible para tódolos usuarios do sistema, só é preciso poñer o cartafol Eclipse nunha ruta accesible por todo usuario. Neste caso vaise facer uso da máis recomendada '''/opt/eclipse'''.<br />
*Logo só resta axustar o propietario e os permisos do cartafol.<br />
*Pódese facer todo isto dende o contorno gráfico pero vaise realizar dende a consola con '''sudo'''.<br />
*Finalmente crearase un '''menú''' para que calquera usuario poida lanzar o IDE dende o Botón de Inicio do Lanzador.<br />
<br />
<gallery caption="Instalación IDE Eclipse para tódolos usuarios" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_ubuntu_18.jpg| Mover o cartafol eclipse: '''sudo mv Descargas/eclipse /opt/'''<br />
Image:Android_2013_ubuntu_19.jpg| Cambiar o usuario e o grupo propietario dese cartafol e o seu contido: '''sudo chown root:root /opt/eclipse -R'''<br />
Image:Android_2013_ubuntu_19.jpg| Dar permisos de control total ao propietario, aos demais usuarios de lectura e execución para ese cartafol e todo o seu contido: '''sudo chmod 755 /opt/eclipse -R'''<br />
Image:Android_2013_ubuntu_20.jpg| Un usuario normal podería ir ao cartafol '''/opt/eclipse''' e lanzar o IDE, pero mellor crear un menú.<br />
Image:Android_2013_ubuntu_21.jpg| Para iso hai que crear un lanzador (extensión desktop) en '''/usr/share/applications'''. Nese directorio están os lanzadores (menús) das demais aplicacións. Para iso creamos o ficheiro con '''gedit''' e executámolo como root: '''sudo gedit /usr/share/applications/Eclipse.desktop'''<br />
Image:Android_2013_ubuntu_22.jpg| Pegamos o contido que se amosa dúas imaxes máis abaixo, modificando as rutas se fose o caso.<br />
Image:Android_2013_ubuntu_23.jpg| Se agora se preme no botón Inicio xa se ve o Lanzador de Eclipse.<br />
Image:Android_2013_ubuntu_24.jpg| Tamén se pode lanzar Eclipse dende a consola. Como root hai que usar o comando '''sudo''', como usuario normal sen ''sudo''.<br />
</gallery><br />
<br />
<syntaxhighlight lang="bash" line highlight=""><br />
[Desktop Entry]<br />
Type=Application<br />
Name=Eclipse<br />
Comment=Eclipse Integrated Development Enviroment<br />
Exec=env UBUNTU_MENUPROXY= /opt/eclipse/eclipse<br />
Icon=/opt/eclipse/icon.xpm<br />
Categories=Development;IDE;Java;<br />
</syntaxhighlight><br />
<br />
'''NOTA:''' Na versión 13.10 de Ubuntu se non se engade en Exec '''env UBUNTU_MENUPROXY''' non se amosarían os menús da aplicación.<br />
<br />
== Instalación Android SDK ==<br />
*O proceso de instalación é semellante ao do IDE Eclipse: descargar un paquete e descomprimilo.<br />
*En http://developer.android.com/sdk/index.html#Other podemos comezar co proceso de instalación.<br />
*Poderíamos descargar o '''Bundle''' asociado ao noso SO e este xa traería integrado nun só paquete: Eclipse + Android SDK + Plugin ADT. Só restaría instalar o JRE (ou JDK se se desexa).<br />
**Poderíase configurar para que puidera ser usado por calquera usuario do sistema do mesmo xeito que se fixo antes con Eclipse e que se vai facer a continuación co SDK de Android.<br />
*Pero, como indicamos, vaise instalar cada compoñente por separado.<br />
<br />
<gallery caption="Instalación Android SDK" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_windows_29.jpg|En http://developer.android.com/sdk/index.html#Other poderemos descargar o '''SDK''' para Android. asociado ao noso SO. Neste caso baixarase o SDK para Linux, fixarse que a versión é a mesma para 32 bits que para 64 bits, co cal é probable que nas versións do SO de 64 bits haxa que instalar '''librarías de 32 bits''' que precisen os compoñentes do SDK para ser executadas.<br />
Image:Android_2013_ubuntu_27.jpg| Aceptamos as condicións e descargamos.<br />
Image:Android_2013_ubuntu_28.jpg| Descomprimimos o ficheiro. En modo gráfico ...<br />
Image:Android_2013_ubuntu_27A.jpg| ... ou por consola.<br />
</gallery><br />
<br />
*Agora xa teríamos unha carpeta co SDK, da que podería facer uso o usuario actual pero non todos os demais do sistema.<br />
*Por tanto, igual que se fixo antes con Eclipse para configuralo para tódolos usuarios, vaise proceder agora có SDK de Android.<br />
<br />
===Android SDK para tódolos usuarios ===<br />
* Igual que antes: poñer o SDK nunha ruta accesible para tódolos usuarios do sistema: '''/opt/android-sdk-linux'''.<br />
*Logo só resta axustar o propietario e os permisos do cartafol.<br />
*Pódese facer todo isto dende o contorno gráfico pero vaise realizar dende a consola con sudo. <br />
<br />
<gallery caption="Instalación Android SDK para tódolos usuarios" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_ubuntu_29.jpg| Mover o SDK: '''sudo mv Descargas/android-sdk-linux /opt/'''<br />
Image:Android_2013_ubuntu_30.jpg| Axustar os propietarios do cartafol e o seu contido: '''sudo chown root:root /opt/android-sdk-linux -R'''<br />
Image:Android_2013_ubuntu_30.jpg| Axustar os permisos ... '''sudo chmod 755 /opt/android-sdk-linux -R'''<br />
Image:Android_2013_ubuntu_32.jpg| O contido do cartafol /opt/android-sdk-linux<br />
Image:Android_2013_ubuntu_33.jpg| O contido do subcartafol '''tools'''. Hai un programa chamado '''android''' que permite, entre outras cousas, xestionar as APIs do SDK e os emuladores de dispositivos.<br />
Image:Android_2013_ubuntu_33A.jpg| Podemos executalo dende a consola, indicando a súa ruta. Con '''sudo''' é executado como root, e sen sudo como un usuario normal. '''/opt/android-sdk-linux/tools/android --help'''.<br />
Image:Android_2013_ubuntu_34.jpg| Como imos actualizar as APIs do SDK e descargar os seus compoñentes é preciso lanzar o '''Xestor do SDK (SDK Manager)''' como root: '''sudo /opt/android-sdk-linux/tools/android sdk'''. A opción ''sdk'' é a que se usa por defecto cando non se indica ningunha.<br />
Image:Android_2014_ubuntu_35.jpeg| Se se preme na imaxe verase en tamaño real, e poderá apreciarse, que aínda non está o SDK listo para poder crear o noso primeiro programa: precísanse compoñentes que xa marca por defecto o xestor: Unha API (marca por defecto as últimas, a 5.1.1 e M) e compoñentes básicos (na imaxe veñen marcadas outras por ser unha versión anterior).<br />
Image:Android_2013_windows_52.jpg| Neste caso, como xa se indicou nun apartado anterior, vanse descargar a API 16 asociada á versión de Android 4.1.2 e se desexa as 5.1.1 e M. Lembrar que estas dúas últimas APIS ocupan uns 6 GiB.<br />
Image:Android_2013_ubuntu_37.jpg| Aceptar as licencias dos compoñentes.<br />
Image:Android_2013_ubuntu_38.jpg| Ollo!!! que abaixo hai máis licencias para aceptar. E premer en '''Install'''<br />
Image:Android_2013_ubuntu_39.jpg| Comezo da descarga. Da un erro de que non pode parar o servidor ADB. Este compoñente verase nun apartado posterior.<br />
Image:Android_2013_ubuntu_40.jpg| Continúa a descarga.<br />
Image:Android_2013_ubuntu_41.jpg| Erro de que non pode iniciar o servidor ADB, e isto si que é un problema. Isto pasa nas versión de 64 bits de Ubuntu 13.10, porque para iniciarse ese servidor precisa unhas librarías de 32 bits que non están instaladas. Logo arranxarase.<br />
Image:Android_2013_ubuntu_42.jpg| Compoñentes do SDK instalados.<br />
Image:Android_2013_ubuntu_78.jpg| Carpetas creadas e asociadas ao SDK.<br />
</gallery><br />
<br />
<br />
'''NOTA:''': Cando decidimos instalar unha nova versión do S.O. Android non é necesario marcar todas as opcións dentro desta API. Así:<br />
:* SDK: Necesario para poder desenvolver a aplicación. Sempre debe ser marcada.<br />
:* Samples for SDK: Documentación de exemplo. Non é necesario marcala.<br />
:* System Image (ARM/Intel/MIPS): Cando máis adiante utilicemos un dispositivo virtual para correr as nosas aplicacións, será necesario ter descargado a lo menos unha destas imaxes. O normal é que se temos un procesador INTEL descarguemos unha imaxe INTEL xa que despois poderemos instalar un acelerador hardware para dito micro. Se non temos intel poderíamos descargar calquera das opcións.<br />
:* Google API: O mesmo que o System Image pero para dar soporte a aplicacións que van facer uso de Google Maps. Se non imos traballar con el non será necesario descargalas.<br />
:* Sources for Android SDK: Fontes das funcións do SDK. Non é necesario descargalas.<br />
<br />
==Instalación plugin ADT==<br />
*Só resta instalar o plugin en Eclipse que permita traballar dende este IDE co SDK de Android.<br />
*Este plugin chámase: '''Android Development Tools (ADT)''' e estende as capacidades de Eclipse para xestionar dispositivos móviles (emulados e reais), compilar e instalar aplicacións en dispositivos, etc.<br />
*En http://developer.android.com/tools/sdk/eclipse-adt.html hai máis información sobre este compoñente e como se pode instalar no IDE.<br />
<br />
<gallery caption="Instalación ADT Plugin" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_ubuntu_45.jpg| En http://developer.android.com/tools/sdk/eclipse-adt.html premer en '''Installing the Eclipse Plugin'''<br />
Image:Android_2013_ubuntu_46.jpg| En http://developer.android.com/sdk/installing/installing-adt.html indica que podemos instalar o Plugin de dúas formas:<br />
Image:Android_2013_ubuntu_47.jpg| Unha descargando o paquete e logo instalalo dende Eclipse ...<br />
Image:Android_2013_ubuntu_48.jpg| ... ou copiar o enlace ao repositorio no que se atopa o plugin ADT: https://dl-ssl.google.com/android/eclipse/. Usaremos esta forma.<br />
Image:Android_2013_ubuntu_43.jpg| Lanzar eclipse como root.<br />
Image:Android_2013_ubuntu_44.jpg| Premer en '''Help -> Install New Software...'''<br />
Image:Android_2013_ubuntu_49.jpg| Pegar o repositorio ... Premer en '''Add'''.<br />
Image:Android_2013_ubuntu_50.jpg| Poñer un nome ao repositorio, neste caso '''ADT'''.<br />
Image:Android_2013_ubuntu_51.jpg| Amosa os compoñentes que se van instalar. Na última versión do ADT só hai un compoñente. O compoñente '''NDK: Native Development Kit''' era para desenvolver aplicacións en linguaxe nativa como C ou C++. Máis información: http://developer.android.com/tools/sdk/ndk/index.html<br />
Image:Android_2013_ubuntu_52.jpg| Dentro dos compoñentes de '''Developer Tools''' hai outros como '''DDMS''' que se verá nun apartado posterior.<br />
Image:Android_2013_ubuntu_53.jpg| Unha vez marcado todo premer en '''Next'''.<br />
Image:Android_2013_ubuntu_54.jpg| Premer en '''Next'''.<br />
Image:Android_2013_ubuntu_55.jpg| Aceptar a licencia.<br />
Image:Android_2013_ubuntu_56.jpg| Proceso de descarga e instalación dos paquetes.<br />
Image:Android_2013_ubuntu_57.jpg| Aceptar a advertencia que indica que hai software sen asinar.<br />
Image:Android_2013_ubuntu_58.jpg| Reiniciar eclipse cando remate a instalación do plugin.<br />
Image:Android_2013_ubuntu_59.jpg| Advertencia que indica que non se atopa a ruta do SDK de Android. Pechar.<br />
Image:Android_2013_ubuntu_60.jpg| Unha vez instalado o Plugin ADT en Eclipse este permítenos que instalemos un novo SDK de Android descargándoo dende cero, ou usar un xa instalado. Escoller esta segunda opción e indicar a ruta '''/opt/android-sdk-linux'''<br />
Image:Android_2013_ubuntu_61.jpg| Indicar se se desexa participar nas estadísticas de Google.<br />
Image:Android_2013_ubuntu_62.jpg| Na versión de Ubuntu de 13.10 de 64bits aparecen varios erros que fan mención o problema que se tiña antes co compoñente ADB. Este servizo é lanzado polo plugin ADT para poder usarse no DDMS como se verá máis tarde.<br />
Image:Android_2013_ubuntu_62A.jpg| ... aquí indica que precisa unha libraría que non ten.<br />
Image:Android_2013_ubuntu_63.jpg| Entramos igualmente en Eclipse ...<br />
Image:Android_2013_ubuntu_64.jpg| E vemos dous erros na parte inferior avisando do mesmo.<br />
</gallery><br />
<br />
==Librarías de 32 bits precisas para Ubuntu 13.10 Linux de 64 bits==<br />
*Se o lector está usando unha versión de Ubuntu de 32 bits xa pode pasar ao seguinte punto.<br />
*Como se viu antes o SDK de Android era válido para as versións de 32bits e 64bits, pero se estamos nun SO de 64 bits, este non ten instaladas algunhas librarías de 32 bits que precisan algúns compoñentes do SDK, por exemplo o ADB.<br />
*O '''Android Debug Bridge (ADB)''' é un comando que arranca un servidor que nos vai permitir comunicarnos e interactuar cos dispositivos físicos ou emulados. <br />
* O ADB verase con profundidade nun apartado posterior, por agora so interesa que se poida executar.<br />
* No enlace hai máis información: http://developer.android.com/tools/help/adb.html<br />
<br />
<gallery caption="Instalación libraría 32 bits" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_ubuntu_65.jpg| Este compoñente atópase na ruta do SDK en: '''/opt/android-sdk-linux/platform-tools/adb'''. Ao executalo vese que nos indica un erro cunha libraría.<br />
Image:Android_2013_ubuntu_66.jpg| Instalamos a libraría, pero de 32 bits, como root: '''sudo apt-get install lib32stdc++6'''<br />
Image:Android_2013_ubuntu_67.jpg| Executamos de novo o comando: '''/opt/android-sdk-linux/platform-tools/adb''' e xa amosa a axuda do comando.<br />
</gallery><br />
<br />
*Agora xa podemos iniciar Eclipse que non se terá ningún problema co ADB nunha versión linux de 64 bits.<br />
*Aínda hai que instalar algunha libraría máis de 32 bits, pero imos esperar a que xurda o erro.<br />
<br />
==Configuración Eclipse e plugin ADT. Actualizacións==<br />
*Agora xa podemos iniciar eclipse sen problemas e imos ver:<br />
**Parámetros de configuración de Eclipse.<br />
**Como actualizar Eclipse ou o SDK de Android.<br />
**Que elementos engadiu o plugin ADT á Perspectiva Java de Eclipse.<br />
***Unha '''Perspectiva''' é unha combinación de pantallas para facilitar o desenvolvemento de aplicacións de distintos tipos.<br />
***Aconséllase que se lle bote un ollo a: '''"Mi primera hora con Eclipse"''': http://ubuntulife.files.wordpress.com/2008/03/intro_eclipse_espanol.pdf<br />
<br />
<br />
<br />
<gallery caption="Preferencias" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_ubuntu_68.jpg| Premer en '''Window -> Preferences'''.<br />
Image:Android_2013_ubuntu_70.jpg| Na categoría '''Android''' pódese ver a ruta do SDK, se esta se perdera, con vir a esta preferencia xa se podería configurar.<br />
Image:Android_2013_ubuntu_69.jpg| A versión do compilador JDK que vai usar o IDE.<br />
Image:Android_2013_ubuntu_69A.jpg| A versión do JRE e a súa ruta.<br />
</gallery><br />
<br />
<br />
<br />
<gallery caption="Actualizacións" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_ubuntu_71.jpg| Hai que lanzar o Eclipse como root (sudo /opt/eclipse/eclipse). En '''Help -> Check for Updates'''. <br />
Image:Android_2013_ubuntu_72.jpg| Comprobando se hai actualizacións do IDE.<br />
Image:Android_2013_ubuntu_73.jpg| Non hai actualizacións.<br />
</gallery><br />
<br />
<br />
<br />
<gallery caption="Perspectiva Java" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_ubuntu_74A.jpg|A combinación de ventás (Perspectiva) que se ve é a que se denomina Java EE<br />
Image:Android_2013_ubuntu_74.jpg| Pero ADT instalou compoñentes na Perspectiva Java. Premer en '''Window -> Open Perspective -> Java'''<br />
Image:Android_2013_ubuntu_75.jpg| Aparecen novas iconas, entre elas, o '''Android SDK Manager''' e o Xestor de Dispositivos Virtuais.<br />
Image:Android_2013_ubuntu_75A.jpg| O mesmo pasa se se preme en '''Window'''<br />
Image:Android_2013_ubuntu_76.jpg| Dende o propio Eclipse, o plugin proporciona un enlace ao comando que chama ao '''Xestor de SDK de Android''', que estaba na ruta: '''/opt/android-sdk-linux/tools/android sdk'''. Dende aquí poderíanse instalar/desinstalar compoñentes e incluso actualizalos. Pero hai que iniciar o Eclipse como '''root''': '''sudo /opt/eclipse/eclipse'''. Non o pode facer un usuario normal (ben, salvo que en /opt/android-sdk-linux se lle dean permisos de escritura a todo o mundo).<br />
</gallery><br />
<br />
==Carpetas de traballo==<br />
*As carpetas que se obteñen finalmente pertencen a 2 tipos:<br />
**'''Carpetas de programas''':<br />
***'''/opt/eclipse''': Eclipse + plugin ADT<br />
***'''/opt/android-sdk-linux''': Android SDK <br />
**'''Carpetas de configuración de usuario'''<br />
***'''/home usuario/.eclipse''': Carpeta oculta. Contén arquivos de configuración relativos a ese usuario e ao IDE Eclipse.<br />
***'''/ruta/workspace''': Carpeta indicada polo usuario onde se van gardar os proxectos creados no IDE Eclipse.<br />
***'''/home usuario/.android''': Carpeta oculta. Contén arquivos de configuración relativos ao SDK de Android e onde se van gardar os emuladores de dispositivos móbiles (AVDs) que cree o usuario.<br />
<br />
<br />
<br />
*Dende a sesión do usuario co que se estaba no sistema se estivo executando Eclipse e o SDK de Android como root, aconsellamos, para que non haxa problemas con permisos, que se borren as tres carpetas asociadas á configuración do usuario. Puidera ser o caso de que xa non existiran esa carpetas, pero é mellor asegurarse.<br />
<br />
[[Image:Android_2013_ubuntu_77.jpg|500px]]<br />
<br />
==Fixar a icona ao Lanzador==<br />
*Unha forma de facilitar o acceso a eclipse pode ser fixando a icona ao Lanzador.<br />
*Hai varias formas de facelo, unha delas é a seguinte, unha vez que se ten o localizado na Lente de Incio, arrastralo ate a barra do Lanzador.<br />
<br />
<gallery caption="Fixar icona ao Lanzador" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_avd_01.jpg|<br />
Image:Android_2013_avd_01A.jpg|<br />
</gallery><br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=LIBGDX_A_c%C3%A1mara_2D&diff=57383LIBGDX A cámara 2D2015-10-03T22:06:10Z<p>Angelfg: /* Facendo zoom */</p>
<hr />
<div><span style="font-size:150%;">UNIDADE 2: A cámara 2D. Cámara ortográfica.</span><br />
<br />
<br />
==A cámara 2D==<br />
<br />
<br />
[[Imagen:LIBGDX_xogos2d_desenrolo_8.jpg|400px|center]]<br />
<br />
===Introducción===<br />
<br />
Temos que entender que todo o que se visualiza nun xogo son puntos nun espazo. No caso dos xogos 2D estamos falando de coordenadas X,Y (Z que sería a profundidade ten un valor de 0)<br />
<br />
Cando nos indicamos que queremos ver algo na coordenada (x=10,Y=15) vai existir unha cámara que vai 'transformar' esas coordenadas a coordenadas do noso dispositivo móbil ou pantalla de PC e fará que se visualice no lugar correcto. A cámara vai ter unha posición e un tamaño (área que vai visualizar). <br />
<br />
Todos estes datos son aplicados a cada un dos puntos que queremos debuxar en forma dunha serie de operacións matemáticas usando matrices. En OPEN GL existen dúas matrices que veremos en profundidade na parte 3D. Unha matriz vai a establecer o tamaño do que se visualiza (matriz de proxección) e outra vai establecer a posición da cámara e cara a onde mira, é dicir, a súa dirección (matriz de modelado). Se xuntamos as dúas matrices obtemos unha matriz combinada que vai ser a que se aplique a cada un dos puntos do noso xogo.<br />
<br />
<br />
Cunha cámara poderemos:<br />
*Mover ou rotar a cámara: propiedade '''location''' / método '''translate''' e método '''rotate'''<br />
*Facer zoom ou afastarse: método '''zoom'''<br />
*Cambiar o tamaño do que visualiza a cámara: propiedades '''viewportwidth''' e '''viewportheight'''<br />
*Pasar coordenadas de puntos dende o dispositivo real a coordenadas da cámara e viceversa: método '''unproject''' e '''project'''. <br />
<br />
Existen outros métodos e propiedades que iremos vendo cando o necesitemos.<br />
<br />
===Cámara ortográfica===<br />
<br />
*Clase '''OrthographicCamera''': http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/OrthographicCamera.html<br />
<br />
*Deriva da clase [http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/Camera.html Camera]<br />
<br />
A cámara que se usa nos xogos 2D denomínase cámara ortográfica (orthographic camera). A diferenza da cámara 3D (que se denomina cámara en perspectiva ou perspective camera) esta non ten perspectiva. <br />
<br />
'''Nota:''' A partires de agora podemos utilizar tipos de datos Vector2. Tedes unha descrición [http://informatica.iessanclemente.net/manuais/index.php/LIBGDX_Anexo_tipos_de_datos neste enlace]. <br />
<br />
En 3D os obxectos mais afastados vense máis pequenos que os próximos.<br />
<br />
Por exemplo:<br />
<br />
[[Imagen:LIBGDX_xogos2d_desenrolo_9.jpg | 400px | center]]<br />
<br />
*Neste exemplo estamos a visualizar os mesmos obxectos (dous triángulos) situados na mesma posición nos dous casos. A diferenza é que a cámara ortográfica non ten en conta a distancia/perspectiva.<br />
<br />
<br />
<br />
<br />
:Métodos máis importantes:<br />
::*'''[http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/OrthographicCamera.html#setToOrtho%28boolean%29 public void setToOrtho(boolean yDown,float viewportWidth, float viewportHeight)]'''<br />
:::Define o tamaño do [http://informatica.iessanclemente.net/manuais/index.php/Archivo:LIBGDX_xogos2d_desenrolo_8.jpg viewport da cámara]. <br />
:::*ydown: indica se o punto (0,0) está situado na parte superior esquerda (valor true) ou na parte inferior esquerda (valor false)<br />
:::*viewportWidth: ancho do viewport.<br />
:::*viewportHeight: alto do viewport.<br />
::*'''[http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/OrthographicCamera.html#update%28%29 public void update()]'''<br />
:::Actualiza a matriz de proxeción e de modelado.<br />
::*'''[http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/Camera.html#project%28com.badlogic.gdx.math.Vector3%29 public Vector3 project(Vector3 worldCoords)]'''<br />
:::Pasa as coordenadas do mundo a coordenadas da pantalla.<br />
:::*worldCoords: coordenadas do mundo.<br />
::*'''[http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/Camera.html#unproject%28com.badlogic.gdx.math.Vector3%29 public Vector3 unproject(Vector3 ScreenCoords)]'''<br />
:::Pasa as coordenadas de pantalla a coordenadas do noso mundo.<br />
:::*screenCoords: coordenadas de pantalla.<br />
<br />
<br />
<br />
<br />
Definiremos por tanto a cámara no noso xogo.<br />
<br />
'''Código da clase RendererXogo:'''<br />
<syntaxhighlight lang="java" line enclose="div" highlight="3,6" ><br />
public class RendererXogo {<br />
<br />
private OrthographicCamera camara2d;<br />
<br />
public RendererXogo(){<br />
camara2d = new OrthographicCamera();<br />
}<br />
<br />
<br />
......<br />
</syntaxhighlight><br />
<br />
<br />
Agora temos que darlle un tamaño. O tamaño (width e height) da cámara é o que se coñece como '''VIEWPORT'''. No seguinte debuxo se corresponde co '''plano near'''.<br />
<br />
[[Imagen:LIBGDX_xogos2d_desenrolo_8.jpg|400px|center]]<br />
<br />
<br />
Os raios indican como nos vemos os obxectos con dita cámara. Temos que imaxinar un encerado e pensar que todo o que vemos vaise 'esmagar' contra dito encerado. É como se leváramos fisicamente os obxectos ata o encerado e os esmagamos. Por iso os obxectos non teñen perspectiva con dita cámara.<br />
<br />
<br />
Cando definimos unha cámara definimos o tamaño do plano near (viewport width e viewport height) que é igual ó tamaño do plano far . Ó ser unha cámara ortográfica o tamaño dos dous planos é o mesmo sempre. A distancia entre os dous planos é o que se coñece como '''VIEW FRUSTRUM''' e ven ser o volume de visualización. Todo o que está dentro deste volume é o que se verá. Este volume está definido polas propiedades far e near da cámara e veñen a representar a distancia á cámara.<br />
<br />
[[Imagen:LIBGDX_xogos2d_desenrolo_10.jpg|400px|center]]<br />
<center>[http://www.elai.upm.es/webantigua/spain/Asignaturas/InfoInd/teoria/Apuntes%20de%20OpenGL.pdf Imaxe obtida dos apuntes de Cristina Cañero Morales]</center><br />
<br />
<br />
No caso da cámara 2D estes xa teñen uns valores por defecto. Asi o plano far é 100, o plano near é 0 e o tamaño o temos que asinar nos. <br />
<br />
Todos os gráficos os imos debuxar no plano near. Tanto daría o lonxe que os debuxaramos xa que mentres estiveran dentro do plano far se verían igual.<br />
<br />
===O tamaño da pantalla. A relación de aspecto===<br />
<br />
Un dos primeiros problemas a que nos temos que enfrontar cando deseñamos un xogo é determinar a que resolución imos dirixir o noso xogo e cal vai ser a [http://es.wikipedia.org/wiki/Relaci%C3%B3n_de_aspecto relación de aspecto da pantalla].<br />
<br />
A relación de aspecto é a relación entre o seu ancho e o seu alto. Normalmente se dividen e o resultado representa cuanto máis ancho é a pantalla con respecto o seu alto.<br />
<br />
<br />
*Agora que queda claro o que é e que representa a relación de aspecto temos que aprender outro concepto.<br />
<br />
Cando definimos unha cámara e o seu tamaño (viewport) estamos definindo un tamaño 'ficticio' que non ten por que corresponderse coa resolución da pantalla do noso dispositivo. Así eu podo definir un tamaño para o meu xogo de 400x200 unidades (fixarvos que digo unidades, non pixeles). O que vai facer a cámara é '''proxectar''' o punto á resolución correspondente.<br />
<br />
[[Image:LIBGDX_xogos2d_desenrolo_16.jpg|thumb|center|400px|Nesta pantalla cunha resolución de 400x200 unidades o punto central estaría na coordenada 200x100. O que vai facer a cámara é proxectar este punto ó sistema de coordenadas do noso dispositivo]]<br />
<br />
<br />
*Que vantaxes temos se non cambiamos o tamaño do noso Viewport en función da resolución do dispositivo ?<br />
:Pois que se colocamos algo no punto central este estará no centro en todas as resolucións de todos os dispositivos...<br />
<br />
*Desvantaxes: Perdemos a relación de aspecto. <br />
:Por exemplo, temos como no exemplo anterior definido o noso xogo cun tamaño de 400x200 unidades. O noso gráfico ocupa 200 unidades de ancho (a metade do ancho total) e 100 unidades de alto (a metade do alto total). <br />
:Proxectemos estes datos a un dispositivo cunha resolución de 600x600 pixeles...<br />
::Relación de aspecto do gráfico na cámara (no viewport) 200/100=2 (o seu ancho é o dobre do seu alto)<br />
<br />
::Se trasladamos estes puntos a unha resolución de 600x600 pixeles:<br />
:::Ancho debe ocupar a metade: 600/2 = 300 pixeles de ancho.<br />
:::Alto debe ocupar a metade: 600/2 = 300 pixeles de alto.<br />
:::Relación de aspecto no dispositivo: 300/300=1. Ten o mesmo alto que ancho e polo tanto sairía deformado.<br />
<br />
O veremos máis adiante cun exemplo gráfico e a súa posible solución...<br />
<br />
<br />
Outro problema que xurde se cambiamos o tamaño do viewport en función do tamaño da resolución é o seguinte:<br />
<br />
O tamaño da pantalla pode variar xa que varía a resolución da mesma. Se aplicamos como tamaño<br />
do noso xogo dita resolución non poderemos posicionar de forma absoluta os nosos protagonistas, xa<br />
que se por exemplo:<br />
<br />
<br />
[[Image:LIBGDX_xogos2d_desenrolo_11.jpg|thumb|400px|center|Nesta pantalla cunha resolución de 400x200 o punto central estaría na coordenada 200x100.]]<br />
<br />
<br />
<br />
Cambiemos de resolución:<br />
<br />
[[Image:LIBGDX_xogos2d_desenrolo_12.jpg|thumb|400px|center|Resolución da pantalla cambia a 800x400 e punto 200x100]]<br />
<br />
Como vemos a posición non é a mesma.<br />
<br />
<br />
Para evitalo temos varias aproximacións. <br />
<br />
*Se modificamos o tamaño do viewport e a axustamos á resolución do dispositivo, podemos establecer unha unidade de medida definida por nos, no exemplo anterior definiríamos o noso mundo cunha resolución de 400x200 unidades (viewport). Se cambiamos de resolución determinamos cantos pixeles por unidade temos no eixe x (ppux) e cantos no eixe y (ppuy).<br />
<br />
: Así, no caso anterior:<br />
::ppux = 800/400 = 2<br />
::ppuy = 400/200 = 2<br />
<br />
: Quere dicir que cando queiramos debuxar algo no punto 200,100 teríamos que multiplicalo por ppux e ppuy respectivamente dándonos o punto central da nova resolución (200x2,100x2) = (400,200). O mesmo principio o poderíamos aplicar o tamaño dos gráficos para que tiveran a mesma relación de aspecto.<br />
<br />
<br />
*Outra aproximación podería ser ampliar o tamaño do viewport en función da relación de aspecto.<br />
Isto o explicaremos co seguinte exemplo. Imaxinemos que definimos un viewport para a cámara de 600x600 unidades....Se proxectamos estas unidades a un dispositivo coa mesma resolución (600x600 pixeles) quedaría así:<br />
<br />
[[Image:LIBGDX_xogos2d_desenrolo_13.jpg|thumb|400px|center|Gráfico de tamaño 200x200 unidades nun viewport de 600x600 unidades nunha pantalla de 600x600 pixeles]]<br />
<br />
Fixarse como o ancho do gráfico ocupa unha terceira parte do ancho total....<br />
<br />
Se agora aumentamos o ancho da pantalla a 800x480 pixeles podemos comprobar como o gráfico perde a relación de aspecto.<br />
<br />
[[Image:LIBGDX_xogos2d_desenrolo_14.jpg|thumb|400px|center|Gráfico de tamaño 200x200 unidades nun viewport de 600x600 unidades nunha pantalla de 800x480 pixeles]]<br />
<br />
Agora o gráfico mide de ancho 266 pixeles fronte os 200 pixeles que tiña nun dispositivo de 600x600 pixeles de resolución...Isto o sabemos facendo unha regra de tres: se 600 unidades son 800 pixeles, 200 unidades son...<br />
Polo tanto o seu ancho vai ser maior que o seu alto.<br />
Para evitalo poderíamos calcular a relación de aspecto do dispositivo:<br />
<br />
:Relación de aspecto: 800/480 = 1,666. Isto quere dicir que o ancho é 1,666 veces maior que o seu ancho.<br />
<br />
:E definimos o viewport da cámara, en vez de 600x600 unidades con 600*relacion_aspectox600 unidades = 1000x600 unidades que serán proxectadas nun dispositivo de 800x480pixeles.<br />
<br />
Dará como resultado o seguinte:<br />
<br />
[[Image:LIBGDX_xogos2d_desenrolo_15.jpg|thumb|400px|center|ViewPort modificado a 1000x600 unidades para manter a relación de aspecto nun dispositivo de 800x480 pixeles]]<br />
<br />
Como vemos aumentamos o ancho de visualización do noso mundo. Isto pode non importar dependendo do tipo de xogo, como por exemplo un de tipo scroll como [http://replicaisland.net/ Replica Island], e non nos importa que un xogador vexa máis 'terreo' do noso xogo que outro dependendo da resolución.<br />
<br />
<br />
<br />
<br />
Existen moitos artigos que dan diferentes solucións ó problema:<br />
*http://blog.gemserk.com/2013/01/22/our-solution-to-handle-multiple-screen-sizes-in-android-part-one/<br />
*http://www.acamara.es/blog/2012/02/keep-screen-aspect-ratio-with-different-resolutions-using-libgdx/<br />
*http://www.badlogicgames.com/forum/viewtopic.php?f=11&t=860&p=4965<br />
<br />
<br />
No noso caso imos utilizar un tamaño fixo (independente da resolución) para o noso mundo e imos facer que todas as resolucións se axusten a dito tamaño. Se cambia a resolución do dispositivo este tamaño 'inventado' mantense e é a cámara a que fai os cálculos para debuxar os puntos no sitio correcto.<br />
<br />
Desta forma esquecemos o problema do posicionamento e teremos o problema de que os gráficos poden saír algo deformados.<br />
<br />
<br />
A forma de establecer o tamaño da cámara (viewport):<br />
<br />
*'''Propiedade viewportwidth''': ancho da cámara.<br />
*'''Propiedade viewportheight''': alto da cámara.<br />
<br />
Normalmente se fai uso do método:<br />
<br />
*'''public void setToOrtho(boolean yDown,float viewportWidth, float viewportHeight)''' <br />
<br />
:Define o tamaño do viewport da cámara. <br />
:Parámetros:<br />
::ydown: indica se o punto (0,0) está situado na parte superior esquerda (valor true) ou na parte inferior esquerda (valor false)<br />
::viewportWidth: ancho do viewport.<br />
::viewportHeight: alto do viewport. <br />
<br />
<br />
*<u><b>IMPORTANTE:</b></u> Despois de facer calquera cambio na cámara (posición, tamaño,...) hai que chamar ó método '''update()''' para que actualice as matrices de proxección e modelado.<br />
<br />
O método onde normalmente se establece o seu tamaño é o resize.<br />
<br />
No noso caso:<br />
<br />
Creamos un paquete novo de nome '''com.plategaxogo2d.modelo''' (axustade o nome ó voso caso) e definimos unha clase Mundo.<br />
En dita clase Mundo imos definir todo o que forma o noso xogo e definiremos o tamaño do noso mundo (o xogo). <br />
<br />
*<b>Un caso práctico</b><br />
No meu caso vou desenvolver un xogo para unha resolución de 600x1000 pixeles. <br />
Isto da unha relación de aspecto de 600/1000 = 0,6. <br />
Como non quero crear un mundo tan grande, utilizo un ancho e alto máis pequeno pero coa mesma relación de aspecto, por exemplo 300x500 unidades (300/500=0,6).<br />
<br />
Imos poñer un tamaño de 300x500 unidades para o noso xogo.<br />
<br />
Definiremos dúas propiedades de clase públicas de nomes TAMAÑO_MUNDO_ANCHO, TAMAÑO_MUNDO_ALTO.<br />
<br />
<br />
'''Código da clase Mundo:'''<br />
<syntaxhighlight lang="java" line enclose="div"><br />
package com.plategaxogo2d.modelo;<br />
<br />
public class Mundo {<br />
<br />
public static final int TAMANO_MUNDO_ANCHO=300;<br />
public static final int TAMANO_MUNDO_ALTO=500;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Definimos agora o tamaño da cámara 2D no noso xogo:<br />
<br />
'''Código da clase RendererXogo:'''<br />
<syntaxhighlight lang="java" line enclose="div" highlight="3,4" ><br />
public void resize(int width, int height) {<br />
<br />
camara2d.setToOrtho(false,Mundo.TAMANO_MUNDO_ANCHO,Mundo.TAMANO_MUNDO_ALTO);<br />
camara2d.update();<br />
<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
-----<br />
'''TAREFA 2.2 A FACER:''' Esta parte está asociada á realización dunha tarefa. <br />
-----<br />
<br />
Fixarse que para debuxar algo que ocupe todo a pantalla necesitaremos 300x500 unidades. A cámara xa se encargará de ''proxectar'' esas unidades ficticias a pixeles de resolución de pantalla, que poden ser 800x600, 1024x768....<br />
<br />
<br />
Para ver como queda só temos que modificar o arquivo de configuración da versión Desktop e asinarlle un ancho de 600 pixeles e un alto de 1000 pixeles (vos facédeo segundo a tarefa).<br />
<br />
===Movendo a cámara===<br />
<br />
<u><b>Preparación:</b></u> Agora ides facer unha copia da clase RendererXogo, xa que imos modificala para amosarvos como se pode mover a cámara. Premede co rato sobre a clase, botón dereito e escollede a opción Copy. Despois repetides a operación pero escolledes a opción Paste. Vos preguntará un nome para a clase. Indicade '''UD2_1_RendererXogo'''. <br />
<br />
Modificade a pantalla PantallaXogo para que chame a esta clase. Isto se fai modificando as liñas indicadas:<br />
<br />
'''Código da clase PantallaXogo:'''<br />
<br/>Obxectivo:Facer que se visualice o render da clase UD2_1_RendererXogo.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="4,9"><br />
public class PantallaXogo implements Screen {<br />
<br />
private MeuXogoGame meuxogogame;<br />
private UD2_1_RendererXogo rendererxogo;<br />
<br />
public PantallaXogo(MeuXogoGame meuxogogame) {<br />
<br />
this.meuxogogame = meuxogogame;<br />
rendererxogo = new UD2_1_RendererXogo();<br />
}<br />
</syntaxhighlight><br />
<br />
<br/><u>Nota:</u> Lembrar de premer a combinación de teclas Control+Shift+O para importar a clase.<br />
<br/><br />
<br />
<br />
O problema que temos é que para que se vexa que se move a cámara necesitamos cargar algún gráfico. Isto vai ser explicado no seguinte punto.<br />
<br />
Agora imos indicar o código necesario para cargar o gráfico no centro da pantalla (xa explicaremos logo o que estamos a facer).<br />
<br />
'''Código da clase UD2_1_RendererXogo:'''<br/>Obxectivo:Explica cales son os métodos que temos para mover a cámara.<br />
<syntaxhighlight lang="java" line enclose="div"><br />
package com.plategaxogo2d.renderer;<br />
<br />
import com.badlogic.gdx.Gdx;<br />
import com.badlogic.gdx.graphics.GL20;<br />
import com.badlogic.gdx.graphics.OrthographicCamera;<br />
import com.badlogic.gdx.graphics.Texture;<br />
import com.badlogic.gdx.graphics.g2d.SpriteBatch;<br />
import com.plategaxogo2d.modelo.Mundo;<br />
<br />
public class UD2_1_RendererXogo {<br />
<br />
private Texture grafico;<br />
private SpriteBatch spritebatch;<br />
<br />
private OrthographicCamera camara2d;<br />
<br />
<br />
<br />
public UD2_1_RendererXogo() {<br />
camara2d = new OrthographicCamera();<br />
grafico = new Texture(Gdx.files.internal("badlogic.jpg"));<br />
spritebatch = new SpriteBatch();<br />
} <br />
<br />
<br />
/**<br />
* Debuxa todos os elementos gráficos da pantalla<br />
* @param delta: tempo que pasa entre un frame e o seguinte.<br />
*/<br />
public void render(float delta){<br />
Gdx.gl.glClearColor(1, 1, 1, 1);<br />
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);<br />
<br />
spritebatch.begin();<br />
spritebatch.draw(grafico,camara2d.viewportWidth/2,camara2d.viewportHeight/2,50,50);<br />
spritebatch.end();<br />
<br />
}<br />
<br />
public void resize(int width, int height) {<br />
<br />
camara2d.setToOrtho(false,Mundo.TAMANO_MUNDO_ANCHO,Mundo.TAMANO_MUNDO_ALTO);<br />
camara2d.update();<br />
<br />
spritebatch.setProjectionMatrix(camara2d.combined);<br />
<br />
}<br />
public void dispose(){<br />
spritebatch.dispose();<br />
grafico.dispose();<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
Neste punto o único que nos interesa é o visto ata do agora e saber que no método render se está chamando de forma continua e estamos borrando a pantalla (liñas 31 e 32) e debuxando un gráfico (liñas 34-36).<br />
A liña que debuxa a gráfico (liñá 35) chama o método draw do spritebach e recibe catro parámetros: posición x, posición y, tamaño y e tamaño y.<br />
<br />
A cámara está situada por defecto no punto medio do viewport. No exemplo estaría no punto (150x250) que é onde estamos a colocar o gráfico (Texture).<br />
<br />
Se executamos a versión desktop aparecerá o seguinte:<br />
<br />
[[Imagen:LIBGDX_UD2_5_a_camara2d_1.jpg|thumb|center|x400px|Viewport de 300x500 unidades para manter a relación de aspecto dun dispositivo móbil de 480x800 pixeles.]]<br />
<br />
<br />
Para movela dispoñemos dos seguinte métodos:<br />
<br />
::*[http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/OrthographicCamera.html#translate(float,%20float) Método translate]:<br />
::*'''public void translate(Vector2 vec)'''<br />
::*'''public void translate(float x,float y) '''<br />
::Traslada a cámara á posición indicada por x,y. A traslada sumando ó valor da súa posición o valor indicado.<br />
<br />
::*[http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/Camera.html#position Método position]:<br />
::*Devolve un vector3 co que podemos indicar a nova posición da cámara. Debemos de chamar ó método '''set''' da clase Vector3 para asinarlle un novo valor. A posición z será 0 normalmente.<br />
<br />
::*[http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/OrthographicCamera.html#rotate(float) Método rotate]: <br />
::*Rota a cámara o ángulo indicado no vector de dirección. Varias aclaracións:<br />
:::*O ángulo se lle suma ó que xa ten. Quere isto dicir que se o ángulo de cámara é de 90 grados e chamamos a dito método cun valor de 5. Cada vez que o chamemos sumará 5 ó valor anterior. No exemplo sería 95 grados. <br />
:::*A rotación a fai sobre o eixe que ten o vector dirección da cámara. O vector dirección é un vector que indica cara a onde está apuntando a cámara. Por defecto '''coincide co eixe z''' do sistema de coordenadas (x,y,z). É o mesmo eixe que se corresponde cos teus ollos mirando a pantalla. Se imaxinas unha liña que atravesa a túa cabeza e vai cara ó computador, se xiras a cabeza no eixe indicado terás o seguinte efecto:<br />
<br />
<br />
'''Código da clase UD2_1_RendererXogo:'''<br/><br />
Exemplo de código para rotar a cámara.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="5-7"><br />
public void render(float delta){<br />
Gdx.gl.glClearColor(1, 1, 1, 1);<br />
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);<br />
<br />
camara2d.rotate(1);<br />
camara2d.update();<br />
spritebatch.setProjectionMatrix(camara2d.combined);<br />
<br />
spritebatch.begin();<br />
spritebatch.draw(grafico,200,150,50,50);<br />
spritebatch.end();<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
:::Veremos os eixes de dirección máis adiante en profundidade.<br />
<br />
<br />
<br />
<u><b>Nota:</b></u> Lembrade que sempre hai que chamar ó método update cando se faga unha modificación.<br />
<br />
O código dos métodos anteriores pódese poñer:<br />
<br />
* No '''método resize''' se a cámara non se move durante o xogo e queremos darlle unha posición inicial diferente á predeterminada.<br />
<br />
* No '''método render''' despois de borrar a pantalla e antes de debuxar os gráficos. Se o facemos neste punto, temos que informarlle ó obxecto que debuxa (no exemplo ten de nome spritebatch) que debuxe todo de acordo ás novas matrices de proxección e modelado da cámara (ó cambiar a posición da cámara cambiamos a súa matriz de modelado). Isto se fai chamando o método setProjectionMatrix da clase SpriteBatch.<br />
<br />
Imos facelo no método render:<br />
<br />
'''Código da clase UD2_1_RendererXogo:'''<br /><br />
Exemplo de código para posicionar a cámara.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="5-7"><br />
public void render(float delta){<br />
Gdx.gl.glClearColor(1, 1, 1, 1);<br />
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);<br />
<br />
camara2d.position.set(50,50,0);<br />
camara2d.update();<br />
spritebatch.setProjectionMatrix(camara2d.combined);<br />
<br />
spritebatch.begin();<br />
spritebatch.draw(grafico,Mundo.TAMANO_MUNDO_ANCHO/2,Mundo.TAMANO_MUNDO_ALTO/2,50,50);<br />
spritebatch.end();<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
O efecto é o seguinte:<br />
<br />
[[Imagen:LIBGDX_UD2_5_a_camara2d_2.jpg|thumb|center|x400px|Cámara movida á posición 50,50 nun dispositivo de 400x800 pixeles nun mundo de 300x500 unidades. Fixarse que movemos a cámara pero o gráfico está na mesma posición que antes.]]<br />
<br />
===Facendo zoom===<br />
<br />
Como comentamos antes, a cámara ten un vector dirección que coincide no eixe Z do espazo. En dito eixe, os valores positivos son os que van cara a cámara e os valores negativos son os que van cara a onde apunta á cámara.<br />
<br />
[[Imagen:LIBGDX_UD2_5_a_camara2d_3.jpg|thumb|center|400px|Amosa cales son os valores positivos dos eixes x,y,z]]<br />
<center>[http://www.elai.upm.es/webantigua/spain/Asignaturas/InfoInd/teoria/Apuntes%20de%20OpenGL.pdf Imaxe obtida dos apuntes de Cristina Cañero Morales]</center><br />
<br />
Podemos facer zoom na cámara. Se poñemos un valor positivo nos afastaríamos do obxecto e cun valor negativo nos achegaríamos ó obxecto. <br />
<br />
Indicar que a cámara, a parte de ter un vector dirección (cara onde se dirixe a cámara) ten un método ('''lookat''') que indica cara onde está mirando a cámara. Por iso, no seguinte exemplo, se facedes que o zoom aumente, cando pase da imaxe dará a volta a cámara....<br />
<br />
'''Código da clase UD2_1_RendererXogo:'''<br/><br />
Exemplo de código para facer zoom coa cámara.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="5-7"><br />
public void render(float delta){<br />
Gdx.gl.glClearColor(1, 1, 1, 1);<br />
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);<br />
<br />
camara2d.zoom+=0.01f; // Neste caso se afasta. Se restamos se achegaría.<br />
camara2d.update();<br />
spritebatch.setProjectionMatrix(camara2d.combined);<br />
<br />
spritebatch.begin();<br />
spritebatch.draw(grafico,200,150,50,50);<br />
spritebatch.end();<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
<br />
'''Nota:''' Unha vez visto os principais métodos da cámara imos volver a usar a clase RendererXogo, cambiando a clase PantallaXogo para que chame a RendererXogo como tiñamos antes.<br />
<br />
===Proxectando os puntos===<br />
<br />
Como comentamos anteriormente unha das cousas que podemos facer coa cámara é pasar coordenadas de puntos dende o dispositivo real a coordenadas da cámara (o noso mundo) e viceversa. <br />
<br />
[[Imagen:LIBGDX_xogos2d_desenrolo_16.jpg|frame|center|Nesta pantalla o noso mundo mide 400x200 unidades. Se prememos sobre a pantalla do dispositivo daranos as coordenadas do mesmo. Teremos que pasar dita coordenadas ó sistema de coordenadas da cámara. Tamén podemos facer o proceso contrario]]<br />
<br />
Outro exemplo:<br />
<br />
[[Imagen:LIBGDX_UD2_6_graficos_10.jpg|frame|center|Outro exemplo de proxección. O dispositivo ten unha resolución de 800x480 pixeles e o mundo 500x300 unidades]]<br />
<br />
<br />
Para facelo debemos usar os métodos:<br />
*[http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/Camera.html#unproject%28com.badlogic.gdx.math.Vector3,%20float,%20float,%20float,%20float%29 '''unproject''']: <br />
:Transforma un Vector dato dende o sistema de coordenadas da pantalla do dispositivo ó sistema de coordenadas da cámara.<br />
:Normalmente será este método o que utilicemos para interaccionar coas nosas personaxes.<br />
*[http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/Camera.html#project%28com.badlogic.gdx.math.Vector3%29 '''project'''].<br />
:Fai o proceso contrario. Pasa do sistema de coordenadas da cámara ó sistema de coordenadas da pantalla do dispositivo.<br />
<br />
<br />
<u><b>Preparación:</b></u> Agora ides facer unha copia da clase UD2_1_RendererXogo, xa que imos ver como facer o project e unproject. Premede co rato sobre a clase, botón dereito e escollede a opción Copy. Despois repetides a operación pero escolledes a opción Paste. Vos preguntará un nome para a clase. Indicade '''UD2_2_RendererXogo'''. Modificade a pantalla PantallaXogo para que chame a esta clase.<br />
<br />
<br />
O problema que temos é que para facer esta práctica e podamos pasar dun sistema de coordenadas a outro temos que controlar cando prememos sobre a pantalla do dispositivo. <br />
<br />
Isto o facemos cunha interface. A '''interface InputProcessor'''.<br />
<br />
O veremos máis adiante neste curso. Agora copiade o seguinte código e quedádevos con a idea de que existe unha interface que incorpora uns métodos. Un destes métodos é facer 'click' sobre a pantalla (método touchDown).<br />
<br />
O proceso para incorporar unha interface é moi sinxelo.<br />
<br />
Primeiro escribimos este código:<br />
<br />
'''Código da clase UD2_2_RendererXogo:'''<br />
<syntaxhighlight lang="java" line enclose="div"><br />
public class UD2_2_RendererXogo implements InputProcessor {<br />
</syntaxhighlight><br />
<br />
Teredes que importar a nova clase (teclas Control + Shift + O).<br />
<br />
Unha vez importada vos dará un erro. Situar o cursor enriba da clase que da erro como amosa a seguinte imaxe:<br />
<br />
[[Imagen:LIBGDX_UD2_6_graficos_8.jpg|400px|center]]<br />
<br />
Vos aparecerá unha ventá emerxente no que vos dará a opción de '''Add unimplemented methods'''. Ó premer sobre dita opción se engadirán todos os métodos de dita interface entre os que estará o método touchDown:<br />
<br />
<br />
'''Código da clase UD2_2_RendererXogo:'''<br />
<br/>Obxectivo: Incorpora a interface InputProcessor.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="81-85"><br />
/**<br />
* Explica como facer o project e unproject da cámara.<br />
* Move o gráfico ó punto indicado ó premer sobre a pantalla.<br />
*/<br />
<br />
package com.plategaxogo2d.renderer;<br />
<br />
import com.badlogic.gdx.Gdx;<br />
import com.badlogic.gdx.InputProcessor;<br />
import com.badlogic.gdx.graphics.GL20;<br />
import com.badlogic.gdx.graphics.OrthographicCamera;<br />
import com.badlogic.gdx.graphics.Texture;<br />
import com.badlogic.gdx.graphics.g2d.SpriteBatch;<br />
import com.plategaxogo2d.modelo.Mundo;<br />
<br />
public class UD2_2_RendererXogo implements InputProcessor {<br />
<br />
private Texture grafico;<br />
private SpriteBatch spritebatch;<br />
<br />
private OrthographicCamera camara2d;<br />
<br />
<br />
<br />
public UD2_2_RendererXogo() {<br />
camara2d = new OrthographicCamera();<br />
grafico = new Texture(Gdx.files.internal("badlogic.jpg"));<br />
spritebatch = new SpriteBatch();<br />
} <br />
<br />
<br />
/**<br />
* Debuxa todos os elementos gr�ficos da pantalla<br />
* @param delta: tempo que pasa entre un frame e o seguinte.<br />
*/<br />
public void render(float delta){<br />
Gdx.gl.glClearColor(1, 1, 1, 1);<br />
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);<br />
<br />
spritebatch.begin();<br />
spritebatch.draw(grafico,Mundo.TAMANO_MUNDO_ANCHO/2,Mundo.TAMANO_MUNDO_ALTO/2,50,50);<br />
spritebatch.end();<br />
<br />
}<br />
<br />
public void resize(int width, int height) {<br />
<br />
camara2d.setToOrtho(false,Mundo.TAMANO_MUNDO_ANCHO,Mundo.TAMANO_MUNDO_ALTO);<br />
camara2d.update();<br />
<br />
spritebatch.setProjectionMatrix(camara2d.combined);<br />
<br />
}<br />
public void dispose(){<br />
spritebatch.dispose();<br />
grafico.dispose();<br />
}<br />
<br />
<br />
@Override<br />
public boolean keyDown(int keycode) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
<br />
@Override<br />
public boolean keyUp(int keycode) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
<br />
@Override<br />
public boolean keyTyped(char character) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
<br />
@Override<br />
public boolean touchDown(int screenX, int screenY, int pointer, int button) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
<br />
@Override<br />
public boolean touchUp(int screenX, int screenY, int pointer, int button) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
<br />
@Override<br />
public boolean touchDragged(int screenX, int screenY, int pointer) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
<br />
@Override<br />
public boolean mouseMoved(int screenX, int screenY) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
<br />
@Override<br />
public boolean scrolled(int amount) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
A maiores, para que funcione a xestión de eventos temos que chamar ó método:<br />
<br />
[http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/input/RemoteInput.html#setInputProcessor%28com.badlogic.gdx.InputProcessor%29 setInputProcessor] e indicarlle a clase que vai xestionar os eventos.<br />
<br />
Cando saiamos da mesma deberemos de quitar dita asignación, como facemos no seguinte código:<br />
<br />
'''Código da clase UD2_2_RendererXogo:'''<br />
<br/>Obxectivo: Indicar que clase xestiona a InputProcessor.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="6,11"><br />
public UD2_2_RendererXogo() {<br />
camara2d = new OrthographicCamera();<br />
grafico = new Texture(Gdx.files.internal("badlogic.jpg"));<br />
spritebatch = new SpriteBatch();<br />
<br />
Gdx.input.setInputProcessor(this);<br />
} <br />
<br />
public void dispose() {<br />
<br />
Gdx.input.setInputProcessor(null);<br />
spritebatch.dispose();<br />
grafico.dispose();<br />
}<br />
<br />
<br />
</syntaxhighlight><br />
<br />
<br />
<b><u>Nota:</u></b>: Lembrar que estamos a facer isto para poder explicar o project e unproject da cámara. Xa explicaremos en profundidade a xestión de eventos.<br />
<br />
<br />
* Analicemos o método touchdown:<br />
<syntaxhighlight lang="java" line enclose="div"><br />
@Override<br />
public boolean touchDown(int screenX, int screenY, int pointer, int button) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
</syntaxhighlight><br />
<br />
Entre os seus parámetros veñen as coordenadas x,y do dispositivo '''EN PIXELES DE PANTALLA'''.<br />
<br />
Podemos comprobalo:<br />
<br />
'''Código da clase UD2_2_RendererXogo:'''<br />
<br/>Obxectivo: Imprimir en pixeles o punto onde se preme na pantalla.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="5"><br />
@Override<br />
public boolean touchDown(int screenX, int screenY, int pointer, int button) {<br />
// TODO Auto-generated method stub<br />
<br />
Utiles.imprimirLog("UD2_2_RendererXogo", "touchDown", String.valueOf(screenX)+"-"+String.valueOf(screenY));<br />
return false;<br />
}<br />
</syntaxhighlight><br />
<br />
[[Imagen:LIBGDX_UD2_6_graficos_9.jpg|400px|center]]<br />
<br />
<br />
====Realizar un unproject====<br />
<br />
Imos ver como pasar as coordenadas en pixeles a coordenadas do noso mundo (que son as coordenadas do viewport da cámara).<br />
Lembrar que ditas coordenadas as ten definidas a cámara no seu viewport e se corresponden coas constantes de clase definidas na clase Mundo.<br />
<br />
<br />
'''Código da clase UD2_2_RendererXogo:'''<br />
<br/>Obxectivo: Pasar das coordenadas reais ás coordenadas da cámara.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="8"><br />
@Override<br />
public boolean touchDown(int screenX, int screenY, int pointer, int button) {<br />
// TODO Auto-generated method stub<br />
<br />
Utiles.imprimirLog("UD2_2_RendererXogo", "touchDown", String.valueOf(screenX)+"-"+String.valueOf(screenY));<br />
<br />
Vector3 temporal = new Vector3(screenX,screenY,0);<br />
camara2d.unproject(temporal);<br />
Utiles.imprimirLog("UD2_2_RendererXogo", "touchDown", "COORDENADAS MUNDO:" + String.valueOf(temporal));<br />
<br />
<br />
return false;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
Algunhas aclaracións:<br />
* O vector temporal leva como valor no eixe z un 0. Isto fai que a proxección se faga sobre o plano near da cámara. Se levase o valor 1 se faría sobre o plano far.<br />
* Ó chamar ó método unproject modifícase o vector temporal.<br />
* O método toma como punto 0,0 a esquina inferior esquerda. <br />
* Por defecto establece como ancho e alto do dispositivo o total da pantalla (no exemplo 800x480). Pero podemos modificar isto se ides o enlace do método unproject.<br />
<br />
<br />
Lembra que podemos aplicar [http://informatica.iessanclemente.net/manuais/index.php/LIBGDX_Anexo_Consellos_de_programacion o consello de programación] neste caso sobre o vector temporal.<br />
<br />
====Realizar un project====<br />
<br />
Imos ver como pasar as coordenadas do noso mundo a coordenadas en pixeles.<br />
<br />
Supoñamos que movemos a imaxe á coordenada 100,400 do noso mundo e queremos saber a que coordenada se corresponde do noso dispositivo / pantalla en pixeles.<br />
Lembrar que no exemplo estamos traballando nunha '''resolución de 480x800''' pixeles.<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="5-6"><br />
@Override<br />
public boolean touchDown(int screenX, int screenY, int pointer, int button) {<br />
// TODO Auto-generated method stub<br />
<br />
temporal.set(100,400,0);<br />
camara2d.unproject(temporal);<br />
Utiles.imprimirLog("UD2_2_RendererXogo", "touchDown", "COORDENADAS MUNDO:" + String.valueOf(temporal));<br />
<br />
return false;<br />
}<br />
</syntaxhighlight><br />
<br />
'''Resultado: 160,640 '''<br />
<br />
Para comprobalo podemos facer unha regra de tres:<br />
<br />
:Se 300 unidades son 480 pixeles<br />
: 100 unidades son x<br />
<br />
:x = 48000/300 = 160<br />
<br />
E o mesmo para o y.<br />
<br />
<br />
Algunhas aclaracións:<br />
* Ó chamar ó método project modifícase o vector temporal.<br />
* O método toma como punto 0,0 a esquina inferior esquerda. <br />
* Por defecto establece como ancho e alto do dispositivo o total da pantalla (no exemplo 800x480). Pero podemos modificar isto se ides o enlace do método project.<br />
<br />
====Exemplo: Movendo o gráfico====<br />
<br />
O aprendido ata o de agora non nos deixar facer moitas cousas...<br />
<br />
Isto vai ser unha parte a utilizar posteriormente no desenvolvemento do xogo.<br />
<br />
Agora a modo de exemplo imos facer que o gráfico que aparece en pantalla se mova ó lugar onde prememos na pantalla.<br />
<br />
Lembrar que a xestión de eventos non a imos facer aquí, como será explicado posteriormente.<br />
<br />
Este punto trataba de coñecer como pasar dun sistema de coordenadas a outro.<br />
<br />
'''Exercicio proposto:''' Aquí vos deixo a solución.<br />
<br />
'''Código da clase UD2_2_RendererXogo:'''<br />
<br/>Obxectivo: Mover o gráfico ó punto indicado.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="25,32,48,92-93"><br />
/**<br />
* Explica cales son os métodos que temos para mover a cámara.<br />
* Carga un gráfico sinxelo no centro da pantalla<br />
*/<br />
<br />
package com.plategaxogo2d.renderer;<br />
<br />
import com.badlogic.gdx.Gdx;<br />
import com.badlogic.gdx.InputProcessor;<br />
import com.badlogic.gdx.graphics.GL20;<br />
import com.badlogic.gdx.graphics.OrthographicCamera;<br />
import com.badlogic.gdx.graphics.Texture;<br />
import com.badlogic.gdx.graphics.g2d.SpriteBatch;<br />
import com.badlogic.gdx.math.Vector3;<br />
import com.plategaxogo2d.angel.Utiles;<br />
import com.plategaxogo2d.modelo.Mundo;<br />
<br />
public class UD2_2_RendererXogo implements InputProcessor {<br />
<br />
private Texture grafico;<br />
private SpriteBatch spritebatch;<br />
<br />
private OrthographicCamera camara2d;<br />
<br />
private Vector3 temporal;<br />
<br />
public UD2_2_RendererXogo() {<br />
camara2d = new OrthographicCamera();<br />
grafico = new Texture(Gdx.files.internal("badlogic.jpg"));<br />
spritebatch = new SpriteBatch();<br />
<br />
temporal = new Vector3();<br />
<br />
Gdx.input.setInputProcessor(this);<br />
}<br />
<br />
/**<br />
* Debuxa todos os elementos gr�ficos da pantalla<br />
* <br />
* @param delta<br />
* : tempo que pasa entre un frame e o seguinte.<br />
*/<br />
public void render(float delta) {<br />
Gdx.gl.glClearColor(1, 1, 1, 1);<br />
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);<br />
<br />
spritebatch.begin();<br />
spritebatch.draw(grafico, temporal.x,temporal.y, 50, 50);<br />
spritebatch.end();<br />
<br />
}<br />
<br />
public void resize(int width, int height) {<br />
<br />
camara2d.setToOrtho(false, Mundo.TAMANO_MUNDO_ANCHO,<br />
Mundo.TAMANO_MUNDO_ALTO);<br />
camara2d.update();<br />
<br />
spritebatch.setProjectionMatrix(camara2d.combined);<br />
<br />
}<br />
<br />
public void dispose() {<br />
<br />
Gdx.input.setInputProcessor(null);<br />
spritebatch.dispose();<br />
grafico.dispose();<br />
}<br />
<br />
@Override<br />
public boolean keyDown(int keycode) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
@Override<br />
public boolean keyUp(int keycode) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
@Override<br />
public boolean keyTyped(char character) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
@Override<br />
public boolean touchDown(int screenX, int screenY, int pointer, int button) {<br />
// TODO Auto-generated method stub<br />
<br />
temporal.set(screenX,screenY,0);<br />
camara2d.unproject(temporal);<br />
<br />
return false;<br />
}<br />
<br />
@Override<br />
public boolean touchUp(int screenX, int screenY, int pointer, int button) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
@Override<br />
public boolean touchDragged(int screenX, int screenY, int pointer) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
@Override<br />
public boolean mouseMoved(int screenX, int screenY) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
<br />
@Override<br />
public boolean scrolled(int amount) {<br />
// TODO Auto-generated method stub<br />
return false;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] -- (2014).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Archivo:Android_2013_olamundo_03.jpg&diff=57181Archivo:Android 2013 olamundo 03.jpg2015-08-14T13:51:11Z<p>Angelfg: Angelfg subió una nueva versión de «Archivo:Android 2013 olamundo 03.jpg»</p>
<hr />
<div></div>Angelfghttps://manuais.iessanclemente.net/index.php?title=C%C3%A1mara_fotogr%C3%A1fica&diff=57170Cámara fotográfica2015-07-28T09:40:23Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Neste curso só se vai introducir como manexar a cámara de fotos e amosar a foto obtida.<br />
*Para ver como gardar as imaxes e como incluso gravar e manipula vídeos hai un apartado final onde se indica como proceder.<br />
<br />
As clases que interveñen son:<br />
<br />
* [http://developer.android.com/reference/android/hardware/Camera.html Clase Camera]: danos acceso á cámara, as súas características. Usarémola se facemos unha aplicación na que queiramos xestionar a cámara por nos mesmos.<br />
<br />
<br />
Para facer uso da cámara podemos utilizar un Intent, evitándonos ter que deseñar a aplicación para xestionar a cámara.<br />
<br />
<br />
Permisos necesarios a engadir no arquivo AndroidManifest.xml: <br />
<br />
* Permiso para facer uso da cámara:<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="" ><br />
<uses-permission android:name="android.permission.CAMERA" /><br />
</syntaxhighlight> <br />
<br />
<br />
<u>Nota:</u> Se usamos a opción de chamar á cámara cun Intent non necesitamos dito permiso.<br />
<br />
* Permiso para indicar que a nosa aplicación fai uso da cámara (Ollo que é uses-feature):<br />
:<syntaxhighlight lang="xml" line enclose="div" highlight="" ><br />
<uses-feature android:name="android.hardware.camera" required="true"/><br />
</syntaxhighlight> <br />
<br />
Se queremos facer uso doutras ‘características’, tanto da cámara coma doutro hardware que ten o dispositivo móbil, consultar: http://developer.android.com/guide/topics/manifest/uses-feature-element.html#hw-features<br />
<br />
Desta forma Google Play impedirá que se instale á aplicación se o dispositivo non ten o hardware necesario coas características especificadas. <br />
<br />
Neste caso, a nosa aplicación está requirindo ó uso da cámara, pero pode ocorrer que non a necesite para que funcione (podemos limitar a funcionalidade da nosa aplicación se o dispositivo non ten cámara, por exemplo). Para indicar isto temos que poñer:<br />
<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="" ><br />
<uses-feature android:name="android.hardware.camera" android:required="false" /><br />
</syntaxhighlight><br />
<br />
<br />
Chamaremos a unha aplicacións e recolleremos o resultado de volta, que será a foto.<br />
<br />
Os pasos a seguir son:<br />
<br />
* Crear un Intent que sexa do tipo:<br />
:* [http://developer.android.com/reference/android/provider/MediaStore.html#ACTION_IMAGE_CAPTURE MediaStore.ACTION_IMAGE_CAPTURE] : Captura unha imaxe.<br />
<br />
:<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
Intent intento = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);<br />
</syntaxhighlight> <br />
<br />
<br />
* Chamar ó [http://developer.android.com/reference/android/app/Activity.html#startActivityForResult%28android.content.Intent,%20int%29 método startActivityForResult()]. <br />
:Neste momento o S.O. lanzará unha aplicación para recoller a imaxe. <br />
:Lembrar que con esta forma de chamar a unha activity, esperamos un resultado (a foto).<br />
<br />
:<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
startActivityForResult(intento, REQUEST_CODE_CAMARA);<br />
</syntaxhighlight> <br />
<br />
* Obter o resultado da aplicación lanzada. Para iso temos que desenrolar o [http://developer.android.com/reference/android/app/Activity.html#onActivityResult%28int,%20int,%20android.content.Intent%29 método onActivityResult()] da nosa Activity.<br />
<br />
*Nó método '''onActivityResult()''' imos recoller a imaxe vén no campo "data" dentro de getExtras do obxecto Bundle: <br />
::<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
protected void onActivityResult(int requestCode, int resultCode, Intent data) {<br />
<br />
Bitmap bitMap= data.getExtras().get("data"));<br />
.........<br />
}<br />
</syntaxhighlight> <br />
<br />
: Unha vez temos o BitMap podemos visualizalo nun control ImageView da seguinte forma:<br />
<br />
::<syntaxhighlight lang="java" line enclose="div" highlight="4" ><br />
protected void onActivityResult(int requestCode, int resultCode, Intent data) {<br />
<br />
Bitmap bitMap= data.getExtras().get("data"));<br />
imgView.setImageBitmap(bitMap);<br />
}<br />
</syntaxhighlight> <br />
<br />
: Sendo imgView un obxecto da clase ImageView.<br />
<br />
==A Cámara==<br />
*Segundo o AVD/Dispostivo este pode ter cámara traseira e tamén dianteira, para os famoso autoretratos, que todos damos en chamar Selfies <br />
*No caso dun AVD a cámara pode ser emulada ou usar a do ordenador real se dispón dela.<br />
*Nesta imaxe amósase que se vai usar a cámara emulada. <br />
[[Image:Android_2014_U5_10_Fotos_01.jpg|350px]]<br />
<br />
==Caso práctico==<br />
*Crear o proxecto: '''U5_10_Fotos<br />
<br />
<gallery caption="Realizar unha foto" widths="350" heights="300px" perrow="2"><br />
Image:Android_2014_U5_10_Fotos_02.jpg|A aplicación dispón dun botón que vai lanzar a través dun intent. E dunha view "ImageView" que vai amosar a foto que nos devolve a cámara cando volvemos da activity que a manexa. Nestes intres ese View ten o debuxo de Android. <br />
Image:Android_2014_U5_10_Fotos_03.jpg| Como a cámara é emulad, anda por aí un cadrado bailando até que premamos o botón do obturador para realizar a foto.<br />
Image:Android_2014_U5_10_Fotos_04.jpg|Unha vez premido o obturador vemos que podemos descartar a foto (x) ou aceptala (marca de verificación), en calquera caso volvemos á activity principal.<br />
Image:Android_2014_U5_10_Fotos_05.jpg|No caso de aceptar a foto, vemos na para inferior da activity principal a foto realizada coa cámara na activity secundaria.<br />
</gallery><br />
<br />
<br />
===O xml do layout===<br />
<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="44-49" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<Button<br />
android:id="@+id/bFoto"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:onClick="onBotonClick"<br />
android:text="Facer Foto" /><br />
<br />
<ImageView<br />
android:id="@+id/imgvwFoto"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:contentDescription="foto a sacar"<br />
android:src="@drawable/ic_launcher" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
<br />
<br />
===O Código java da aplicación===<br />
<syntaxhighlight lang="java" line enclose="div" highlight="15,43-44,48-68" ><br />
package com.example.u5_10_fotos;<br />
<br />
import android.app.Activity;<br />
import android.content.Intent;<br />
import android.graphics.Bitmap;<br />
import android.os.Bundle;<br />
import android.provider.MediaStore;<br />
import android.view.Menu;<br />
import android.view.MenuItem;<br />
import android.view.View;<br />
import android.widget.ImageView;<br />
import android.widget.Toast;<br />
<br />
public class U5_10_Fotos extends Activity {<br />
private final int REQUEST_CODE_CAMARA = 1;<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u5_10__fotos);<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u5_10__fotos, menu);<br />
return true;<br />
}<br />
<br />
@Override<br />
public boolean onOptionsItemSelected(MenuItem item) {<br />
// Handle action bar item clicks here. The action bar will<br />
// automatically handle clicks on the Home/Up button, so long<br />
// as you specify a parent activity in AndroidManifest.xml.<br />
int id = item.getItemId();<br />
if (id == R.id.action_settings) {<br />
return true;<br />
}<br />
return super.onOptionsItemSelected(item);<br />
}<br />
<br />
public void onBotonClick(View v) {<br />
Intent intento = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);<br />
startActivityForResult(intento, REQUEST_CODE_CAMARA);<br />
}<br />
<br />
@Override<br />
protected void onActivityResult(int requestCode, int resultCode, Intent data) {<br />
// TODO Auto-generated method stub<br />
if (requestCode == REQUEST_CODE_CAMARA) {<br />
if (resultCode == RESULT_OK) {<br />
<br />
if (data == null) {<br />
Toast.makeText(this, "NON HAI IMAXE", Toast.LENGTH_LONG).show();<br />
return;<br />
}<br />
<br />
ImageView imgview = (ImageView) findViewById(R.id.imgvwFoto);<br />
imgview.setImageBitmap((Bitmap) data.getExtras().get("data"));<br />
<br />
} else if (resultCode == RESULT_CANCELED) {<br />
// Foto cancelada<br />
} else {<br />
// Fallo na captura da foto.<br />
}<br />
}<br />
<br />
}<br />
<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Liñas 43-44''': Creamos un intent e lanzámolo esperando un resultado (a foto, neste caso).<br />
<br />
*'''Liñas 48-68''': Recibimos o resultado da activity secundaria (a que manexa a cámara) e comprobamos se o código devolto foi o mesmo que usamos para lanzar a cámara e tamén comprobamos se recibimos unha imaxe que nese caso imos amosar na vista ImageView, unha vez que a recollemos da chave "data" do campo data.<br />
<br />
==Afondar sobre o uso da cámara e vídeo==<br />
*Para ter un coñecemento máis profundo do uso da cámara:<br />
**Gardar as fotos,<br />
**Gravar e gardar vídeos,<br />
**Audio,<br />
**Etc.<br />
<br />
<br />
*Pódese consultar o seguinte enlace do curso avanzado de Android: [[PDM Avanzado Captura de Vídeo / Imaxes]]<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=PDM_Avanzado_Empaquetado_e_distribuci%C3%B3n&diff=57168PDM Avanzado Empaquetado e distribución2015-07-28T09:17:18Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
<br />
Unha vez temos a aplicación rematada chega o momento de, ou ben pasala ó/ós usuarios que van facer uso dela ou ben subila ó Market de Android para a súa comercialización.<br />
<br />
Para poder realizar este paso é necesario xerar o APK da aplicación cun certificado válido.<br />
<br />
Temos que xerar o arquivo apk da aplicación pero coa aplicación 'firmada' cun keystore que ven ser un almacén de claves. <br />
<br />
Cando xeremos o apk primeiro daranos a opción de crear un novo almacén ou utilizar un xa existente.<br />
<br />
Nun almacén imos poder 'gardar' moitas aplicacións. Cada almacén terá unha clave.<br />
<br />
Así mesmo, cada aplicación terá outra clave asociada o seu certificado.<br />
<br />
Polo tanto cando xeremos o apk imos ter que gardar dúas claves: unha para o almacén e outra para cada unha das aplicacións gardadas en dito almacén.<br />
<br />
<br />
A firma é moi importante xa que cada vez que cambiemos de versión teremos que firmala có mesmo certificado para que o S.O. Android o interprete como unha actualización da aplicación.<br />
<br />
<br />
<br />
==Eliminando erros==<br />
<br />
Se estadas a utilizar librerías externas (como a de Google Play Services) ou calquera outra pode ser que vos aparezan estes erros cando estades intentando xerar o apk:<br />
<br />
[[Imagen:PDM_Avanzada_Empaquetado_7.jpg | 400px | center]]<br />
<br />
Para eliminar estes erros temos que:<br />
<br />
<gallery caption="Eliminación de erros lint" widths="350" heights="300px" perrow="2"><br />
Image:PDM_Avanzada_Empaquetado_8.jpg| Imos o menú de Eclipse => Preferences.<br />
Image:PDM_Avanzada_Empaquetado_9.jpg| Escollemos na parte esquerda a opción de 'Lint Error Checking' e desmarcamos a opción 'Run full....'.<br />
Image:PDM_Avanzada_Empaquetado_10.jpg | Escollemos a opción de menú de Eclipse => Proyect => Clean.<br />
Image:PDM_Avanzada_Empaquetado_11.jpg | Escollemos o proxecto a recompilar.<br />
<br />
</gallery><br />
<br />
==Graficamente==<br />
<br />
Simplemente nos situamos sobre a versión de Android, prememos botón dereito e escollemos a opción Android Tools => 'Export Signed Application Package':<br />
<br />
[[Imagen:PDM_Avanzada_Empaquetado_1.jpg|500px|center]]<br />
<br />
<br />
Aparece un asistente:<br />
<br />
<br />
<gallery caption="Asistente de xeración de apk" widths="350" heights="300px" perrow="2"><br />
Image:PDM_Avanzada_Empaquetado_2.jpg| Indicamos o proxecto que queremos xerar o apk. Unha vez escollido prememos o botón de 'Next'.<br />
Image:PDM_Avanzada_Empaquetado_3.jpg| Nesta pantalla podemos indicar se xa temos un keystore (almacén de claves). Se o tivésemos deberíamos seleccionalo. Inicialmente imos crear un novo.<br />
Image:PDM_Avanzada_Empaquetado_4.jpg| Nesta pantalla temos que indicar: '''Alias:''' Un alias para o key. Pode ser o mesmo que o nome ou unha abreviación do mesmo. '''Password:''' Novamente asinámoslle unha contrasinal. Ten que ter o lo menos 6 caracteres. Esta vai ser a contrasinal da key da aplicación. '''Validity (years)''': Aquí indicamos o tempo que vai ser válida a nosa key en anos. Os seguintes campos fan referencia a información persoal e da organización. O campo de Country Code, se pode consultar no listado da [http://es.wikipedia.org/wiki/ISO_3166-1 ISO 3166-1]. No noso caso sería ES. <br />
Image:PDM_Avanzada_Empaquetado_5.jpg| Indicamos o lugar onde se vai xerar o apk xa coa firma.<br />
<br />
</gallery><br />
<br />
Agora xa podemos instalar o apk en calquera dispositivo con Android.<br />
<br />
==Dende consola==<br />
<br />
Esta información tamén se pode obter dende unha consola ou terminal. En Windows <u>debemos utilizar unha consola con permisos administrativos</u> (executar como administrador).<br />
<br />
Debemos situarnos coa orde '''cd''' (se non o temos no path) no cartafol onde estea instalado o JDK e dentro deste no cartafol /bin/.<br />
<br />
Nese cartafol se atopa o executable keytool.<br />
<br />
* LINUX:<br />
<br />
::<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
./keytool -genkey -v -keystore almacen.keystore -alias clavealmacen -keyalg RSA -keysize 2048 -validity 10000<br />
</syntaxhighlight> <br />
<br />
<br />
* WINDOWS:<br />
<br />
::<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
keytool -genkey -v -keystore almacen.keystore -alias clavealmacen -keyalg RSA -keysize 2048 -validity 10000<br />
</syntaxhighlight><br />
<br />
Neste caso estariamos a crear un almacén e un certificado (key) válido por 10.000 días.<br />
<br />
Ó darlle a 'enter' pediranos o password do almacén (mínimo 6 caracteres) e a información que preguntou antes graficamente para o certificado (key):<br />
<br />
[[Imagen:PDM_Avanzada_Empaquetado_6.jpg | 500px | center]]<br />
<br />
Unha vez feito xa temos o almacén creado.<br />
<br />
==Obtendo a pegada dixital SHA1 dun almacén para utilizar con GoogleMap==<br />
<br />
Relacionado coa Unidade vista anteriormente de [http://manuais.iessanclemente.net/index.php/PDM_Avanzado_GoogleMaps#Obtenci.C3.B3n_da_pegada_dixital_SHA1_Produci.C3.B3n Google Map] temos a opción de obter a clave SHA1 dun almacén de datos, necesario para poder ver o mapa de Google Map nunha aplicación que queiramos dar ós usuarios.<br />
<br />
Para obter o SHA1 debemos escribir dende consola:<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
keytool -v -keystore almacen.keystore -list<br />
</syntaxhighlight><br />
<br />
Sendo almacen.keystore o almacén onde se atopa a key que imos utilizar para firmar a nosa aplicación.<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=GridView&diff=57158GridView2015-07-28T08:54:31Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*A vista '''GridView''' ofrece a posibilidade de amosar ao usuario un conxunto de datos para ser seleccionados en forma tabular.<br />
[[Image:Gridview.png]]<br />
<br />
*Co visto até agora o usuario é quen de poder facer uso desta View usando as seguintes referencias:<br />
**http://developer.android.com/guide/topics/ui/layout/gridview.html<br />
**http://developer.android.com/reference/android/widget/GridView.html<br />
<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=ListView&diff=57157ListView2015-07-28T08:53:27Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Un '''ListView''' é unha view de que lle permite ao usuario seleccionar un elemento.<br />
*A diferencia dun Spinner unha lista amosa todos os seus elementos na pantalla.<br />
[[Image:Listview.png]]<br />
<br />
*A imaxe recolle un exemplo de lista, cada item pode conter un só dato, ou múltiples datos. O primeiro caso é o que se vai ver neste curso.<br />
<br />
<br />
<gallery caption="ListView" widths="350" heights="300px" perrow="2"><br />
Image:Android_2014_U4_03_ListView_01.jpg| A imaxe amosa unha lista simple<br />
Image:Contactos.png| Un ListView máis complexo é a lista de contactos do teléfono. Cada ítem ten como mímio: Foto, Nome, Telf, se ten whatsaspp, etc.<br />
</gallery><br />
<br />
<br />
*Ao igual que no Spinner usaremos unha fonte de datos (array estático, array dinñamico, recurso xml, etc) para enlazalo co adaptador e este co ListView.<br />
<br />
<br />
==Caso Práctico==<br />
*Comezar creando o proxecto: '''U4_03_ListView''' <br />
<br />
<gallery caption="ListView" widths="350" heights="300px" perrow="2"><br />
Image:Android_2014_U4_03_ListView_01.jpg| Exemplo dunha lista simple, ao premer nun ítem ...<br />
Image:Android_2014_U4_03_ListView_02.jpg| Indícanos que ítem foi seleccionado con un Toast.<br />
</gallery><br />
<br />
<br />
<br />
===XML do Layout===<br />
<br />
*Definimos no Layout unha vista de tipo ListView (Liñas 12-15).<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="12-15" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Selecciona unha froita" /><br />
<br />
<ListView<br />
android:id="@+id/lv_froitas"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
<br />
===O código Java da aplicación===<br />
*A filosofía do código Java é moi semellante ao do Spinner.<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="24,27,30,33,38-39" ><br />
package com.example.u4_03_listview;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.MenuItem;<br />
import android.view.View;<br />
import android.widget.AdapterView;<br />
import android.widget.AdapterView.OnItemClickListener;<br />
import android.widget.ArrayAdapter;<br />
import android.widget.ListView;<br />
import android.widget.TextView;<br />
import android.widget.Toast;<br />
<br />
public class U4_03_ListView extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u4_03__list_view);<br />
ListView lvFroitas = (ListView) findViewById(R.id.lv_froitas);<br />
<br />
//Fonte de datos<br />
String[] froitas = new String[] { "Pera", "Mazá", "Plátano" };<br />
<br />
//Enlace do adaptador coa fonte de datos <br />
ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, froitas);<br />
<br />
//Enlace do adaptador co ListView<br />
lvFroitas.setAdapter(adaptador);<br />
<br />
//Escoitador<br />
lvFroitas.setOnItemClickListener(new OnItemClickListener() {<br />
<br />
@Override<br />
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {<br />
// TODO Auto-generated method stub<br />
//Toast.makeText(getBaseContext(), "Seleccionaches: " + parent.getItemAtPosition(position), Toast.LENGTH_SHORT).show();<br />
Toast.makeText(getBaseContext(), "Seleccionaches: " + ((TextView) view).getText(), Toast.LENGTH_SHORT).show();<br />
<br />
}<br />
});<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u4_03__list_view, menu);<br />
return true;<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
*'''Liña 24''': Ao igual que no Spinner, creamos unha fonte de datos, neste caso cun array estático.<br />
*'''Liña 27''': Do mesmo xeito creamos o adaptador<br />
*'''Liña 30''': E finalmente, vinculamos o adaptador ao ListView<br />
*'''Liña 33''': O Escoitador asociado ao ListView.<br />
*'''Liñas 38,39''': Ao igual que no spinner, neste caso a vista que recibimos cando facemos click nun ítem da view é do tipo TextView.<br />
<br />
==ListView usando un recurso XML ou un array dinámico==<br />
*Neste caso funciona igual que o visto no Spinner que fai uso dun adaptador.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Adaptadores&diff=57155Adaptadores2015-07-28T08:52:38Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Un '''adaptador''':<br />
** é un elemento intermediario entre unha fonte de datos (XML, Arrays, Ficheiros, BBDD) e un interface de usuario que amosa eses datos, por exemplo un Spinner, unha lista de Selección, etc.<br />
**Por cada dato crea unha View e a representa.<br />
** é o responsable de xerar todos os elementos de representación asociados aos datos. Imaxinar que cada ítem estivera formado por dous subcompoñentes: nome de persoa e foto. O adaptador debe ser quen de poder representar iso.<br />
*Dispoñemos tipos de adaptadores pero imos usar: '''ArrayAdapter''', que proporciona un interface de selección a través dun array de obxecto de calquera tipo.<br />
<br />
<br />
*Neste curso imos ver como usar '''ArrayAdapter''' para presentar datos de selección a través de '''Spinner''' e '''ListView'''.<br />
<br />
<br />
*Referncias:<br />
**ArrayAdapter: http://developer.android.com/reference/android/widget/ArrayAdapter.html<br />
<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Depuraci%C3%B3n:_LogCat&diff=57154Depuración: LogCat2015-07-28T08:52:23Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Unha das técnicas para realizar depuración e seguimento das aplicacións é a creación de logs (rexistros) en tempo de execución.<br />
*En Android úsase a clase '''Log''', que posúe un conxunto de métodos estáticos que nos van axudar no proceso de depuración/seguimento.<br />
<br />
[[Image:Android_2014_U4_01_Depuracion_01.jpg|700px]]<br />
*A imaxe amosa un conxunto de mensaxes que teñen, entre outros, os seguintes campos.<br />
**Nivel de criticidade: tipo de mensaxe (Erro, Warning, INfo, Debug, etc)<br />
**PID: Código do proceso que produciu a mensaxe.<br />
**Tag: Etiqueta que axuda á identificación da mensaxe, moi útil para filtrar resultados.<br />
**Mensaxe<br />
<br />
<br />
*Para cada nivel de criticidade existe un método estático que nós axuda a clasificar as mensaxes que pode producir a aplicación: '''e(), w(), i(), d() e v()'''.<br />
*Cada un dos métodos recibe como parámetro a etiqueta (''tag'') e o texto da mensaxe.<br />
<br />
<br />
*Referencias:<br />
**A Clase Log: http://developer.android.com/reference/android/util/Log.html<br />
<br />
==Caso práctico==<br />
*Crear o seguinte proxecto: '''U4_01_Depuracion'''<br />
*Imos realizar un pequeno proxecto onde amosamos como poder usar o LOG.<br />
*A etiqueta que se está usando no programa é: "DEPURACIÓN"<br />
*E estamos usando un filtro para ver só as etiquetas con ese nome.<br />
*Para ver as mensaxes de log usaremos a ventá '''LogCat''' que está tanto na perspectiva Java como DDMS.<br />
<br />
<gallery caption="Depuración" widths="350" heights="300px" perrow="2"><br />
Image:Android_2014_U4_01_Depuracion_03.jpg|Lanzamos a aplicación <br />
Image:Android_2014_U4_01_Depuracion_02.jpg|E no LogCat amosa unha serie de mensaxes con distintos niveis de criticidade.<br>Estas foron creadas dentro do método onCreate().<br />
Image:Android_2014_U4_01_Depuracion_04.jpg|Escribimos un valor correcto<br />
Image:Android_2014_U4_01_Depuracion_05.jpg|E no LogCat vemos por anda a aplicación ...<br />
Image:Android_2014_U4_01_Depuracion_06.jpg|Escribimos un valor incorrecto<br />
Image:Android_2014_U4_01_Depuracion_07.jpg|E volvemos ver por onde anda a aplicación ...<br />
</gallery><br />
<br />
===O XML do Layout===<br />
*A continuación amósase o Layout da aplicación:<br />
<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="13,19" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical"<br />
tools:context="com.example.u4_01_depuracion.U4_01_Depuracion" ><br />
<br />
<EditText<br />
android:id="@+id/et"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:hint="Introduce o século no que vives"<br />
android:inputType="number" /><br />
<br />
<Button<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Preme aquí"<br />
android:onClick="onButtonClick" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
<br />
<br />
===O código Java da aplicación===<br />
<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="18-22,38,42,48" ><br />
package com.example.u4_01_depuracion;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.util.Log;<br />
import android.view.Menu;<br />
import android.view.MenuItem;<br />
import android.view.View;<br />
import android.widget.EditText;<br />
import android.widget.Toast;<br />
<br />
public class U4_01_Depuracion extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u4_01__depuracion);<br />
Log.e("DEPURACIÓN", "Mensaxe de erro");<br />
Log.w("DEPURACIÓN", "Mensaxe de aviso");<br />
Log.i("DEPURACIÓN", "Mensaxe de información");<br />
Log.d("DEPURACIÓN", "Mensaxe de mensaxe de depuración");<br />
Log.v("DEPURACIÓN", "Mensaxe de vervose");<br />
<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u4_01__depuracion, menu);<br />
return true;<br />
}<br />
<br />
public void onButtonClick(View v) {<br />
EditText et = (EditText) findViewById(R.id.et);<br />
<br />
if (et.getText().toString().equals("21")) {<br />
Toast.makeText(this, "Tes os pes na terra ", Toast.LENGTH_SHORT).show();<br />
Log.i("DEPURACIÓN BOTÓN", "Dentro if");<br />
<br />
} else if (et.getText().toString().equals("")) {<br />
Toast.makeText(this, "Non escribiches nada", Toast.LENGTH_SHORT).show();<br />
Log.i("DEPURACIÓN BOTÓN", "Dentro else if");<br />
<br />
} else<br />
<br />
{<br />
Toast.makeText(this, "Estás noutro planeta", Toast.LENGTH_SHORT).show();<br />
Log.i("DEPURACIÓN BOTÓN", "Dentro else");<br />
<br />
}<br />
<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
*'''Liñas 18-22''': A aplicación emite mensaxes a través dos métodos estáticos con distintos niveis de criticidade.<br />
**A etiqueta (tag) é o primeiro campo.<br />
*'''Liñas 38,42,48''': emisión de mensaxes que nos axudan a saber porque parte do código se atopa a aplicación.<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Intents_expl%C3%ADcitos&diff=57148Intents explícitos2015-07-28T08:25:51Z<p>Angelfg: </p>
<hr />
<div>==Intents explícitos==<br />
*Crear o proxecto: '''U3_20_Intents'''.<br />
<br />
*Imos comezar usando os Intents de forma '''explícita''', primeiro chamando a unha segunda activity que imos crear nós e logo chamando á calculadora.<br />
*Finalmente chamaremos a distintas activities, como contactos, navegador web, etc de forma '''implícita'''.<br />
*En calquera dos casos imos pasar información entre as Activities, ben dende a que chama á chamada, como viceversa.<br />
<br />
*Como indicamos imos comezar creando unha Aplicación con 2 Activities: unha principal e outra secundaria.<br />
*Logo lanzaremos a calculadora do sistema.<br />
<br />
<br />
==Lanzar unha segunda Activity propia da aplicación==<br />
*Crear o proxecto: '''U3_20_Intents'''.<br />
<br />
<gallery caption="Chamadas entre Activities" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_50_LanzarActivity_06.jpg| Dende a pantalla principal vaise introducir un nome. Cando se prema o botón chamarase á segunda acivity que recibira o valor do cadro de texto. Ademais nesta primeira pantalla temos a opción de destruír esa activity no momento de chamar á segunda.<br> Aconséllase experimentar con esa opción e usar o botón '''Back''' unha vez que se está na segunda Activity.<br />
Image:Android_2013_U2_50_LanzarActivity_07.jpg| Segunda pantalla que recibe a información da primeira e ademais ten un botón para destruír esta segunda Activity ...<br />
Image:Android_2013_U2_50_LanzarActivity_07A.jpg| ... se prememos o botón '''Pechar''' lánzase un Toast dende o método '''finish()''' da segunda Activity que indica se a segunda Activity foi pechada dende o botón '''Pechar''' ou ....<br />
Image:Android_2013_U2_50_LanzarActivity_07B.jpg| ... dende o botón '''Retroceso/Back''' da botonera.<br />
<br />
</gallery><br />
<br />
==Creación dunha segunda Activity==<br />
*Pódese facer manualmente ou a través da utilidade que proporciona o IDE para crear unha Activity.<br />
<gallery caption="Creación dunha segunda Activity" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_50_LanzarActivity_01.jpg| Ir ao menú '''File->New->Other'''<br />
Image:Android_2013_U2_50_LanzarActivity_02.jpg| Escoller '''Android Activity'''<br />
Image:Android_2013_U2_50_LanzarActivity_03.jpg| Activity en branco.<br />
Image:Android_2013_U2_50_LanzarActivity_04.jpg| Escoller en que proxecto creala e o nome, neste caso: RecibirDatos. Premer '''Next'''.<br />
Image:Android_2013_U2_50_LanzarActivity_04A.jpg| Observar como nos indica que vai modificar por nós o Arquivo '''AndroidManifest.xml''' <br />
Image:Android_2013_U2_50_LanzarActivity_05.jpg| Observar que a ferramenta xa nos creou<br>- un XML e <br>- unha Clase Java para esa Activity.<br>Agora só resta codificar e deseñar o layout.<br />
Image:Android_2013_U2_50_LanzarActivity_08.jpg|O ficheiro '''AndroidManifest.xml''', creando a entrada para a nova Activity. Para indicar que agora temos unha nova actividade na aplicación. Indicando o seu nome e etiqueta.<br>Observar como a Activity principal (U3_20_Intents) ten un filtro que indica que é a Activity principal da aplicación e que é a través da que se lanza a Aplicación. <br />
</gallery><br />
<br />
===O XML do layout da Activity principal===<br />
*Observar na '''liña 41''' que chamamos á segunda actividade co atributo xml: android:onClick<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="41" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical"<br />
android:padding="5dp" ><br />
<br />
<LinearLayout<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:orientation="horizontal" ><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Dime o teu nome" /><br />
<br />
<EditText<br />
android:id="@+id/et_nome"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content" /><br />
</LinearLayout><br />
<br />
<CheckBox<br />
android:id="@+id/chk_destruir"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:checked="false"<br />
android:text="Destruír esta activity ao chamar á 2ª" /><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:layout_gravity="center_horizontal"<br />
android:text="Chamadas explícitas a intents"<br />
android:textColor="#00F" /><br />
<br />
<Button<br />
android:id="@+id/btn_enviar"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:onClick="onEnviarClick"<br />
android:text="Chamar 2ª Activity: Recibir Datos" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
===A clase Java a activity principal===<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="14,32-42" ><br />
package com.example.u3_20_intents;<br />
<br />
import android.app.Activity;<br />
import android.content.Intent;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.CheckBox;<br />
import android.widget.TextView;<br />
import android.widget.Toast;<br />
<br />
public class U3_20_Intents extends Activity {<br />
<br />
public final static String NOME = "nome";<br />
<br />
TextView tvNome;<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u3_20__intents);<br />
tvNome = (TextView) findViewById(R.id.et_nome);<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u3_20__intents, menu);<br />
return true;<br />
}<br />
<br />
public void onEnviarClick(View view) {<br />
CheckBox chkDestruir = (CheckBox) findViewById(R.id.chk_destruir);<br />
<br />
Intent intent = new Intent(this, RecibirDatos.class);<br />
intent.putExtra(NOME, tvNome.getText().toString());<br />
<br />
startActivity(intent);<br />
<br />
if (chkDestruir.isChecked())<br />
finish();<br />
}<br />
<br />
public void finish() {<br />
super.finish();<br />
Toast.makeText(this, "Mataches a actividade principal", Toast.LENGTH_SHORT).show();<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
*'''Liña 14''': Definimos unha constante de tipo String, chamada NOME. Observar que é pública.<br />
*'''Liña 35''': Creamos un obxecto de tipo '''Intent'''. O construtor recibe 2 parámetros:<br />
**O primeiro parámetro é unha referencia ao contexto (a clase Activity é unha subclase de Context, por iso poñemos this).<br />
**O segundo parámetro é a clase que o sistema ‘intentará’ cargar (no noso caso o nome da clase asociada á Activity que desexamos cargar).<br />
*'''Liña 36''': Asignamos ao intent un par CHAVE-VALOR a través do método '''putExtra()'''. Neste caso un valor String a través de NOME, definido na liña 14.<br />
**Tamén poderíamos non usar a constante: intent.putExtra("nome", tvNome.getText().toString())<br />
*'''Liña 38''': Lanzamos a Activity<br />
*'''Liña 40-41''': Se o CheckBox do Layout está marcado entón destruímos esta Activity:<br />
**Realizar probas marcando e desmarcando esta marca e premendo despois o botón '''Back''' da Segunda Activity..<br />
<br />
===O XML da Activity que recibe a chamada===<br />
<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="20" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<TextView<br />
android:id="@+id/tv_resultado"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:layout_gravity="center_horizontal"<br />
android:text="resultado"<br />
android:textSize="20sp" /><br />
<br />
<Button<br />
android:id="@+id/btn_pechar"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:layout_gravity="center_horizontal"<br />
android:onClick="onPecharClick"<br />
android:text="Pechar" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
===A clase Java da Activity que recibe a chamada. Activity Secundaria.===<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="11,12,18,22,24,35-38,42-44" ><br />
package com.example.u3_20_intents;<br />
<br />
import android.app.Activity;<br />
import android.content.Intent;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.TextView;<br />
import android.widget.Toast;<br />
<br />
public class RecibirDatos extends Activity {<br />
String Forma_Pechar_Activity;<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_recibir_datos);<br />
Forma_Pechar_Activity = " Premendo botonera Retroceso";<br />
<br />
TextView tvResultado = (TextView) findViewById(R.id.tv_resultado);<br />
<br />
Intent intent = getIntent();<br />
<br />
tvResultado.setText("Ola " + intent.getExtras().getString(U3_20_Intents.NOME));<br />
<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.recibir_datos, menu);<br />
return true;<br />
}<br />
<br />
public void onPecharClick(View view) {<br />
Forma_Pechar_Activity = " Premendo botón Pechar";<br />
<br />
finish();<br />
<br />
}<br />
<br />
public void finish() {<br />
super.finish();<br />
Toast.makeText(this, "Saíches da actividade secundaria: " + Forma_Pechar_Activity, Toast.LENGTH_SHORT).show();<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
*Para recuperar a información na segunda Activty hai que realizalo cando se está creando a Activity, pode ser nun método a parte chamado dende o onCreate() ou no propio onCreate();<br />
*'''Liña 11''': Observar o nome da nova Clase.<br />
*'''Liña 12''': Variable tipo String para gardar a forma na que se sae da segunda activity: Botón '''Pechar''' ou tecla '''Back'''.<br />
*'''Liña 18''': Por defecto asignamos a esa variable que se sae da segunda Activty premendo o botón '''Back'''. <br />
*'''Liña 12''': Creamos un intent onde recollemos cal foi o intent que iniciou esta Activity.<br />
*'''Liña 24''': Collemos a información que viña en NOME e mostrámola nunha etiqueta de texto.<br />
*'''Liña 35-38''': se se preme o botón de pechar destruirase esta Activity e cambiamos o valor da variable String.<br />
*'''Liña 42-44''': Como xa se sabe da parte anterior do Cliclo de Vida dunha Activity este método (finish()) execútase cando se destrúe a Activity.<br />
<br />
==Pasar datos da actividade secundaria á principal==<br />
*Até agora pasamos datos da actividade principal á secundaria.<br />
*Imos modificar a aplicación anterior, para que na secundaria se poida introducir o apelido dunha persoa e este se pase á actividade principal.<br />
*Ademais imos controlar na Actividade Principal se se volveu da actividade secundaria premendo o botón '''Pechar''' ou a botonera '''Back'''.<br />
<br />
<br />
<gallery caption="Paso de valores da Activity Secundaria á Principal" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_50_LanzarActivity_06.jpg| Igual que antes dende a pantalla principal vaise introducir un nome. Premer no botón que lanza a segunda actividade.<br />
Image:Android_2014_U3_20_LanzarActivity_10.jpg|Agora aparte de recibir o Nome da Actividade Principal, podemos escribir na Actividade Secundaria os apelidos da persoa e premer en Pechar. <br />
Image:Android_2014_U3_20_LanzarActivity_11.jpg| Observar como a actividade Principal amosa os apelidos introducidos na Actividade Secundaria.<br />
Image:Android_2014_U3_20_LanzarActivity_12.jpg| Nesta ocasión retornouse da actividade secundaria á Principal premendo na botonera '''Back'''.<br />
</gallery><br />
<br />
*A continuación vanse ver os cambios introducidos no código anterior.<br />
<br />
===Pasar datos da secundaria á principal: A clase Java da Activity principal===<br />
<br />
*A continuación vaise indicar o código que se engadiu ou modificou con respecto ao anterior.<br />
*Agora á actividade secundaria chámase con método '''startActivityForResult(intent, número)'''. Este método indícalle que esperamos que nos devolva un resultado cando esta remate.<br />
*O número que lle pasamos á actividade secundaria é o que nos vai devolver esta cando se peche e así cando se volva á actividade principal, nesta, co método '''onActivityResult(int requestCode, int resultCode, Intent data)''' podemos comprobar que número nos devolve a actividade que nos pasa o control e actuar en consecuencia.<br />
<br />
<br />
*'''Referencias''':<br />
**http://developer.android.com/reference/android/app/Activity.html#startActivityForResult%28android.content.Intent,%20int%29<br />
**http://developer.android.com/reference/android/app/Activity.html#onActivityResult%28int,%20int,%20android.content.Intent%29<br />
<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="15,39,40, 46-57" ><br />
package com.example.u3_20_intents;<br />
<br />
import android.app.Activity;<br />
import android.content.Intent;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.CheckBox;<br />
import android.widget.TextView;<br />
import android.widget.Toast;<br />
<br />
public class U3_20_Intents extends Activity {<br />
<br />
public final static String NOME = "com.example.NOME";<br />
private static final int COD_PETICION = 33;<br />
<br />
TextView tvNome;<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u3_20__intents);<br />
tvNome = (TextView) findViewById(R.id.et_nome);<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u3_20__intents, menu);<br />
return true;<br />
}<br />
<br />
public void onEnviarClick(View view) {<br />
CheckBox chkDestruir = (CheckBox) findViewById(R.id.chk_destruir);<br />
<br />
Intent intent = new Intent(this, RecibirDatos.class);<br />
intent.putExtra(NOME, tvNome.getText().toString());<br />
<br />
// startActivity(intent);<br />
startActivityForResult(intent, COD_PETICION);<br />
<br />
if (chkDestruir.isChecked())<br />
finish();<br />
}<br />
<br />
protected void onActivityResult(int requestCode, int resultCode, Intent data) {<br />
<br />
if (requestCode == COD_PETICION) {<br />
if (resultCode == RESULT_OK) {<br />
if (data.hasExtra("APELIDO"))<br />
Toast.makeText(this, tvNome.getText() + "\nO teu apelido é: " + data.getExtras().getString("APELIDO"), Toast.LENGTH_SHORT).show();<br />
<br />
} else<br />
Toast.makeText(this, "Saíches da actividade secundaria sen premer o botón Pechar", Toast.LENGTH_SHORT).show();<br />
}<br />
<br />
}<br />
<br />
public void finish() {<br />
super.finish();<br />
Toast.makeText(this, "Mataches a actividade principal", Toast.LENGTH_SHORT).show();<br />
}<br />
<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Liña 15''': Creamos unha constante enteira e asinámoslle un número calquera, que se lle vai pasar á actividade secundaria cando se chame e que ela nos vai devolver cando se peche.<br />
*'''Liña 39''': Comentamos o método co que chamabamos antes á actividade secundaria.<br />
*'''Liña 40''': Chamamos ao intent asociado á actividade secundaria, pasándolle un número que logo nos devolverá cando esta se peche e devolva o control á actividade principal.<br />
*'''Liña 46''': o método onActivityResult (int requestCode, int resultCode, Intent data) actívase cando se volve dunha actividade secundaria. <br />
**En '''requestCode''': recollemos o código que nos envía esa actividade secundaria, e así controlando ese código podemos saber de que actividade secundaria se regresou á principal.<br />
**En '''resultCode''': recibimos o código que nos pasaron dende a actividade secundaria:<br />
***''public static final int RESULT_CANCELED= 0 (0x00000000)''. Para cando queremos indicar que na actividade secundaria se cancelou algo.<br />
***''public static final int RESULT_OK= -1 (0xffffffff)''. Para cando queremos indicar que o que se tiña que facer na activity secundaria fíxose correctamente.<br />
**'''data''': recibimos o intent que nos envía a clase secundaria, e que podemos ver se nos pasa algún valor do estilo CHAVE-VALOR, url, etc.<br />
*'''Liña 48''': Comprobamos se á volta á actividade principal é por mor da actividade secundaria: '''RecibirDatos''' que chamamos antes co número 33.<br />
*'''Liña 49''': Comprobamos se na activity secundaria se concluíu dun xeito exitoso. Se non é así, unha das razóns polas que non se puido rematar foi porque se premeu o botón '''Back''' (liña 54).<br />
*'''Liña 50''': comprobamos se o intent '''data''' ten un campo '''APELIDO''' de ser así ...<br />
*'''Liña 51''': ... extraemos o seu valor e amosamos a través dun Toast.<br />
<br />
===Pasar datos da secundaria á principal: O XML da activity secundaria===<br />
*Só se engadiu un EditText.<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="15-20" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<TextView<br />
android:id="@+id/tv_resultado"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:layout_gravity="center_horizontal"<br />
android:text="resultado"<br />
android:textSize="20sp" /><br />
<br />
<EditText<br />
android:id="@+id/et_apelido"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:layout_gravity="center_horizontal"<br />
android:hint="Introduce o teu apelido" /><br />
<br />
<Button<br />
android:id="@+id/btn_pechar"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:layout_gravity="center_horizontal"<br />
android:onClick="onPecharClick"<br />
android:text="Pechar" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
===Pasar datos da secundaria á principal: A clase Java da Activity secundaria===<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="12,18,36,39-41,48,49" ><br />
package com.example.u3_20_intents;<br />
<br />
import android.app.Activity;<br />
import android.content.Intent;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.EditText;<br />
import android.widget.TextView;<br />
<br />
public class RecibirDatos extends Activity {<br />
// String Forma_Pechar_Activity;<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_recibir_datos);<br />
// Forma_Pechar_Activity = " Premendo botonera Retroceso";<br />
<br />
TextView tvResultado = (TextView) findViewById(R.id.tv_resultado);<br />
<br />
Intent intent = getIntent();<br />
<br />
tvResultado.setText("Ola " + intent.getExtras().getString(U3_20_Intents.NOME));<br />
<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.recibir_datos, menu);<br />
return true;<br />
}<br />
<br />
public void onPecharClick(View view) {<br />
// Forma_Pechar_Activity = " Premendo botón Pechar";<br />
EditText et_apelido = (EditText) findViewById(R.id.et_apelido);<br />
<br />
Intent datos_volta = new Intent();<br />
datos_volta.putExtra("APELIDO", et_apelido.getText().toString());<br />
setResult(RESULT_OK, datos_volta);<br />
finish();<br />
<br />
}<br />
<br />
public void finish() {<br />
super.finish();<br />
// Toast.makeText(this, "Saíches da actividade secundaria: " +<br />
// Forma_Pechar_Activity, Toast.LENGTH_SHORT).show();<br />
}<br />
<br />
}<br />
</syntaxhighlight ><br />
*'''Liñas 12,18,36,48 e 49''': Comentámolas pois agora na actividade principal xa somos quen de saber se o usuario premeu ou non o botón Pechar ou Back.<br />
*'''Liña 39''': Creamos un novo intent.<br />
*'''Liña 40''': Engadimos datos extendidos ao intent, neste caso o par: APELIDO-Valor.<br />
*'''Liña 41''': setResult envíalle o resultado á activity chamadora.<br />
<br />
<br />
==Chamar a unha activity doutra aplicación: á calculadora==<br />
*A continuación imos engadir máis código ás clases e xmls anteriores para poder chamar a unha activity doutra aplicación, neste caso do sistema.<br />
*Imos facelo de forma explícita.<br />
<br />
<gallery caption="Chamar á calculadora" widths="350" heights="300px" perrow="2"><br />
Image:Android_2014_U3_20_LanzarActivity_13.jpg| Premer no botón calculadora.<br />
Image:Android_2014_U3_20_LanzarActivity_14.jpg| Ábrese a Activity doutra aplicación. Neste caso a calculadora.<br />
</gallery><br />
<br />
===Chamar á calculadora: o xml da activity principal.===<br />
*Simplemente engadimos un novo botón (Liñas 44-49).<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="44-49" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical"<br />
android:padding="5dp" ><br />
<br />
<LinearLayout<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:orientation="horizontal" ><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Dime o teu nome" /><br />
<br />
<EditText<br />
android:id="@+id/et_nome"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content" /><br />
</LinearLayout><br />
<br />
<CheckBox<br />
android:id="@+id/chk_destruir"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:checked="false"<br />
android:text="Destruír esta activity ao chamar á 2ª" /><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:layout_gravity="center_horizontal"<br />
android:text="Chamadas explícitas a intents"<br />
android:textColor="#00F" /><br />
<br />
<Button<br />
android:id="@+id/btn_enviar"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:onClick="onEnviarClick"<br />
android:text="Chamar 2ª Activity: Recibir Datos" /><br />
<br />
<Button<br />
android:id="@+id/btn_calculadora"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:onClick="onCalculadoraClick"<br />
android:text="Calculadora" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
===Chamar á calculadora: A clase java da activity principal.===<br />
*Engadimos o código para procesar o evento onClick do botón (Liñas 59-65).<br />
<syntaxhighlight lang="java" line enclose="div" highlight="59-65" ><br />
package com.example.u3_20_intents;<br />
<br />
import android.app.Activity;<br />
import android.content.Intent;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.CheckBox;<br />
import android.widget.TextView;<br />
import android.widget.Toast;<br />
<br />
public class U3_20_Intents extends Activity {<br />
<br />
public final static String NOME = "com.example.NOME";<br />
private static final int COD_PETICION = 33;<br />
<br />
TextView tvNome;<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u3_20__intents);<br />
tvNome = (TextView) findViewById(R.id.et_nome);<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u3_20__intents, menu);<br />
return true;<br />
}<br />
<br />
public void onEnviarClick(View view) {<br />
CheckBox chkDestruir = (CheckBox) findViewById(R.id.chk_destruir);<br />
<br />
Intent intent = new Intent(this, RecibirDatos.class);<br />
intent.putExtra(NOME, tvNome.getText().toString());<br />
<br />
// startActivity(intent);<br />
startActivityForResult(intent, COD_PETICION);<br />
<br />
if (chkDestruir.isChecked())<br />
finish();<br />
}<br />
<br />
protected void onActivityResult(int requestCode, int resultCode, Intent data) {<br />
<br />
if (requestCode == COD_PETICION) {<br />
if (resultCode == RESULT_OK) {<br />
if (data.hasExtra("APELIDO"))<br />
Toast.makeText(this, tvNome.getText() + "\nO teu apelido é: " + data.getExtras().getString("APELIDO"), Toast.LENGTH_SHORT).show();<br />
<br />
} else<br />
Toast.makeText(this, "Saíches da actividade secundaria sen premer o botón Pechar", Toast.LENGTH_SHORT).show();<br />
}<br />
<br />
}<br />
<br />
public void onCalculadoraClick(View v) {<br />
<br />
Intent intent = new Intent();<br />
intent.setClassName("com.android.calculator2", "com.android.calculator2.Calculator");<br />
<br />
startActivity(intent);<br />
}<br />
<br />
public void finish() {<br />
super.finish();<br />
Toast.makeText(this, "Mataches a actividade principal", Toast.LENGTH_SHORT).show();<br />
}<br />
<br />
}<br />
<br />
</syntaxhighlight><br />
*'''Liña 62''': Nesta ocasión co método '''setClassName(String packageName, String className)''' indicámoslle no nome do paquete que contén a clase e nome da clase.<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=O_evento_onLongClick&diff=57145O evento onLongClick2015-07-28T08:20:28Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
Para continuar coa xestión de eventos imos ver como xestionar un click longo.<br />
<br />
==onLongClick()==<br />
*Cando sobre unha vista se preme por duración de 1 segundo ou máis lánzase o evento '''LongClick''' que é capturado polo método '''onLongClick()''' asociado ao correspondente interface.<br />
<br />
*O método onLongClick() devolve un booleano para poder comprobar se o evento se consumou ou non. Se chegamos a premer por un segundo (ou máis) ou non.<br />
**Devolve '''true''' se puidemos capturar o evento e xa non fai nada máis.<br />
**Devolve '''false''' se non se puido capturar o evento e continua chamando a outros escoitadores tipo on-Click.<br />
<br />
==Caso Práctico==<br />
*Comezamos creando o proxecto '''U3_03_OnLongClick'''<br />
<br />
*Esta actividade ten 2 vistas:<br />
**Un botón que se pode facer Click (usando a propiade do XML) e LongClick (capturado a través dun Listener)<br />
**Unha etiqueta de texto (en 2 liñas) na que se pode facer Click (hai que habilitalo) e LongClick. Neste último caso os dous eventos captúranse con cadanseu Listener.<br />
[[Image:Android_2013_U3_03_OnLongClick_01.jpg]]<br />
<br />
<br />
===XML do Layout===<br />
<br />
*Observar a '''Liña 20''' onde se habilita o TextView para sexa ''clickable''.<br />
*Agora poderíase engadir ao compoñente a propiedade: android:onClick="onBotonClick" <br />
<syntaxhighlight lang="xml" line enclose="div" highlight="20" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<Button<br />
android:id="@+id/boton"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:onClick="onBotonClick"<br />
android:text="Botón:\n<br />
onClick Layout\n<br />
onLongClick Listener" /><br />
<br />
<TextView<br />
android:id="@+id/text_view"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:clickable="true"<br />
android:text="Fai click e<br />
\nPreme aquí por máis de 1 seg"<br />
android:textSize="20sp" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
===Código Java===<br />
<syntaxhighlight lang="java" line enclose="div" highlight="21-28,33-40,42-49" ><br />
package com.example.u3_03_onlongclick;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.view.View.OnClickListener;<br />
import android.view.View.OnLongClickListener;<br />
import android.widget.Button;<br />
import android.widget.TextView;<br />
import android.widget.Toast;<br />
<br />
public class U3_03_OnLongClick extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u3_03__on_long_click);<br />
<br />
Button boton = (Button) findViewById(R.id.boton);<br />
boton.setOnLongClickListener(new OnLongClickListener() {<br />
@Override<br />
public boolean onLongClick(View v) {<br />
// TODO Auto-generated method stub<br />
Toast.makeText(v.getContext(), "Premeches 1 seg no botón", Toast.LENGTH_SHORT).show();<br />
return true;<br />
}<br />
});<br />
<br />
<br />
<br />
TextView tv = (TextView) findViewById(R.id.text_view);<br />
tv.setOnLongClickListener(new OnLongClickListener() {<br />
@Override<br />
public boolean onLongClick(View v) {<br />
// TODO Auto-generated method stub<br />
Toast.makeText(v.getContext(), "Premeches 1 seg na etiqueta de texto", Toast.LENGTH_SHORT).show();<br />
return true;<br />
}<br />
});<br />
<br />
tv.setOnClickListener(new OnClickListener() {<br />
<br />
@Override<br />
public void onClick(View v) {<br />
// TODO Auto-generated method stub<br />
Toast.makeText(v.getContext(), "Fixeches click na etiqueta de texto", Toast.LENGTH_SHORT).show();<br />
}<br />
});<br />
<br />
}<br />
<br />
public void onBotonClick(View v) {<br />
Toast.makeText(this, "Fixeches Click no botón", Toast.LENGTH_SHORT).show();<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u3_03__on_long_click, menu);<br />
return true;<br />
}<br />
<br />
}<br />
<br />
</syntaxhighlight><br />
*'''Liñas 21-28''':<br />
**Cando se faga un LongClick en ''boton'' este executará o método onLonClick() que devolverá true se se chegou a consumar o evento.<br />
**Probar a cambiar a liña 26 a '''return false''' e executar a aplicación. Que pasa?<br />
<br />
<br />
*'''Liñas 33-40''':<br />
**Acontece o mesmo que no caso anterior, so que para a etiqueta de texto.<br />
<br />
<br />
<br />
*'''Liñas 42-49''':<br />
**Se na etiqueta sucede o evento Click chámase ao Listener correspondente da etiqueta.<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=PDM:_Android._Obxectivos_e_escenarios_do_UNIDADE_3&diff=57142PDM: Android. Obxectivos e escenarios do UNIDADE 32015-07-28T08:19:23Z<p>Angelfg: </p>
<hr />
<div>*Nesta Unidade veremos:<br />
*O ciclo de vida dunha actividade<br />
*Escoitadores<br />
*Ventás de diálogo<br />
*Intents<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Librer%C3%ADas_de_compatibilidade&diff=57141Librerías de compatibilidade2015-07-28T08:19:08Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
<br />
* A medida que as versións do S.O. Android foron avanzando, apareceron novos controis e novas formas de xestionar os controis existentes.<br />
<br />
* Para facer compatible estas novidades cos dispositivos antigos, Android permite incorporar unha serie de librerías para facer que os dispositivos antigos poidan visualizar estes controis.<br />
<br />
<br />
*'''Referencias''':<br />
**Support Library: https://developer.android.com/tools/support-library/index.html<br />
<br />
==Creación de Activities==<br />
<br />
*Cando creamos unha activity nova pódese escoller (durante o asistente) a opción BlankActivity ou EmptyActivity.<br />
<br />
:*Se se escolle BlankActivity fai que a activity derive de ActionBarActivity para que amose unha barra de menú e que sexa compatible con versións anteriores a API 11. Ao facelo importaremos no noso proxecto a clase '''android.support.v7.app.ActionBarActivity''' e o mesmo tempo engadirá ao noso proxecto a librería '''appcompat_v7'''.<br />
<br />
:*Se se escolle EmptyActivity fai que a activity derive de Activity. Neste caso supoñemos que o min target API é 11 ou superior. Neste caso a barra de menú xa vai na propia activity e non hai que utilizar ningunha librería.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Estilos_e_temas&diff=57140Estilos e temas2015-07-28T08:18:21Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Os '''estilos''' permiten definir unhas características visuais para as vistas e agrupalas cun identificador que pode ser usado por diferentes compoñentes para que todos teñan o mesmo aspecto.<br />
*Un '''tema''' (theme) é aplicado a unha activity enteira (os seus elementos gráficos)<br />
*Un '''estilo''' é aplicado a compoñentes individuais.<br />
<br />
*Para definir un estilo temos que crear no cartafol '''/res/values''' un arquivo xml cun recurso (resource) de tipo estilo (style).<br />
<br />
<br />
*Cada ítem do ficheiro de estilos terá o par: propiedade xml, valor:<br />
**Exemplo: android:textSize -> "22sp"<br />
<br />
<br />
*'''Referencias''':<br />
**Estilos e temas: http://developer.android.com/guide/topics/ui/themes.html<br />
<br />
==Caso práctico==<br />
*Crear o proxecto: '''U2_42_Estilos'''.<br />
*Imos definir un estilo común para aplicar ás etiquetas de texto, por exemplo.<br />
<br />
<br />
<gallery caption="Estilos" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_42_Estilos_01.jpg| Crear un novo ficheiro xml en '''/res/values'''<br />
Image:Android_2013_U2_42_Estilos_02.jpg| Poñerlle un nome.<br />
Image:Android_2013_U2_42_Estilos_03.jpg| Ir ao ficheiro e engadir un elemento.<br />
Image:Android_2013_U2_42_Estilos_04.jpg| Engadir un recurso de tipo '''Style/Theme'''<br />
Image:Android_2013_U2_42_Estilos_05.jpg| Engadir un nome para o recurso e se é posible un pai.<br />
Image:Android_2013_U2_42_Estilos_06.jpg| Engadir un ...<br />
Image:Android_2013_U2_42_Estilos_07.jpg| ... ítem<br />
Image:Android_2013_U2_42_Estilos_08.jpg| Indicar a propiedade xml e o valor desexado<br />
Image:Android_2013_U2_42_Estilos_09.jpg| Ficheiro de estilos en formato xml<br />
Image:Android_2013_U2_42_Estilos_10.jpg| Etiquetas, todas como mesmo estilo/formato.<br />
</gallery><br />
<br />
<br />
===Ficheiro de estilos===<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="4-7" ><br />
<?xml version="1.0" encoding="utf-8"?><br />
<resources><br />
<style name="estilo_etiquetas" parent="@android:style/TextAppearance"><br />
<item name="android:layout_width">wrap_content</item><br />
<item name="android:layout_height">wrap_content</item><br />
<item name="android:textColor">#00F</item><br />
<item name="android:textSize">22sp</item><br />
<br />
</style><br />
<br />
</resources><br />
</syntaxhighlight><br />
<br />
===O XML do layout===<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="8,12,16" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<TextView<br />
style="@style/estilo_etiquetas"<br />
android:text="TextView 1" /><br />
<br />
<TextView<br />
style="@style/estilo_etiquetas"<br />
android:text="TextView 2" /><br />
<br />
<TextView<br />
style="@style/estilo_etiquetas"<br />
android:text="TextView 3" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Internacionalizaci%C3%B3n&diff=57136Internacionalización2015-07-28T08:12:37Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Tamén temos outras formas de ''personalizar'' as nosas aplicacións en base a unha serie de sufixos.<br />
*Se queremos que as cadeas de constantes estean traducidas a varios idiomas, só temos que crear un cartafol novo de nome '''values-??''' onde ?? é o idioma.<br />
*Para o inglés teriamos '''/res/values-en''', '''/res/values-es''' para o español,....<br />
*O idioma por defecto será o que estea gardado en '''/res/values'''.<br />
*So se deben cambiar os valores das contanstes, os identificadores deben ser os mesmos.<br />
<br />
<br />
*'''Referencias''':<br />
**Localización: http://developer.android.com/guide/topics/resources/localization.html<br />
<br />
==Caso práctico==<br />
*Crear un novo proxecto: '''U2_41_Internacional'''<br />
*Imos en '''/res/values''' definimos as cadeas de texto en galego e esas mesmas cadeas as definimos en inglés en /res/values-en'''.<br />
*Para probar a aplicación hai que cambiar o idioma do sistema como se viu na Unidade 1.<br />
<gallery caption="TableLayout Dinánico" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_41_Internacional_01.jpg| Cartafois de recursos: values e values-en. cada un co seu ficheiro de strings.<br />
Image:Android_2013_U2_41_Internacional_02.jpg| A aplicación está en galego, tanto no layout como no código (Toast).<br />
Image:Android_2013_U2_41_Internacional_03.jpg| E o mesmo pasa en inglés. O layout e o código Java é o mesmo para os dous casos.<br />
</gallery><br />
<br />
===strings.xml de /res/values===<br />
<br />
<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="1" ><br />
<?xml version="1.0" encoding="utf-8"?><br />
<resources><br />
<br />
<string name="app_name">U2_41_Internacional</string><br />
<string name="action_settings">Settings</string><br />
<string name="idioma">Esta aplicación, por defecto, está en galego!</string><br />
<string name="boton">Preme aquí</string><br />
<string name="mensaxe_toast">Premeches o botón!</string><br />
<br />
</resources><br />
<br />
</syntaxhighlight><br />
<br />
<br />
===strings.xml de /res/values-en===<br />
<br />
<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="1" ><br />
<?xml version="1.0" encoding="utf-8"?><br />
<resources><br />
<br />
<string name="app_name">U2_41_Internacional</string><br />
<string name="action_settings">Settings</string><br />
<string name="idioma">This app is by default in galician language!</string><br />
<string name="boton">Click here</string><br />
<string name="mensaxe_toast">You have clicked on the button!</string><br />
<br />
</resources><br />
<br />
</syntaxhighlight><br />
<br />
===O XML do layout===<br />
<br />
<br />
<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="10,15,16" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="@string/idioma" /><br />
<br />
<Button<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="@string/boton"<br />
android:onClick="onBotonClick" /><br />
<br />
<br />
</LinearLayout><br />
<br />
</syntaxhighlight><br />
*'''Liñas 10 e 15''': Agora temos que traballar con constantes, non podemos poñer o texto a ''lume''.<br />
<br />
===O código Java===<br />
<syntaxhighlight lang="java" line enclose="div" highlight="25" ><br />
package com.example.u2_41_internacional;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.Toast;<br />
<br />
public class U2_41_Internacional extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_41__internacional);<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_41__internacional, menu);<br />
return true;<br />
}<br />
<br />
public void onBotonClick(View v) {<br />
Toast.makeText(this, R.string.mensaxe_toast, Toast.LENGTH_SHORT).show();<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
*'''Liña 25''' observar como o toast tamén colle a cadea de texto dos recursos tipo string.<br />
<br />
==Consideracións a ter en conta==<br />
<br />
Estes sufixos que estamos a utilizar (-land; -es) poden ser combinados entre eles e con outros moitos diferentes.<br />
<br />
No seguinte [http://developer.android.com/guide/topics/resources/providing-resources.html#table2 enlace] aparece dita orde de prefixos.<br />
<br />
Por exemplo:<br />
*res/values-en-rUS/strings.xml<br />
*res/values-en-rUK/strings.xml<br />
<br />
Onde o segundo sufixo fai referencia a inglés ‘americano’ (en-rUS) ou ‘ inglés’ do Reino Unido (en-rUK).<br />
<br />
<u>Nota</u>: a letra r fai referencia á rexión.<br />
<br />
Para facilitarnos o traballo, Eclipse dispón dunha pantalla na que podemos indicar que 'características' queremos que teña o noso arquivo de recursos e automaticamente xa engade por nós os sufixos necesarios.<br />
<br />
Cando creamos un arquivo de recursos aparece a seguinte pantalla:<br />
<br />
[[Archivo:Android_2013_U2_41_Internacional_04.jpg|300px|thumb|left]] <br />
<br />
<div style="clear:both;"><br />
<br />
Se prememos o botón 'Next' pasamos á pantalla comentada anteriormente. Neste exemplo estamos a crear un recurso de tipo layout para pantallas de 7-10 pulgadas (tamaño x-large), entón teríamos que crear un layout nun cartafol ‘layout-xlarge’:<br />
<br />
[[Archivo:Android_2013_U2_41_Internacional_05.jpg|300px|thumb|left]] <br />
<br />
* Debemos pasar a 'propiedade' SIZE dende a lista da esquerda á dereita (premendo o botón coa dirección dereita). Unha vez pasada debemos darlle un valor, no noso caso x-large.<br />
* Ó facelo, podedes observar como na parte baixa aparece o nome co sufixo correcto.<br />
<br />
<div style="clear:both;"><br />
<br />
Podemos combinar moitas máis 'propiedades'. Así, no seguinte exemplo, estamos a crear un arquivo de recursos de tipo 'Values' que se cargará cando utilicemos un dispositivo Android, co idioma Español, nunha pantalla de tipo Small e cunha densidade Media.<br />
<br />
[[Archivo:Android_2013_U2_41_Internacional_06.jpg|300px|thumb|left]]<br />
<br />
* O sufixo que crea neste caso será: -es-small-mdpi.<br />
<br />
<br />
<div style="clear:both;"><br />
<br />
*Na versión '''Lollipop''' (API 21, android 5.0) xa se inclúe o idioma galego.<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Dese%C3%B1os_diferentes_en_funci%C3%B3n_da_orientaci%C3%B3n_do_dispositivo&diff=57135Deseños diferentes en función da orientación do dispositivo2015-07-28T08:11:29Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
* Algúns dispositivos deixan rotar a pantalla, poñéndoa en posición horizontal-vertical (apaisado-retrato)<br />
*Se queremos ter un deseño diferente para cada orientación, debemos de crear un cartafol dentro de ‘res’ de nome '''/res/layout-land'''.<br />
*Aquí dentro poñemos os deseños que queiramos ter cunha orientación apaisada do dispositivo, mentres que deixaremos en '''/res/layout''' os deseños para unha orientación vertical.<br />
<br />
'''Nota''': no emulador, para cambiar a orientación debemos premer os botóns '''CTRL+F11''' ou '''7''' no teclado numérico, sen estar activado o teclado numérico. <br />
<br />
*Antes de continuar abre a calculadora nun AVD ou no dispositivo real e cambia a orientación do dispositivo/AVD. Notas algunha diferencia cando o dispositivo está en Vertical a cando o está en Horizontal?.<br />
<br />
<br />
Veremos máis adiante, na sección [http://informatica.iessanclemente.net/manuais/index.php/Internacionalizaci%C3%B3n Internacionalización], como podemos xerar estes 'sufixos' de forma automática cando creamos o arquivo de recurso.<br />
<br />
*'''Referencias''':<br />
**Diferentes pantallas: http://developer.android.com/training/basics/supporting-devices/screens.html<br />
<br />
==Caso práctico==<br />
*Crear o proxecto: '''U2_40_Landscape'''<br />
*Crear en '''/res''' o cartafol '''layout-land'''.<br />
*Definir o XML vertical<br />
*Copiar o XML vertical á nova carpeta e modificalo segundo as necesidades.<br />
<br />
<gallery caption="Cambio de orientación" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_40_Landscape_01.jpg| Os ficheiros dos layouts para cada orientación<br />
Image:Android_2013_U2_40_Landscape_02.jpg| O dispositivo en vertical dispón os elementos de forma distinta<br />
Image:Android_2013_U2_40_Landscape_03.jpg| ... a se está en apaisado<br />
</gallery><br />
<br />
===XML layout vertical===<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="1" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical"<br />
android:gravity="center" ><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:textColor="#00F"<br />
android:textSize="18sp"<br />
android:text="O dispositivo está en posición vertical" /><br />
<br />
<Button <br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:onClick="oMeuMetodo"<br />
android:text="Botón 1" /><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:gravity="center_horizontal"<br />
android:text="Esta etiqueta só se amosa cando o dipositivo está en vertical" /><br />
<br />
</LinearLayout><br />
<br />
</syntaxhighlight><br />
<br />
<br />
<br />
===XML layout horizontal===<br />
*Observar que falta unha etiqueta, a disposición e distinta, etc.<br />
*Neste caso os botóns en Vertical e en Apaisado chaman ao mesmo método.<br />
<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="1" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="horizontal" ><br />
<br />
<Button<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:onClick="oMeuMetodo"<br />
android:text="Botón 1" /><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="O dispositivo está en posición horizontal"<br />
android:textColor="#F0F"<br />
android:textSize="18sp" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Xerar_Views_nun_Layout_en_tempo_de_execuci%C3%B3n._Layout_ScrollView&diff=57134Xerar Views nun Layout en tempo de execución. Layout ScrollView2015-07-28T08:11:02Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*A continuación vanse crear os elementos dun TableLayout en tempo de execución.<br />
*Os elementos dun TableLayout son as celas e cada unha vai ter un compoñente '''ImageView'''. Podería ser un botón, un texto, etc.<br />
*Ademais a través do Layout '''ScrollView''' vaise permitir facer scroll.<br />
<br />
<br />
*Referencias<br />
**O control ScrollView: http://developer.android.com/reference/android/widget/ScrollView.html<br />
**O control TableLayout: http://developer.android.com/reference/android/widget/TableLayout.html<br />
<br />
==Caso práctico==<br />
*Creamos unha novo proxecto: '''U2_33_TableLayoutDinamico'''<br />
<br />
<gallery caption="TableLayout Dinánico" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_33_TableLayoutDinamico_01.jpg| Ao iniciar a aplicación introducimos o número de filas e columnas que desexamos que teña o TableLayout que está disposto debaixo do botón.<br />
Image:Android_2013_U2_33_TableLayoutDinamico_02.jpg| Xeramos a táboa, e esta cárgase con ImageViews cuxa imaxe é a icona da aplicación.<br />
Image:Android_2013_U2_33_TableLayoutDinamico_04.jpg| Se prememos sobre unha imaxe.<br />
Image:Android_2013_U2_33_TableLayoutDinamico_03.jpg| Aparece un Toast amosando o seu Tag que indica a fila e columna na que está esa imaxe.<br />
</gallery><br />
<br />
<br />
===O XML do layout===<br />
*Imos centrarnos no novidoso:<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="39-49" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<TableLayout<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:stretchColumns="*" ><br />
<br />
<TableRow><br />
<br />
<EditText<br />
android:id="@+id/et_filas"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:hint="Filas"<br />
android:gravity="center"<br />
android:imeOptions="actionDone"<br />
android:inputType="number" /><br />
<br />
<EditText<br />
android:id="@+id/et_columnas"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:gravity="center"<br />
android:hint="Columnas"<br />
android:inputType="number" /><br />
</TableRow><br />
</TableLayout><br />
<br />
<Button<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:onClick="onXerarTaboaClick"<br />
android:text="Xerar táboa" /><br />
<br />
<ScrollView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content" ><br />
<br />
<TableLayout<br />
android:id="@+id/taboa_dinamica"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:stretchColumns="*" ><br />
</TableLayout><br />
</ScrollView><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
*'''ScrollView''': é un layout que permite activar o scroll vertical. Co cal, os elementos que haxa dentro poden crecer en vertical ao seu antollo, pois sempre se poderá realizar scroll.<br />
**Dentro dese Layout definiuse un TableLayout que non ten ningunha fila. Estas crearanse en tempo de execucion.<br />
*'''Liña 44''': observar que a táboa ten un ID para poder acceder a ela dende Java.<br />
<br />
===O código Java===<br />
<syntaxhighlight lang="java" line enclose="div" highlight="24-55" ><br />
package com.example.u2_33_tablelayoutdinamico;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.view.View.OnClickListener;<br />
import android.view.WindowManager;<br />
import android.widget.EditText;<br />
import android.widget.ImageView;<br />
import android.widget.TableLayout;<br />
import android.widget.TableRow;<br />
import android.widget.Toast;<br />
<br />
public class U2_33_TableLayoutDinamico extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_33__table_layout_dinamico);<br />
<br />
}<br />
<br />
public void onXerarTaboaClick(View v) {<br />
TableLayout taboa = (TableLayout) findViewById(R.id.taboa_dinamica);<br />
EditText filas = (EditText) findViewById(R.id.et_filas);<br />
EditText columnas = (EditText) findViewById(R.id.et_columnas);<br />
<br />
int f = Integer.parseInt(filas.getText().toString());<br />
int c = Integer.parseInt(columnas.getText().toString());<br />
<br />
taboa.removeAllViews();<br />
<br />
for (int i = 1; i <= f; i++) {<br />
TableRow fila = new TableRow(this);<br />
taboa.addView(fila);<br />
<br />
for (int j = 1; j <= c; j++) {<br />
ImageView imaxe = new ImageView(this);<br />
imaxe.setTag("Tag" + i + j);<br />
imaxe.setImageResource(R.drawable.ic_launcher);<br />
fila.addView(imaxe);<br />
imaxe.setOnClickListener(new OnClickListener() {<br />
<br />
@Override<br />
public void onClick(View v) {<br />
// TODO Auto-generated method stub<br />
ImageView img = (ImageView) v;<br />
Toast.makeText(getApplicationContext(),"Premeches na imaxe " + img.getTag(),Toast.LENGTH_SHORT).show();<br />
}<br />
});<br />
<br />
}<br />
}<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_33__table_layout_dinamico, menu);<br />
return true;<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
*'''Liña 25''': no obxecto '''taboa''' apuntamos á táboa definida no layout.<br />
*'''Liña 29,30''': f e c indican cantas filas e columnas debe ter o TableLayout. Lembrar que parseInt() é un método estático da clase Integer en Java.<br />
*'''Liña 32''': eliminamos todas as vistas que poida ter a táboa.<br />
*'''Liña 35,36''': engadimos tantos TableRows como filas nos indicou o usuario.<br />
*'''Liña 39,40,41''': creamos un obxecto ImageView co seu Tag e imaxe asociada.<br />
*'''Liña 42''': engadimos en cada fila tantas columnas como nos indicou o usuario a través de engadir, nese caso vistas do tipo ImageView. <br />
*'''Liña 43 a 51''' para cada unha das imaxes chamamos ao seu Listener que estará a espera de que se faga click nesa mesma imaxe que se acaba de crear.<br />
*'''Liña 46 a 50''' cando se preme nunha imaxe podemos coñecer, neste caso, cal é o seu Tag.<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Toast&diff=57133Toast2015-07-28T08:10:25Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Un '''Toast''' proporciona un simple feedback de algo que pasa na aplicación a través dunha pequena mensaxe popup.<br />
*Chámaselle así "Tostada" porque aparece na pantalla do mesmo xeito que as tostadas saltan na torradora cando están feitas.<br />
[[Image:00_toast.png]]<br />
*So usa o espazo que precise a mensaxe e a pantalla actual permanece visible.<br />
*Desaparecen automaticamente pasado un pequeno espazo de tempo.<br />
<br />
<br />
*Para usar o Toast:<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="5,6" ><br />
Context context = getApplicationContext();<br />
CharSequence text = "Hello toast!";<br />
int duration = Toast.LENGTH_SHORT;<br />
<br />
Toast toast = Toast.makeText(context, text, duration);<br />
toast.show();<br />
</syntaxhighlight><br />
*'''Context''': é un interface que permite acceder aos recursos da nosa aplicación<br />
*'''duration''':<br />
**'''LENGTH_SHORT''': constante que equivale a 2 segundos <br />
**'''LENGTH_LONG''': constante que equivale a 3,5 segundos<br />
<br />
<br />
*As liñas 5 e 6 anteriores poden ser substituídas pola seguinte:<br />
<syntaxhighlight lang="java" line enclose="div" highlight="1" ><br />
Toast.makeText(context, text, duration).show();<br />
</syntaxhighlight><br />
<br />
<br />
*'''Referencias''':<br />
**Clase Toast: http://developer.android.com/reference/android/widget/Toast.html<br />
**Introdución: http://developer.android.com/guide/topics/ui/notifiers/toasts.html<br />
<br />
==Caso práctico==<br />
*Comezamos creando o proxecto '''U2_15_Toast'''<br />
*Collendo como base a primeira versión da aplicación dos planetas: '''U2_12_Spinner'''.<br />
*Simplemente agora a nova aplicación ten unha entrada máis ao principio do Spinner '''Selecciona un planeta'''.<br />
<br />
<br />
<gallery caption="Autodestrucción" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_15_Toast_01.jpg| Contido do Spinner.<br />
Image:Android_2013_U2_15_Toast_02.jpg| Non se seleccionou ningún planeta (está seleccionado o ítem 0 do Spinner). Premer no botón.<br />
Image:Android_2013_U2_15_Toast_03.jpg| Aparece un aviso indicando que non se seleccionou ningún planeta (está seleccionada a entrada 0 do Spinner)<br />
Image:Android_2013_U2_15_Toast_04.jpg| Se seleccionamos un planeta funciona como se esperaba, só que agora a posición cambiou con respecto á aplicación orixinal.<br />
</gallery><br />
<br />
<br />
<br />
===Arquivo de recursos: array_planetas.xml===<br />
*Copiamos o ficheiro '''array_planetas.xml''' ubicado en '''/res/values/''' dunha aplicación á outra.<br />
<br />
*Engadimos un ítem ao principio:<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="4" ><br />
<?xml version="1.0" encoding="utf-8"?><br />
<resources><br />
<string-array name="planetas"><br />
<item>Selecciona un planeta</item><br />
<item>Mercurio</item><br />
<item>Venus</item><br />
<item>Terra</item><br />
<item>Marte</item><br />
<item>Xúpiter</item><br />
<item>Saturno</item><br />
<item>Urano</item><br />
<item>Neptuno</item><br />
</string-array><br />
</resources><br />
</syntaxhighlight><br />
<br />
<br />
===O XML do layout===<br />
*É igual ao da aplicación orixinal.<br />
<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="" ><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<Spinner<br />
android:id="@+id/spin_planetas"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:entries="@array/planetas" /><br />
<br />
<Button<br />
android:id="@+id/btn_seleccion"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:onClick="onButtonClick"<br />
android:text="Preme cando selecciones" /><br />
<br />
<TextView<br />
android:id="@+id/lbl_resultado"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Selecciona un planeta" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
<br />
<br />
<br />
===Código Java===<br />
<br />
*Ao método da aplicación orixinal engadímoslle un control: se esta seleccionada ou non a posición 0 do Spinner.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="30-31" ><br />
package com.example.u2_15_toast;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.Spinner;<br />
import android.widget.TextView;<br />
import android.widget.Toast;<br />
<br />
public class U2_15_Toast extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_15__toast);<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_15__toast, menu);<br />
return true;<br />
}<br />
<br />
public void onButtonClick(View v) {<br />
Spinner spinPlanetas = (Spinner) findViewById(R.id.spin_planetas);<br />
TextView lblResultado = (TextView) findViewById(R.id.lbl_resultado);<br />
<br />
if (spinPlanetas.getSelectedItemId() == 0) {<br />
Toast.makeText(this, "Por favor selecciona un planeta",Toast.LENGTH_LONG).show();<br />
lblResultado.setText("");<br />
} else<br />
<br />
lblResultado.setText("Seleccionaches "<br />
+ spinPlanetas.getSelectedItem()<br />
+ "\nque está na posición "<br />
+ spinPlanetas.getSelectedItemId());<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
*'''Liña 30''': Comprobamos se a posición seleccionada no Spinner é a 0 de ser así ...<br />
*'''Liña 31''': realizamos un Toast.<br />
*'''Liña 32''': Poñemos a etiqueta a baleiro.<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Chronometer._Cliclo_de_vida_I_(finish())&diff=57132Chronometer. Cliclo de vida I (finish())2015-07-28T08:09:56Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Un control '''Chronometer''' implementa en Android un cronómetro simple.<br />
*Iníciase con '''start()'''<br />
<br />
*Párase con stop(). Pero ... el segue contando por detrás. Isto é, se se executa de novo start() sen parámetros porá o cronómetro no mesmo tempo que se non se parase.<br />
<br />
*Cando se chama a '''start()''', o control colle o tempo que leva acceso o móbil ('''elapsedRealtime()''') como tempo base e vai contando dende aí.<br />
<br />
<br />
*Se non se lle dá un tempo base el colle o tempo no cal se chama a '''start()'''.<br />
<br />
<br />
*Para establecer un tempo base úsase '''setBase()'''<br />
<br />
<br />
*Por defecto amosa o tempo en formato "MM:SS". Pódese usar '''setFormat(String)''' para cambiar o formato.<br />
<br />
<br />
*A clase '''Chronometer''' herda directamente da clase '''View'''.<br />
<br />
<br />
*Para establecer os valores de tempos base apoiámonos na clase '''SystemClock'''.<br />
<br />
<br />
*'''Referencias''':<br />
**Clase Chronometer: http://developer.android.com/reference/android/widget/Chronometer.html<br />
**Clase SystemClock: http://developer.android.com/reference/android/os/SystemClock.html<br />
<br />
==Caso práctico==<br />
*Comezamos creando o proxecto '''U2_14_Chronometer'''<br />
*Creamos unha aplicación que cando ten un cronómetro que hai que iniciar e que pasado un tempo se non se parou a aplicación autodestrúese.<br />
<br />
<gallery caption="Autodestrucción" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_14_Chronometer_01.jpg| Ao iniciar a aplicación o crono está parado. Iniciámolo.<br />
Image:Android_2013_U2_14_Chronometer_02.jpg| O crono está en funcionamento e se non se para autodestruirase a aplicación en X seg. O valor de partida para a autodestrucción establécese nunha variable no código.<br />
Image:Android_2013_U2_14_Chronometer_03.jpg| Parouse o crono. Se se preme en Start, é como comezar de novo.<br />
</gallery><br />
<br />
<br />
<br />
===XML do Layout===<br />
<br />
*Observar como se crea o control Chronometer e os métodos aos que chaman os botóns.<br />
<syntaxhighlight lang="xml" line enclose="div" highlight="13-18,23,30,37" ><br />
<?xml version="1.0" encoding="utf-8"?><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<TextView<br />
android:id="@+id/tv_autodestruccion"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Autodestrucción en: ?? seg" /><br />
<br />
<Chronometer<br />
android:id="@+id/cronometro"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:layout_gravity="center_horizontal"<br />
android:textSize="20sp" /><br />
<br />
<LinearLayout<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:gravity="center_horizontal"<br />
android:orientation="horizontal" ><br />
<br />
<Button<br />
android:id="@+id/start"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:onClick="onStartClick"<br />
android:text="Start" /><br />
<br />
<Button<br />
android:id="@+id/stop"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:onClick="onStopClick"<br />
android:text="Stop" /><br />
</LinearLayout><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
===Código Java===<br />
<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="24-39,41-45,47-50" ><br />
package com.example.u2_14_chronometer;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.os.SystemClock;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.Chronometer;<br />
import android.widget.Chronometer.OnChronometerTickListener;<br />
import android.widget.TextView;<br />
<br />
public class U2_14_Chronometer extends Activity {<br />
Chronometer crono;<br />
TextView tvAutodestrucion;<br />
int tempoAutodestrucion;<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_14__chronometer);<br />
crono = (Chronometer) findViewById(R.id.cronometro);<br />
tvAutodestrucion = (TextView) findViewById(R.id.tv_autodestruccion);<br />
<br />
crono.setOnChronometerTickListener(new OnChronometerTickListener() {<br />
@Override<br />
public void onChronometerTick(Chronometer chronometer) {<br />
// TODO Auto-generated method stub<br />
<br />
long tempoPasado = SystemClock.elapsedRealtime()<br />
- chronometer.getBase();<br />
int tempoSeg = (int) tempoPasado / 1000;<br />
if (tempoSeg == tempoAutodestrucion)<br />
finish();<br />
<br />
tvAutodestrucion.setText("Autodestrucción en: "<br />
+ (tempoAutodestrucion - tempoSeg) + " seg");<br />
}<br />
});<br />
}<br />
<br />
public void onStartClick(View v) {<br />
tempoAutodestrucion = 20;<br />
crono.setBase(SystemClock.elapsedRealtime());<br />
crono.start();<br />
}<br />
<br />
public void onStopClick(View v) {<br />
crono.stop();<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_14__chronometer, menu);<br />
return true;<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
*'''Liña 42''': Definimos o tempo para a autodestrucción da Activity. Cando se vexan os menús, veremos que este valor podería ser configurado polo usuario que usa a aplicación, como unha opción da mesma. <br />
*'''Liña 43''': establécese o tempo base a partir do cal o cronómetro comeza a contar.<br />
**SystemClock.elapsedRealtime(): devolve o tempo, en milisegundos, que leva aceso o móbil<br />
*'''Liña 44''': o cronómetro comeza a contar, non dende cero, senón dende o tempo tomado como base (o tempo que leva acceso o móbil).<br />
*'''Liña 48''': párase o cronómetro.<br />
*'''Liña 24''': establécese o Listener do cronómetro. Este método vai ser chamado cada vez que o cronómetro cambia de valor.<br />
*'''Liñas 29 e 30''': O tempo que pasou dende que se iniciou o cronómetro é a diferencia entre o tempo que leva acceso o dispositivo e o tempo no cal se iniciou o cronómetro.<br />
*'''Liña 31''': Tempo en segundos.<br />
*'''Liña 33''': Se chegamos ao tempo para autodestrucción hai que matar a Activity. Sería o mesmo que se prememos o botón da botonera "Retroceso ou Back".<br />
<br />
==Ciclo de vida dunha actividade==<br />
*Afondarase máis adiante sobre o ciclo de vida dunha actividade.<br />
*Unha actividade desde que se lanza pasa por moitos estados. <br />
*Cando unha actividade non está en primeira liña da pantalla non está destruída senón que está en estado de Stop (Oculta) esperando na pila a ser chamada, ou se está moi abaixo na pila e se precisan os seus recursos entón o sistema pode destruíla.<br />
[[Image:00_basic-lifecycle.png|600px]]<br />
<br />
*No noso exemplo a actividade destrúese explicitamente se o cronómetro chega a un tempo determinado<br />
*Para iso úsase o método '''finish()'''. <br />
*Ver liña 33 do código.<br />
<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=ImageView&diff=57131ImageView2015-07-28T08:09:32Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Un control '''ImageView''' mostra en pantalla unha imaxe calquera.<br />
<br />
<br />
*Permite ser escalada ('''android:scaleType''') e tinguida (android:tint)<br />
<br />
<br />
*A clase '''ImageView''' herda directamente da clase '''View'''<br />
[[Image:00_Part_of_Android_View_Hierarchy.png|600px]]<br />
*Imaxe obtida de: http://www.itcsolutions.eu/2011/08/27/android-tutorial-4-procedural-vs-declarative-design-of-user-interfaces<br />
<br />
<br />
<br />
*'''Referencias''':<br />
**http://developer.android.com/reference/android/widget/ImageView.html<br />
<br />
==Caso práctico==<br />
*Comezamos creando o proxecto '''U2_13_ImageView'''<br />
*Creamos unha aplicación que cargue por defecto unha imaxe de "OK" e un botón.<br />
*Cando prememos no botón ou na imaxe cambia a imaxe por outra de "NON-OK" e así continuamente.<br />
<br />
<gallery caption="ImageView" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_13_ImageView_01.jpg| Iniciada a aplicación<br />
Image:Android_2013_U2_13_ImageView_02.jpg| Premer no botón cambia imaxe.<br />
Image:Android_2013_U2_13_ImageView_04.jpg| Premer na imaxe tamén a cambia.<br />
</gallery><br />
<br />
<br />
===Recursos de imaxes===<br />
*Crear o cartafol '''/res/values/drawable'''<br />
<br />
<gallery caption="Recursos de imaxes" widths="350" heights="300px" perrow="2"><br />
Image:ok.png| Descargar o boto ok.png<br />
Image:no.png| Descargar o boto no.png<br />
Image:Android_2013_U2_13_ImageView_03.jpg| Arrastralos ao cartafol anterior dentro do IDE. Lembrar que os nomes deben estar en minúsculas.<br />
</gallery><br />
<br />
===XML do layout===<br />
*Observar como se referencia á imaxe que vai cargar o control (liña12).<br />
*Os dous controles chaman ao mesmo método no caso de facer click neles.<br />
<br />
<syntaxhighlight lang="xml" line highlight="12,13,14,20"><br />
<?xml version="1.0" encoding="utf-8"?><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<ImageView<br />
android:id="@+id/img_imaxe"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:contentDescription="Imaxe"<br />
android:src="@drawable/ok"<br />
android:onClick="onCambiarImaxeClick"<br />
android:tag="OK" /><br />
<br />
<Button<br />
android:id="@+id/btn_cambiar_imaxe"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:onClick="onCambiarImaxeClick"<br />
android:text="Cambiar imaxe" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
*'''Liña 14''': Pónselle unha etiqueta á imaxe para poder controlar por código cal é a imaxe cargada.<br />
<br />
<br />
<br />
<br />
===Código Java===<br />
<syntaxhighlight lang="java" line highlight="30,31,34,35"><br />
package com.example.u2_13_imageview;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.ImageView;<br />
<br />
public class U2_13_ImageView extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_13__image_view);<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_13__image_view, menu);<br />
return true;<br />
}<br />
<br />
public void onCambiarImaxeClick(View view) {<br />
// ImageView img = (ImageView) view;<br />
<br />
ImageView img = (ImageView) findViewById(R.id.img_imaxe);<br />
<br />
if (img.getTag() == "OK") {<br />
img.setTag("NO");<br />
img.setImageResource(R.drawable.no);<br />
<br />
} else {<br />
img.setTag("OK");<br />
img.setImageResource(R.drawable.ok);<br />
}<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
*'''Liña 29''': comprobamos cal é o Tag da imaxe cargada.<br />
*'''Liña 30, 31''': se a imaxe é ok.png entón cargamos a de no.png e cambiamos a etiqueta. O mesmo se fai nas liñas 34 e 35.<br />
*A través da clase Java R accedemos ás imaxes.<br />
*'''Liña 25''': se o método se chama so dende a imaxe e non dende o botón poderíamos facer uso do parámetro view do método e comentar a liña 27.<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Spinner&diff=57130Spinner2015-07-28T08:08:55Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Un '''Spinner''' é unha lista despregable de opcións na que o usuario pode escoller unha delas.<br />
[[Image:00_spinners_form.png]]<br />
<br />
<br />
*Imos comezar usando o Spinner apoiándonos primeiro nun botón de texto.<br />
<br />
<br />
*Unha forma estática de definir os datos que van encher o Spinner é usando un arquivo de recursos de tipo '''String-array''':<br />
<br />
<br />
*'''Referencias'''<br />
**O control: http://developer.android.com/reference/android/widget/Spinner.html<br />
**Introdución: http://developer.android.com/design/building-blocks/spinners.html<br />
**Para programadores: http://developer.android.com/guide/topics/ui/controls/spinner.html<br />
<br />
==Caso práctico==<br />
*Crear o proxecto '''U2_12_Spinner'''<br />
*Nunha primeira versión imos crear unha aplicación que permita seleccionar un planeta nun Spiner e logo premendo un botón nos indicará o ítem seleccionado e a súa posición.<br />
<br />
<br />
<gallery caption="Spinner Planetas" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_12_Spinner_11.jpg| Aplicación recén iniciada.<br />
Image:Android_2013_U2_12_Spinner_12.jpg| Seleccionar Xúpiter (5º elemento da lista)<br />
Image:Android_2013_U2_12_Spinner_13.jpg| Premer o botón<br />
Image:Android_2013_U2_12_Spinner_14.jpg| Indícanos que seleccionamos Xúpiter e que está na posición 4. O índice do Spinner comeza en 0.<br />
</gallery><br />
<br />
===Arquivo de recursos: String-Array===<br />
<gallery caption="Crear array" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_12_Spinner_01.jpg| En '''/res/values''' crear un novo ficheiro XML de Android. <br />
Image:Android_2013_U2_12_Spinner_02.jpg| Indicar o nome, nesta caso: array_planetas e rematar.<br />
Image:Android_2013_U2_12_Spinner_03.jpg| Engadir un elemento ...<br />
Image:Android_2013_U2_12_Spinner_04.jpg| ... tipo String_Array <br />
Image:Android_2013_U2_12_Spinner_05.jpg| Poñerlle un nome ao recurso: planetas<br />
Image:Android_2013_U2_12_Spinner_06.jpg| Engadir un ...<br />
Image:Android_2013_U2_12_Spinner_07.jpg| ... ítem<br />
Image:Android_2013_U2_12_Spinner_08.jpg| Indicar un valor para ese ítem: Mercurio<br />
Image:Android_2013_U2_12_Spinner_09.jpg| Ficheiro en formaro XML, onde xa se pode copiar/pegar/modificar e crear o resto dos items. <br />
Image:Android_2013_U2_12_Spinner_10.jpg| <br />
</gallery><br />
<br />
<br />
*Ficheiro de recursos: array_planetas.xml.<br />
*Polo nome do string_array é por onde se vai acceder ao array.<br />
<syntaxhighlight lang="xml" line highlight="3"><br />
<?xml version="1.0" encoding="utf-8"?><br />
<resources><br />
<string-array name="planetas"><br />
<item>Mercurio</item><br />
<item>Venus</item><br />
<item>Terra</item><br />
<item>Marte</item><br />
<item>Xúpiter</item><br />
<item>Saturno</item><br />
<item>Urano</item><br />
<item>Neptuno</item><br />
</string-array><br />
</resources><br />
</syntaxhighlight><br />
<br />
<br />
<br />
===XML do Layout===<br />
<br />
*Observar como se crea un Spinner<br />
<syntaxhighlight lang="xml" line highlight="7-11,17"><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<Spinner<br />
android:id="@+id/spin_planetas"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:entries="@array/planetas" /><br />
<br />
<Button<br />
android:id="@+id/btn_seleccion"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:onClick="onButtonClick"<br />
android:text="Preme cando selecciones" /><br />
<br />
<TextView<br />
android:id="@+id/lbl_resultado"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Selecciona un planeta" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
*'''Liña 11''': é onde se vincula o Spinner co recurso tipo array: planetas.<br />
*'''Liña 17''': chamamos a un método cando se faga Click.<br />
<br />
<br />
<br />
===Código Java===<br />
<syntaxhighlight lang="java" line highlight="25-32"><br />
package com.example.u2_12_spinner;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.Spinner;<br />
import android.widget.TextView;<br />
<br />
public class U2_12_Spinner extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_12__spinner);<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_12__spinner, menu);<br />
return true;<br />
}<br />
<br />
public void onButtonClick(View v) {<br />
Spinner spinPlanetas = (Spinner) findViewById(R.id.spin_planetas);<br />
TextView lblResultado = (TextView) findViewById(R.id.lbl_resultado);<br />
<br />
lblResultado.setText("Seleccionaches "<br />
+ spinPlanetas.getSelectedItem() <br />
+ "\nque está na posición " + spinPlanetas.getSelectedItemId());<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
*'''Liñas 26,27''': Definimos os obxectos nos que recollemos os controis declarados no Layout.<br />
*'''Liñas 31,32''': seleccionamos o elemento da lista e a súa posición.<br />
<br />
===Capturar o evento cando se selecciona un ítem===<br />
*Nesta segunda versión vaise deixar que o botón siga realizando a súa función, pero agora cando seleccionemos un ítem que se capture o evento e que na etiqueta indicar cal é o planeta seleccionado e a súa posición.<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="19-42" ><br />
package com.example.u2_12_spinner;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.AdapterView;<br />
import android.widget.AdapterView.OnItemSelectedListener;<br />
import android.widget.Spinner;<br />
import android.widget.TextView;<br />
<br />
public class U2_12_Spinner extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_12__spinner);<br />
<br />
Spinner spinPlanetas = (Spinner) findViewById(R.id.spin_planetas);<br />
<br />
spinPlanetas.setOnItemSelectedListener(new OnItemSelectedListener() {<br />
<br />
@Override<br />
public void onItemSelected(AdapterView<?> parent, View view,<br />
int pos, long id) {<br />
// TODO Auto-generated method stub<br />
<br />
TextView lblResultado = (TextView) findViewById(R.id.lbl_resultado);<br />
<br />
lblResultado.setText("Seleccionaches "<br />
+ parent.getItemAtPosition(pos)<br />
+ "\nque está na posición " + pos);<br />
<br />
}<br />
<br />
@Override<br />
public void onNothingSelected(AdapterView<?> arg0) {<br />
// TODO Auto-generated method stub<br />
<br />
}<br />
});<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_12__spinner, menu);<br />
return true;<br />
}<br />
<br />
public void onButtonClick(View v) {<br />
Spinner spinPlanetas = (Spinner) findViewById(R.id.spin_planetas);<br />
TextView lblResultado = (TextView) findViewById(R.id.lbl_resultado);<br />
<br />
lblResultado.setText("Seleccionaches " + spinPlanetas.getSelectedItem()<br />
+ "\nque está na posición " + spinPlanetas.getSelectedItemId());<br />
}<br />
<br />
}<br />
<br />
</syntaxhighlight><br />
*'''Liña 21''': Listener que se chama cando se selecciona un elemento do Spinner<br />
*'''Liña 24''': O métod onItemSelected(AdapterView<?> parent, View view, int pos, long id) é chamado cando se selecciona un item distinto do xa seleccionado.<br />
*Parámetros:<br />
**parent: O elemento (AdapterView) onde se fixo a selección.<br />
**view: A vista que foi selecionada dentro do AdapterView<br />
**position: A posición da vista dentro do Adaptador.<br />
**id: Cada ítem pode ter varias filas (neste caso só ten unha) este campo indicaría a fila dentro do ítem<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=RadioButton&diff=57129RadioButton2015-07-28T08:08:30Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*O control '''RadioButton''' permite escoller unha opción entre varias posibles.<br />
*Aconséllase usar este control sempre que se queiran amosar ao usuario múltiples opcións, unha ao carón doutra.<br />
*En caso contrario débese usar un Spinner (Lista despregable).<br />
*No layout os '''RadioButton''' organízanse dentro dun '''RadioGroup''' que vai controlar que non haxa máis dunha opción marcada. <br />
<br />
[[Image:Radiobuttons.png|300px]]<br />
*Nota: ''polas opcións que ofrece a imaxe, tomada de Android SDK, aí debe traballar un galego''.<br />
<br />
<br />
*'''RadioGroup''' herda da clase '''LinearLayout''' co cal terá as súas propiedades, entre elas: '''android:orientation'''<br />
<br />
<br />
*'''RadioButton''' herda da clase '''CompoundButton''' ao igual que '''CheckBox'''. Por tanto, teremos dispoñible a propiedade '''android:onCLick'''.<br />
[[Image:00_Part_of_Android_View_Hierarchy.png|600px]]<br />
*Imaxe obtida de: http://www.itcsolutions.eu/2011/08/27/android-tutorial-4-procedural-vs-declarative-design-of-user-interfaces<br />
<br />
<br />
<br />
*'''Referencias:'''<br />
**Control RadioButton: http://developer.android.com/reference/android/widget/RadioButton.html<br />
**Control RadioGroup: http://developer.android.com/reference/android/widget/RadioGroup.html<br />
**Introdución ao control: http://developer.android.com/guide/topics/ui/controls/radiobutton.html<br />
<br />
==Caso práctico==<br />
*Creamos un novo proxecto: '''U2_11_RadioButton'''<br />
<br />
*Imos crear unha aplicación na que o usuario indique se é ou non maior de idade e que se amose a opción escollida no EditText.<br />
<br />
<gallery caption="RadioButton" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_11_RadioButton_01.jpg| Ao iniciar a aplicación aparece marcada por defecto a primeira opción. Pero aínda non se premeu en ningunha opción.<br />
Image:Android_2013_U2_11_RadioButton_02.jpg| Premer na primeira opción. <br />
Image:Android_2013_U2_11_RadioButton_03.jpg| Premer na segunda opción.<br />
</gallery><br />
<br />
===XML do Layout===<br />
<br />
*Observar como '''RadioGroup''' é un layout máis de tipo Linear.<br />
*Observar como a primeira opción está activada por defecto.<br />
<syntaxhighlight lang="xml" line highlight="6,9,25,15,16,23"><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<RadioGroup<br />
android:layout_width="fill_parent"<br />
android:layout_height="wrap_content"<br />
android:orientation="vertical" ><br />
<br />
<RadioButton<br />
android:id="@+id/rbtn_maior18"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:checked="true"<br />
android:onClick="controlarIdade"<br />
android:text=">18 anos" /><br />
<br />
<RadioButton<br />
android:id="@+id/rbtn_menor18"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:onClick="controlarIdade"<br />
android:text="&lt;=18 anos" /><br />
</RadioGroup><br />
<br />
<EditText<br />
android:id="@+id/txt_resultado"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:hint="Resultado" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
===Código Java===<br />
<br />
*Implementamos o método '''controlarIdade'''<br />
<syntaxhighlight lang="java" line highlight="24-36"><br />
package com.example.u2_11_radiobutton;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.EditText;<br />
<br />
public class U2_11_RadioButton extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_11__radio_button);<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_11__radio_button, menu);<br />
return true;<br />
}<br />
<br />
public void controlarIdade(View view) {<br />
<br />
EditText caixa = (EditText) findViewById(R.id.txt_resultado);<br />
<br />
switch (view.getId()) {<br />
case R.id.rbtn_maior18:<br />
caixa.setText("Tes máis de 18 anos");<br />
break;<br />
case R.id.rbtn_menor18:<br />
caixa.setText("Tes menos de 18 anos");<br />
break;<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
*'''Liña 30''': Indagamos que cal é o ID da opción na que se fixo click.<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=CheckBox&diff=57128CheckBox2015-07-28T08:07:55Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Un '''CheckBox''' permite ao usuario elixir unha ou máis opcións dentro dun conxunto.<br />
[[Image:00_checkboxes.png]]<br />
<br />
*Este control ao igual que ToggleButton e Switch herda da clase '''CompoundButton''', quen, á súa vez, herda da clase '''Button'''.<br />
[[Image:00_Part_of_Android_View_Hierarchy.png|600px]]<br />
*Imaxe obtida de: http://www.itcsolutions.eu/2011/08/27/android-tutorial-4-procedural-vs-declarative-design-of-user-interfaces<br />
<br />
<br />
<br />
<br />
*Por tanto, funcionan da mesma maneira, pero ademais este control:<br />
**Ten 2 estados (True/False), que podemos comprobar co método '''isChecked ()'''.<br />
<br />
<br />
*Para xestionar os eventos podemos facelo da mesma forma que nos botóns.<br />
<br />
<br />
*Para usalo nun XML layout usar a etiqueta <CheckBox/><br />
<br />
<br />
*'''Referencias:'''<br />
**O control CheckBox: http://developer.android.com/reference/android/widget/CheckBox.html<br />
**Introdución ao CheckBox: http://developer.android.com/guide/topics/ui/controls/checkbox.html<br />
<br />
==Caso práctico==<br />
*Creamos un novo proxecto: '''U2_10_CheckBox'''<br />
<br />
*Imos crear unha aplicación na que o usuario indique as súas afeccións ("Aficiones").<br />
<br />
<gallery caption="CheckBox" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_10_CheckBox_01.jpg| Ao entrar na aplicación non hai ningunha marcada. <br />
Image:Android_2013_U2_10_CheckBox_02.jpg| Cando se selecciona unha afección aparece unha mensaxe nunha caixa de texto indicando o que se seleccionou.<br />
Image:Android_2013_U2_10_CheckBox_03.jpg| Cando se deselecciona unha afección aparece unha mensaxe nunha caixa de texto indicando o que se deseleccionou. <br />
</gallery><br />
<br />
<br />
===Layout xml===<br />
<br />
*Cada '''CheckBox''' chama a un método cando se marca ou desmarca ese CheckBox.<br />
*O método é o mesmo para os tres.<br />
<br />
<syntaxhighlight lang="xml" line highlight="11,18,25"><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<CheckBox<br />
android:id="@+id/chk_informatica"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:onClick="controlarAfeccions"<br />
android:text="Informática" /><br />
<br />
<CheckBox<br />
android:id="@+id/chk_ler"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:onClick="controlarAfeccions"<br />
android:text="Ler" /><br />
<br />
<CheckBox<br />
android:id="@+id/chk_deporte"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:onClick="controlarAfeccions"<br />
android:text="Deportes" /><br />
<br />
<EditText<br />
android:id="@+id/txt_resultado"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:hint="Resultado" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
===Código Java===<br />
<syntaxhighlight lang="java" line highlight="25-33"><br />
package com.example.u2_10_checkbox;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.view.View;<br />
import android.widget.CheckBox;<br />
import android.widget.EditText;<br />
<br />
public class U2_10_CheckBox extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_10__check_box);<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_10__check_box, menu);<br />
return true;<br />
}<br />
<br />
public void controlarAfeccions(View view) {<br />
CheckBox check = (CheckBox) view;<br />
<br />
EditText caixa = (EditText) findViewById(R.id.txt_resultado);<br />
if (check.isChecked()) <br />
caixa.setText("Marcaches: " + check.getText());<br />
else<br />
caixa.setText("Desmarcaches: " + check.getText());<br />
}<br />
}<br />
</syntaxhighlight><br />
*'''Liña 25''', recibimos a Vista do elemento pulsado hai que facer un casting para convertelo ao tipo CheckBox.<br />
*'''Liña 29''', comprobamos se se marcou ou desmarcou o control.<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=EditText._Control_de_eventos_I&diff=57126EditText. Control de eventos I2015-07-28T07:46:19Z<p>Angelfg: /* Introdución */</p>
<hr />
<div>==Introdución==<br />
*O control '''EditText''' serve para introducir e editar texto por parte do usuario dunha aplicación Android.<br />
*Este control é unha subclase da clase '''TextView''' que se viu anteriormente.<br />
[[Image:00_Part_of_Android_View_Hierarchy.png|600px]]<br />
*Imaxe obtida de: http://www.itcsolutions.eu/2011/08/27/android-tutorial-4-procedural-vs-declarative-design-of-user-interfaces<br />
<br />
<br />
<br />
*A forma de engadir un EditText en XML nun layout é a través do compoñente: <EditText/><br />
*Unha propiedade importante é: '''android:inputType'''<br />
**Permitirá que so se introduzan números, texto, passwords, teléfonos, etc.<br />
**Tamén indicará se o control é dunha soa liña ou multiliña.<br />
**Facer que non autocomplete as palabras, etc.<br />
*Ademais permiten copiar, cortar e pegar.<br />
<br />
[[Image:00_edittext-noextract.png]]<br />
*Cando se entra nun cadro de texto, nun dispositivo que non teña teclado físico conectado, abrirase en pantalla un '''teclado virtual''' (tamén chamado lixeiro/soft) que se adaptará á propiedade '''android:inputType''' como veremos a continuación.<br />
<br />
*Finalmente a tecla '''Enter''' no teclado virtual poder realizar distintas accións, ben por defecto ou ben explicitamente coa propiedade '''android:imeOptions''' (IME: Input Method Editor)<br />
<br />
<br />
*'''Referencias''':<br />
**O control EditText: http://developer.android.com/reference/android/widget/EditText.html<br />
**Campos de texto: http://developer.android.com/design/building-blocks/text-fields.html<br />
**Campos de texto para programadores: http://developer.android.com/guide/topics/ui/controls/text.html<br />
**Filtros de entrada (android:inputType): http://developer.android.com/reference/android/widget/TextView.html#attr_android:inputType<br />
**IME: http://developer.android.com/guide/topics/text/creating-input-method.html<br />
**android:imeOptions: http://developer.android.com/reference/android/widget/TextView.html#attr_android:imeOptions<br />
<br />
<br />
<br />
*'''IMPORTANTE''': Se se vai usar un AVD imos desactivar o teclado hardware para que cando premamos nun cadro de texto nos apareza o teclado virtual.<br />
Lembrar que na imaxe aparece unha API 18 pero nos estamos traballando cunha API 16.<br />
<br />
[[Image:Android_2013_U2_08_EditText_01.jpg|400px]]<br />
*Desactivar o teclado por hardware<br />
<br />
==Casos prácticos==<br />
*Comezamos creando un proxecto no que realizar as probas: '''U2_08_EditText'''<br />
<br />
<br />
===Distintos tipos de datos: a propiedade android:inputType===<br />
*A imaxe amosa un AVD con distintos tipos de campos, e cunha lenda interior indicando que tipo de dato hai que introducir nese campo.<br />
[[Image:Android_2013_U2_08_EditText_02.jpg|300px]] <br />
<br />
*O layout xml que define esa pantalla é o seguinte. Observar como sempre as liñas marcadas.<br />
<br />
<syntaxhighlight lang="xml" line highlight="10,11,16,17,22,23,28,29,34,35"><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<EditText<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:hint="Escribe un número enteiro"<br />
android:inputType="numberSigned" /><br />
<br />
<EditText<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:hint="Escribe un número decimal"<br />
android:inputType="numberSigned|numberDecimal" /><br />
<br />
<EditText<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:hint="Escribe palabras...(saíra a 1ª letra en maísculas)"<br />
android:inputType="textCapWords|textMultiLine" /><br />
<br />
<EditText<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:hint="Enderezo e-mail. Esta línea sae por fóra da pantalla"<br />
android:inputType="textEmailAddress" /><br />
<br />
<EditText<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:hint="Escribe a clave."<br />
android:inputType="textPassword" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
*Propiedade '''android:hint''': indica o texto que se vai amosar no control cando este está baleiro.<br />
*Propiedade '''android:inputType''': indica o tipo de datos que se poden introducir no campo.<br />
**Se non se pon a propiedade, o campo acepta toda combinación de caracteres.<br />
**Pódense combinar os filtros facendo uso de '''"|"'''.<br />
*Obviamente os valores dos Hints é mellor telos declarados en constantes en recursos XML.<br />
<br />
<br />
*Lanzamos a aplicación nun AVD sen botonera hardware.<br />
*'''NOTA Edición 2015''': No caso de usar un AVD con API 21, o botón '''Next''' é substituído por '''">"''', o botón '''Done'' (Feito) por unha marca de verificación. <br />
<gallery caption="Distintos teclados" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_08_EditText_03.jpg| Cando nos posicionamos no primeiro campo, como é para enteiros con signo (inputType), ofrece un teclado con só números, signo "-" e "." ou ",".<br>Probar a introducir un número decimal.<br> Observar tamén que a tecla '''Enter''' foi substituída por '''Next''', para pasar ao seguinte campo. Pronto estudaremos esta tecla.<br />
Image:Android_2013_U2_08_EditText_04.jpg| O segundo campo xa admite números decimais e con signo. A tecla '''Enter''' segue marcando '''Next'''.<br />
Image:Android_2013_U2_08_EditText_05.jpg| O teclado xa contempla as letras e demais. Observar como de xeito automático pon en maiúsculas a primeira letra de cada palabra.<br />
Image:Android_2013_U2_08_EditText_06.jpg| Como o terceiro campo é multiliña a tecla de '''Enter''' é agora un retorno de carro para poder seguir escribindo varias liñas no campo. <br />
Image:Android_2013_U2_08_EditText_07.jpg| Situámonos co dedo (ou rato) no seguinte campo. Agora o teclado xa ofrece a @ para o mail. A tecla '''Enter''' segue sendo '''Next'''.<br />
Image:Android_2013_U2_08_EditText_08.jpg| E agora é o momento de introducir a password. Observar como a tecla '''Enter''' é agora '''Done''' (Feito). Porque este campo é último e xa non hai máis a continuación.<br />
Image:Android_2013_U2_08_EditText_09.jpg| Unha vez que se preme na tecla '''Done''' desaparece o teclado.<br />
<br />
</gallery><br />
<br />
===Control de eventos no teclado virtual. Distintas accións da tecla "Enter": android:imeOptions===<br />
*A tecla '''Enter''' no teclado virtual pode realizar unha serie de accións:<br />
**Por defecto:<br />
***o sistema determina se existe outro elemento ao que poida ir o foco, nese caso a función da tecla é '''Next'''. <br />
***Se non o atopa a acción da tecla é '''Done'''.<br />
***Salvo nalgúns '''inputType''' como por exemplo o multiliña.<br />
**Podemos asignar explicitamente que acción se desexa que se leve a cabo cada caixa de texto. Para iso está o atributo '''android:imeOptions'''.<br />
***Que dun campo vaia ao anterior, que envíe o texto, que busque o texto, etc. En referencias está un enlace ás posibles accións.<br />
<br />
*O seguinte XML vai e a mesma pantalla anterior, só que as accións da tecla '''Enter''' para algúns '''EditText''' foi cambiada. Observar as accións definidas nas liñas marcadas.<br />
<syntaxhighlight lang="xml" line highlight="11,18,32"><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical" ><br />
<br />
<EditText<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:hint="Escribe un número enteiro"<br />
android:imeOptions="actionDone"<br />
android:inputType="numberSigned" /><br />
<br />
<EditText<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:hint="Escribe un número decimal"<br />
android:imeOptions="actionPrevious"<br />
android:inputType="numberSigned|numberDecimal" /><br />
<br />
<EditText<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:hint="Escribe palabras...(saíra a 1ª letra en maísculas)"<br />
android:inputType="textCapWords|textMultiLine" /><br />
<br />
<EditText<br />
android:id="@+id/et_mail"<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:hint="Enderezo e-mail. Esta línea sae por fóra da pantalla"<br />
android:imeOptions="actionSend"<br />
android:inputType="textEmailAddress" /><br />
<br />
<EditText<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:hint="Escribe a clave."<br />
android:inputType="textPassword" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
<br />
<br />
<br />
<gallery caption="Introducir datos" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_08_EditText_10.jpg| O primeiro campo ten definida a acción '''Done''' para a tecla '''Enter'''.<br />
Image:Android_2013_U2_08_EditText_11.jpg| O segundo campo a acción ir ao anterior campo.<br />
Image:Android_2013_U2_08_EditText_12.jpg| O campo do mail, ten definida a acción '''Send''' que vai ser capturada en Java e realizar unha acción en consecuencia. <br />
</gallery><br />
<br />
<br />
*Codificación en Java que captura a acción '''actionSend''' dun campo de texto (email) e o que fai e recoller o texto desa caixa de texto, o e-mail, e volver a imprimir unha mensaxe nesa mesma caixa de texto.<br />
<br />
<syntaxhighlight lang="java" line highlight="20,22-34"><br />
package com.example.u2_08_edittext;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.KeyEvent;<br />
import android.view.Menu;<br />
import android.view.inputmethod.EditorInfo;<br />
import android.widget.EditText;<br />
import android.widget.TextView;<br />
import android.widget.TextView.OnEditorActionListener;<br />
<br />
public class U2_08_EditText extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_08_edit_text);<br />
<br />
<br />
final EditText etMail = (EditText) findViewById(R.id.et_mail);<br />
<br />
etMail.setOnEditorActionListener(new OnEditorActionListener() {<br />
@Override<br />
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {<br />
boolean handled = false;<br />
if (actionId == EditorInfo.IME_ACTION_SEND) {<br />
v.setText("Mensaxe enviada a: "+v.getText());<br />
//etMail.setText("Mensaxe enviada a: " + etMail.getText()); <br />
handled = true;<br />
}<br />
<br />
return handled;<br />
}<br />
});<br />
<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_08__edit_text, menu);<br />
return true;<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Liña 20''': creamos un obxecto (etMail) que apunta ao EditText no que se introduce o mail.<br />
*'''Liña 22 - 33''': chamamos a método Listener (''escoitador'') (que veremos máis adiante) do obxecto etMail: '''setOnEditorActionListener ()'''<br />
**Ese método será chamado cando se realice unha acción nun TextView<br />
**Lembrar que un EditText é unha subclase de TextView<br />
**Por exemplo, cando se prema unha tecla ou cando haxa unha acción IME seleccionada polo usuario.<br />
**Como parámetro váiselle pasar a creación dunha clase anónima que implementa unha interface (OnEditorActionListener) para a cal hai que sobreescribir o único método que ten a interface (onEditorAction()).<br />
<br />
<br />
*'''Liñas 24-29''': sobreescritura do método OnEditorAction() no que se reciben 3 parámetros:<br />
**O TextView que xerou o evento (v). Neste caso a caixa de texto do mail<br />
**O ID da acción enviada <br />
**E se o evento foi xerado pola tecla '''Enter''' ou non (event).<br />
**Comprobamos se o ID da acción é o SEND, nese caso modificamos o contido da caixa de texto do mail. <br />
<br />
<br />
*'''Liña 28''': realiza a mesma función ca 27. Lembrar que '''v''' é un TextView que apunta á caixa de edición do mail e que etMail é un EditText que apunta ao mesmo elemento.<br />
<br />
<br />
*Para que o IDE nos cre a '''clase anónima''':<br />
**Escribir a chamada ao método (ollo ; final incluído): '''etMail.setOnEditorActionListener( );'''<br />
**Escribir '''new''' entre os paréntesis: '''etMail.setOnEditorActionListener(new );'''<br />
**Premer CTRL+Barra espaciadora e xa o sistema completa todo o demais.<br />
**Logo só queda poñer o noso código no método a sobreescribir.<br />
<br />
<br />
*Lembrar premer '''SHIFT+CTRL+O''' para importar os paquetes correspondentes.<br />
<br />
<br />
<br />
<gallery caption="Acción Send" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_08_EditText_12.jpg| Ao premer en '''Send'''<br />
Image:Android_2013_U2_08_EditText_13.jpg| O sistema captura o evento e envía unha mensaxe a o mesma caixa de texto.<br />
</gallery><br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Instalaci%C3%B3n_en_Windows&diff=57112Instalación en Windows2015-07-24T11:52:20Z<p>Angelfg: /* Android SDK para tódolos usuarios */</p>
<hr />
<div>==Introducion==<br />
*Como xa se dixo, vaise instalar, por separado, os seguintes compoñentes en '''Windows 8.1 Enterprise 64 bits'''.<br />
<br />
*A razón de instalar cada compoñente por separado é que nos vai permitir ter un maior control de todo canto se precisa e ademais vai poder permitir que cada lector instale os compoñentes que precise en función dos que xa ten instalados.<br />
*Compoñentes:<br />
{| <br />
|- style="height:70px" <br />
| [[Imagen:00_java.png|70px]]<br />
| O [http://es.wikipedia.org/wiki/Java_Development_Kit JDK] (Java Development Kit) de [http://es.wikipedia.org/wiki/Oracle_Corporation Oracle].<br> Como xa se indicou vaise instalar o JDK no canto do JRE (MV de Java), por se alguén desexa programar a maiores en Java en consola ou con outros IDEs.<br />
|- style="height:70px" <br />
| [[Imagen:00_Eclipse.png|70px]]<br />
| O [http://es.wikipedia.org/wiki/Entorno_de_desarrollo_integrado IDE] (Integrated Development Enviroment) de [http://es.wikipedia.org/wiki/Eclipse_%28software%29 Eclipse].<br />
|- style="height:70px" <br />
| [[Imagen:00_android_platform.png|70px]]<br />
| O [http://es.wikipedia.org/wiki/SDK SDK] (Software Development Kit) de [http://es.wikipedia.org/wiki/Android Android]<br />
|- style="height:70px" <br />
| [[Imagen:00_ADT.png|70px]]<br />
| O '''ADT Plugin''' (Android Development Tools) para Eclipse. Permitirá facer uso dende o IDE do SDK de Android.<br />
|}<br />
<br />
<br />
== Instalación JDK de Oracle==<br />
*No material instalouse a versión 7, pero pódese instalara a actual 8 (Outubro 2014). <br />
*En http://www.oracle.com/technetwork/java/javase/downloads/index.html pódese obter máis información.<br />
<br />
<gallery caption="Instalación JDK" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_windows_01.jpg| No enlace http://www.oracle.com/technetwork/java/javase/downloads/index.html descargamos o JDK.<br />
Image:Android_2013_windows_02.jpg| Aceptamos a licencia e descargamos a última versión do JDK para windows, neste caso para 64 bits.<br />
Image:Android_2013_windows_03.jpg| Ficheiro descargado sen extensión.<br />
Image:Android_2013_windows_04.jpg| Se fóra necesario ... engadir extensión .exe<br />
Image:Android_2013_windows_05.jpg| Executar.<br />
Image:Android_2013_windows_06.jpg| Aceptar a advertencia.<br />
Image:Android_2013_windows_07.jpg| Premer en '''Next'''.<br />
Image:Android_2013_windows_08.jpg| Fixarse na ruta onde vai ser instalado. Premer '''Next'''.<br />
Image:Android_2013_windows_09.jpg| Fixarse onde se vai instalar o JRE.<br />
Image:Android_2013_windows_10.jpg| Proceso de instalación do JRE.<br />
Image:Android_2013_windows_11.jpg| Pechar o proceso de instalación.<br />
Image:Android_2013_windows_12.jpg| Comprobar a versión do JRE: '''java -version'''. En cambio a versión do compilador dinos que non atopa o programa '''javac'''. <br />
Image:Android_2013_windows_13.jpg| Iso é porque non está a ruta no '''path'''. Non fai falla para executar Eclipse nin o SDK de Android, pero se alguén o desexa pode engadir a ruta ao '''path'''. Observar que no path non aparece a ruta ao JRE, pero no proceso de instalación copiase a MV de Java (java.exe) a '''C:\Windows\System32\'''.<br />
</gallery><br />
<br />
== Instalación do IDE Eclipse ==<br />
*A continuación instalarase o IDE de Eclipse, cuxo proceso de instalación é simplemente descargar e descomprimir un paquete, sen máis.<br />
*En http://eclipse.org/ está o sitio do IDE.<br />
<br />
<br />
<gallery caption="Instalación IDE Eclipse" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_windows_14.jpg| En http://www.eclipse.org/downloads/ podemos atopar a última versión. No material usouse á 4.3.1. Hoxe existe a 4.4.1 (Luna). Descargamos neste caso a versión de 64 bits do '''IDE de Java EE''' (Enterprise Edition) por ser máis completa cá do IDE de Java, pero con esta última tamén sería suficiente. <br />
Image:Android_2013_windows_15.jpg| Descomprimir o ficheiro.<br />
Image:Android_2013_windows_16.jpg| Carpeta '''Eclipse''' que xa contén o IDE, listo ... <br />
Image:Android_2013_windows_26.jpg| Pregunta polo espazo de traballo para os proxectos. A versión do programa é Mars (4.5.0).<br />
Image:Android_2013_windows_27.jpg| O IDE funcionando. Pero, pero !!!!! Só está dispoñible para o usuario que o baixou e non para os demais do sistema. Isto non é desexable nunha aula.<br />
</gallery><br />
<br />
===IDE Eclipse para tódolos usuarios===<br />
*Para que o IDE Eclipse estea dispoñible para tódolos usuarios do sistema, só é preciso poñer o cartafol Eclipse nunha ruta accesible por todo usuario. Neste caso vaise facer uso da máis recomendada '''C:\Archivos de Programa'''.<br />
*Finalmente crearase un '''menú''' para que calquera usuario poida lanzar o IDE dende o Botón de Inicio de Windows.<br />
<br />
<gallery caption="Instalación IDE Eclipse para tódolos usuarios" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_windows_17.jpg| Cortar a carpeta Eclipse.<br />
Image:Android_2013_windows_18.jpg| Pegala en '''C:\Archivos de Programa''' (Program Files).<br />
Image:Android_2013_windows_19.jpg| Premer en continuar para aceptar a advertencia de seguridade.<br />
Image:Android_2013_windows_20.jpg| Crear un atallo ao programa eclipse.<br />
Image:Android_2013_windows_21.jpg| Renomear o atallo a eclipse e copialo.<br />
Image:Android_2013_windows_22.jpg| Pegalo en '''C:\ProgramData\Microsoft\Windows\Start Menu\Programs'''. A carpeta "ProgramData" está oculta e a carpeta "Start Menu" pode que se chame "Menú de inicio".<br />
Image:Android_2013_windows_23.jpg| Premer en continuar para aceptar a advertencia de seguridade.<br />
Image:Android_2013_windows_24.jpg| O menú Eclipse xunto con outros accesos directos doutras aplicacións.<br />
Image:Android_2013_windows_25.jpg| Ir a Inicio de Windows e buscar a aplicación Eclipse.<br />
Image:Android_2013_windows_26.jpg| Lanzar o IDE Eclipse<br />
Image:Android_2013_windows_27.jpg| O Eclipse funcionando.<br />
</gallery><br />
<br />
== Instalación Android SDK ==<br />
*O proceso de instalación é semellante ao do IDE Eclipse: descargar un paquete e descomprimilo.<br />
*En http://developer.android.com/sdk/index.html#Other podemos comezar co proceso de instalación.<br />
*Poderíamos descargar o '''Bundle''' asociado ao noso SO e este xa traería integrado nun só paquete: Eclipse + Android SDK + Plugin ADT. Só restaría instalar o JRE (ou JDK se se desexa).<br />
**Poderíase configurar para que puidera ser usado por calquera usuario do sistema do mesmo xeito que se fixo antes con Eclipse e que se vai facer a continuación co SDK de Android.<br />
*Pero, como indicamos, vaise instalar cada compoñente por separado.<br />
<br />
<br />
<br />
<gallery caption="Instalación Android SDK" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_windows_29.jpg|En http://developer.android.com/sdk/index.html#Other poderemos descargar o '''SDK''' para Android. asociado ao noso SO. Neste caso baixarase o instalador executable do SDK para Windows, fixarse que a versión é a mesma para 32 bits que para 64 bits.<br />
Image:Android_2013_windows_30.jpg| Aceptamos as condicións e descargamos.<br />
Image:Android_2013_windows_31.jpg| Executar o instalador.<br />
Image:Android_2013_windows_32.jpg| Aceptar a advertencia de seguridade.<br />
Image:Android_2013_windows_33.jpg| Premer en '''Next'''.<br />
Image:Android_2013_windows_34.jpg| En versións anteriores de Android SDK, o instalador informaba dun erro na localización do ficheiro '''java.exe'''. Isto so pasa na versión de 64 bits de Windows. Para solucionalo hai que engadir nas variables de contorno a variable JAVA_HOME apuntando á ruta do SDK. <br />
Image:Android_2013_windows_35.jpg| Premer en propiedades de '''Este PC'''.<br />
Image:Android_2013_windows_36.jpg| Ir a '''Configuración avanzada do sistema'''.<br />
Image:Android_2013_windows_37.jpg| Na lapela '''Opcións avanzadas''' premer en '''Variables de entorno'''.<br />
Image:Android_2013_windows_38.jpg| Crear unha '''nova''' variable de entorno.<br />
Image:Android_2013_windows_39.jpg| Nome da variable: '''JAVA_HOME''' e valor da variable, neste caso, '''c:\Program files\Java\jdk1.7.0_45'''. Aceptar todo.<br />
Image:Android_2013_windows_40.jpg| Volver a lanzar o instalador do SDK de Android.<br />
Image:Android_2013_windows_41.jpg| Pódese instalar para o usuario actual.<br />
Image:Android_2013_windows_42.jpg| Fixarse como descomprimiría nunha carpeta do usuario que está no sistema. Pero pola mesma razón de antes con Eclipse, preferimos que estea dispoñible para todos os usuarios. Premer en '''Back'''.<br />
</gallery><br />
<br />
<br />
<br />
===Android SDK para tódolos usuarios===<br />
<br />
<gallery caption="Instalación Android SDK tódolos usuarios" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_windows_43.jpg| Seleccionar para tódolos usuarios.<br />
Image:Android_2013_windows_44.jpg| Observar a ruta de instalación. Como temos un SO de 64 bits vaino instalar onde se instalan os programas de 32 bits en '''C:\Program files (x86)\''' na subcarpeta '''\android\android-sdk'''. Quen o desexe pode modificar esa ruta, pero senón a modifica o plugin ADT de Eclipse vai tratar de buscar nesa ruta o SDK por defecto.<br />
Image:Android_2013_windows_45.jpg| Instalar ...<br />
Image:Android_2013_windows_46.jpg| Premer en '''Next'''.<br />
Image:Android_2013_windows_47.jpg| Poderíase lanzar o Xestor do SDK para completar a instalación, pero vaise realizar manualmente.<br />
Image:Android_2013_windows_48.jpg| Na carpeta '''C:\Program files (x86)\android\android-sdk''' podemos lanzar o '''SDK Manager''' ou xestor SDK<br />
Image:Android_2013_windows_49.jpg| Hai que lanzalo como Administrador, premendo co botón dereito sobre o programa.<br />
Image:Android_2013_windows_50.jpg| Aceptar a advertencia de seguridade.<br />
Image:Android_2013_windows_51.jpg| A imaxe pertence a unha versión anterior de Android SDK. Se se preme na imaxe verase en tamaño real, e poderá apreciarse, que aínda non está o SDK listo para poder crear o noso primeiro programa: precísanse compoñentes que xa marca por defecto o xestor: Unha API (marca por defecto a última) e compoñentes básicos.<br />
Image:Android_2013_windows_52.jpg| Neste caso, como xa se indicou nun apartado anterior, vanse descargar a API 16. Se se desexa pódese instalar as APIs 4.4W e L (8 GiB a maiores). Se non é o caso lembrade desmarcalas xa que pode defectos as baixará.<br />
Image:Android_2013_windows_55.jpg| Aceptar as licencias dos compoñentes.<br />
Image:Android_2013_windows_57.jpg| Ollo!!! que abaixo hai máis licencias para aceptar. E premer en '''Install'''<br />
Image:Android_2013_windows_58.jpg| Comezo da descarga. Da un erro de que non pode parar o servidor ADB, porque aínda non está instalado. O servidor ADB verase nun apartado posterior.<br />
Image:Android_2013_windows_59.jpg| Descarga completada e o servidor ADB funcionando.<br />
Image:Android_2013_windows_82.jpg| Compoñentes do SDK instalados.<br />
Image:Android_2013_windows_59A.jpg| Carpetas creadas e asociadas ao SDK.<br />
</gallery><br />
<br />
'''NOTA:''': Cando decidimos instalar unha nova versión do S.O. Android non é necesario marcar todas as opcións dentro desta API. Así:<br />
:* SDK: Necesario para poder desenvolver a aplicación. Sempre debe ser marcada.<br />
:* Samples for SDK: Documentación de exemplo. Non é necesario marcala.<br />
:* System Image (ARM/Intel/MIPS): Cando máis adiante utilicemos un dispositivo virtual para correr as nosas aplicacións, será necesario ter descargado a lo menos unha destas imaxes. O normal é que se temos un procesador INTEL descarguemos unha imaxe INTEL xa que despois poderemos instalar un acelerador hardware para dito micro. Se non temos intel poderíamos descargar calquera das opcións.<br />
:* Google API: O mesmo que o System Image pero para dar soporte a aplicacións que van facer uso de Google Maps. Se non imos traballar con el non será necesario descargalas.<br />
:* Sources for Android SDK: Fontes das funcións do SDK. Non é necesario descargalas.<br />
<br />
==Android Debug Bridge: ADB==<br />
*O '''Android Debug Bridge (ADB)''' é un comando que arranca un servidor que nos vai permitir comunicarnos e interactuar cos dispositivos físicos ou emulados. <br />
* O ADB verase con profundidade nun apartado posterior, por agora so interesa que se poida executar.<br />
* No enlace hai máis información: http://developer.android.com/tools/help/adb.html<br />
<br />
Executamos o comando: '''C:\Program files (x86)\android\android-sdk\platform-tools\adb''' e amosa a axuda do comando.<br />
<br />
[[Image:Android_2013_windows_60.jpg|400px]]<br />
<br />
<br />
<br />
==Instalación plugin ADT==<br />
*Só resta instalar o plugin en Eclipse que permita traballar dende este IDE co SDK de Android.<br />
*Este plugin chámase: '''Android Development Tools (ADT)''' e estende as capacidades de Eclipse para xestionar dispositivos móviles (emulados e reais), compilar e instalar aplicacións en dispositivos, etc.<br />
*En http://developer.android.com/tools/sdk/eclipse-adt.html hai máis información sobre este compoñente e como se pode instalar no IDE.<br />
<br />
<gallery caption="Instalación ADT Plugin" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_windows_64A.jpg| En http://developer.android.com/tools/sdk/eclipse-adt.html premer en '''Installing the Eclipse Plugin'''<br />
Image:Android_2013_windows_64.jpg| En http://developer.android.com/sdk/installing/installing-adt.html indica que podemos instalar o Plugin de dúas formas:<br />
Image:Android_2013_windows_64B.jpg| Unha descargando o paquete e logo instalalo dende Eclipse ...<br />
Image:Android_2013_windows_65.jpg| ... ou copiar o enlace ao repositorio no que se atopa o plugin ADT: https://dl-ssl.google.com/android/eclipse/. Usaremos esta forma.<br />
Image:Android_2013_windows_61.jpg| Lanzar Eclipse.<br />
Image:Android_2013_windows_63.jpg| Premer en '''Help -> Install New Software...'''<br />
Image:Android_2013_windows_66.jpg| Pegar o repositorio ... Premer en '''Add'''.<br />
Image:Android_2013_windows_67.jpg| Poñer un nome ao repositorio, neste caso '''ADT'''<br />
Image:Android_2013_windows_68.jpg| Amosa o compoñente que se vai instalar. A versión actual amosa só o compoñente '''Developer Tools'''. A versión anterior de ADT ofrecía instalar o compoñente '''NDK: Native Development Kit''' que permitía desenvolver aplicacións en linguaxe nativa como C ou C++. Máis información: http://developer.android.com/tools/sdk/ndk/index.html <br>Dentro dos compoñentes de '''Developer Tools''' hai outros como '''DDMS''' que se verá nun apartado posterior.<br>Unha vez marcado todo premer en '''Next'''.<br />
Image:Android_2013_windows_69.jpg| Premer en '''Next'''.<br />
Image:Android_2013_windows_70.jpg| Aceptar a licencia.<br />
Image:Android_2013_windows_71.jpg| Proceso de descarga e instalación dos paquetes.<br />
Image:Android_2013_windows_72.jpg| Aceptar a advertencia que indica que hai software sen asinar.<br />
Image:Android_2013_windows_73.jpg| Permitir acceso ao Firewall de Windows.<br />
Image:Android_2013_windows_74.jpg| Reiniciar eclipse cando remate a instalación do plugin.<br />
Image:Android_2013_windows_75.jpg| Indicar se se desexa participar nas estadísticas de Google.<br />
Image:Android_2013_windows_76.jpg| Eclipse funcionando.<br />
</gallery><br />
<br />
==Configuración Eclipse e plugin ADT. Actualizacións==<br />
*Agora xa podemos iniciar eclipse sen problemas e imos ver:<br />
**Parámetros de configuración de Eclipse.<br />
**Como actualizar Eclipse ou o SDK de Android.<br />
**Que elementos engadiu o plugin ADT á Perspectiva Java de Eclipse.<br />
***Unha '''Perspectiva''' é unha combinación de pantallas para facilitar o desenvolvemento de aplicacións de distintos tipos.<br />
***Aconséllase que se lle bote un ollo a: '''"Mi primera hora con Eclipse"''': http://ubuntulife.files.wordpress.com/2008/03/intro_eclipse_espanol.pdf<br />
<br />
<br />
<br />
<gallery caption="Preferencias" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_windows_85.jpg| Premer en '''Window -> Preferences'''.<br />
Image:Android_2013_windows_87.jpg| Na categoría '''Android''' pódese ver a ruta do SDK, se esta se perdera, con vir a esta preferencia xa se podería configurar.<br />
Image:Android_2013_windows_86.jpg| A versión do compilador JDK que vai usar o IDE.<br />
Image:Android_2013_windows_87A.jpg| A versión do JRE e a súa ruta.<br />
</gallery><br />
<br />
<br />
<gallery caption="Actualizacións" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_windows_83.jpg| Lanzar o Eclipse como Administrador.<br />
Image:Android_2013_windows_77.jpg| En '''Help -> Check for Updates'''. <br />
Image:Android_2013_windows_78.jpg| Comprobando se hai actualizacións do IDE.<br />
Image:Android_2013_windows_79.jpg| Non hai actualizacións.<br />
</gallery><br />
<br />
<br />
<gallery caption="Perspectiva Java" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_windows_80A.jpg| A combinación de ventás (Perspectiva) que se ve é a que se denomina Java EE.<br />
Image:Android_2013_windows_80.jpg| Pero ADT instalou compoñentes na Perspectiva Java. Premer en '''Window -> Open Perspective -> Java'''<br />
Image:Android_2013_windows_81.jpg| Aparecen novas iconas, entre elas, o '''Android SDK Manager''' e o Xestor de Dispositivos Virtuais.<br />
Image:Android_2013_windows_81A.jpg| O mesmo pasa se se preme en '''Window'''<br />
Image:Android_2013_windows_82.jpg| Dende o propio Eclipse, o plugin proporciona un enlace ao comando que chama ao '''Xestor de SDK de Android''', que estaba na ruta: '''C:\Program Files (x86)\android\android-sdk\SDK Manager''' Dende aquí poderíanse instalar/desinstalar compoñentes e incluso actualizalos. Pero hai que iniciar o Eclipse como administrador, como se amosa na seguinte imaxe. Non o pode facer un usuario normal salvo que se modifique a seguridade.<br />
Image:Android_2013_windows_83.jpg| Iniciar Eclipse como administrador.<br />
Image:Android_2013_windows_84.jpg| Aceptar a advertencia de seguridade.<br />
</gallery><br />
<br />
==Carpetas de traballo==<br />
*As carpetas que se obteñen finalmente pertencen a 2 tipos:<br />
**'''Carpetas de programas''':<br />
***'''C:\Program Files\eclipse''': Eclipse + plugin ADT<br />
***'''C:\Program Files (x86)\android\android-sdk''': Android SDK <br />
**'''Carpetas de configuración de usuario'''<br />
***'''C:\Users\usuario\AppData\...''': Carpeta oculta. Contén arquivos de configuración relativos a ese usuario e ao IDE Eclipse.<br />
***'''ruta\workspace''': Carpeta indicada polo usuario onde se van gardar os proxectos creados no IDE Eclipse.<br />
***'''C:\Users\usuario\.android''': Contén arquivos de configuración relativos ao SDK de Android e a ese usuario.<br />
<br />
==Fixar a icona á barra de tarefas==<br />
*Unha forma de facilitar o acceso a eclipse pode ser fixando a icona á barra de tarefas.<br />
*Hai varias formas de facelo, unha delas é a seguinte, unha vez que se ten o Eclipse lanzado, aparece unha icona na barra de tarefas, premer co botón dereito sobra a icona e fixar o programa a esta barra.<br />
<br />
[[Image:Android_2013_windows_88.jpg|400px]]<br />
<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Archivo:Android_2013_windows_52.jpg&diff=57111Archivo:Android 2013 windows 52.jpg2015-07-24T11:51:59Z<p>Angelfg: Angelfg subió una nueva versión de «Archivo:Android 2013 windows 52.jpg»</p>
<hr />
<div></div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Instalaci%C3%B3n_en_OS_X&diff=57101Instalación en OS X2015-07-24T11:43:02Z<p>Angelfg: </p>
<hr />
<div>*A instalación en MAC para OS X é semellante á realizada en Ubuntu, só que a carpeta recomendada para a descompresión do SDK de Android é '''/Applications/android-sdk-macosx''' ou '''/usr/android-sdk-macosx'''<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Instalaci%C3%B3n_ADT_Bundle&diff=57100Instalación ADT Bundle2015-07-24T11:42:52Z<p>Angelfg: </p>
<hr />
<div>* Como xa se foi indicando no proceso de instalación de Ubuntu e Windows é posible descargar un paquete que xa traia todo o necesario para desenvolver aplicacións para Android.<br />
<br />
<br />
*Ese paquete chámase '''ADT Bundle''' e inclúe: Eclipse + Android SDK + ADT Plugin.<br />
<br />
<br />
* Nos seguintes enlaces pódese descargar o ADT Bundle: <br />
<br />
::*Linux 64 bit: http://dl.google.com/android/adt/adt-bundle-linux-x86_64-20140702.zip<br />
::*Linux 32 bit: http://dl.google.com/android/adt/adt-bundle-linux-x86-20140702.zip<br />
::*MacOS X: http://dl.google.com/android/adt/adt-bundle-mac-x86_64-20140702.zip<br />
::*Win32: http://dl.google.com/android/adt/adt-bundle-windows-x86-20140702.zip<br />
::*Win64: http://dl.google.com/android/adt/adt-bundle-windows-x86_64-20140702.zip<br />
<br />
<br />
** Só se precisaría instalar o Runtime de Java (JRE) ou o JDK.<br />
<br />
<br />
* Visto o realizado nos procesos de instalación anteriores calquera podería baixar o Bundle asociado ao seu Sistema Operativo e configuralo para tódolos usuarios. <br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Variables_de_contorno&diff=57097Variables de contorno2015-07-24T11:42:18Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Até agora sempre estivemos poñendo a ruta completa a onde se atopaba as utilidades que precisabamos: adb, android, emulator, etc.<br />
*Pero iso pódese solucionar poñendo as rutas no path a eses comandos:<br />
**'''/ruta SDK/tools'''<br />
**'''/ruta SDK/platform-tools'''<br />
<br />
==Engadir rutas ao path en Linux==<br />
*Primeiro imos ver como modificalo para o usuario actual e logo para todo o sistema.<br />
*Trátase de engadir á variable PATH actual ($PATH) as novas rutas:<br />
<pre><br />
PATH=$PATH:/opt/android-sdk-linux/tools:/opt/android-sdk-linux/platform-tools<br />
export PATH<br />
</pre><br />
<br />
<br />
*Tamén se podería engadir a ruta ao Eclipse para cando se executa dende a consola.<br />
<br />
<br />
<br />
===Engadir rutas ao path para o usuario actual===<br />
<br />
<gallery caption="Path usuario actual" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_adb_89.jpg|O usuario actual pode modificar o ficheiro oculto '''.bashrc''' que se executa cando o usuario inicia sesión.<br />
Image:Android_2013_adb_87.jpg| '''gedit .bashrc'''<br />
Image:Android_2013_adb_88.jpg| Engadir ao final do ficheiro as liñas de enriba.<br />
Image:Android_2013_adb_90.jpg| Executamos '''adb''' e segue sen funcionar. Iso resólvese saíndo e volvendo a entrar para que se execute o ficheiro ou executando o ficheiro: '''. .bashrc'''. Agora xa funciona o comando '''adb'''.<br />
Image:Android_2013_adb_98.jpg| Con '''echo $PATH''' podemos ver o contido da variable PATH.<br />
</gallery><br />
<br />
===Engadir rutas ao path para o sistema===<br />
*Se se teñen permisos de administración pódese realizar isto para todo o sistema no ficheiro '''/etc/profile'''.<br />
<br />
<gallery caption="Path para o sistema" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_adb_91.jpg| ''' sudo gedit /etc/profile''' permite engadir as dúas liñas anteriores a este ficheiro.<br />
Image:Android_2013_adb_92.jpg| Saíndo e volvendo entrar pódese executar o comando '''adb devices''' sen especificar a ruta'''<br />
Image:Android_2013_adb_93.jpg| E lanzar o xestor de AVDs: '''android avd'''.<br />
</gallery><br />
<br />
==Engadir rutas ao path en Windows==<br />
<br />
<br />
<gallery caption="Path para o sistema" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_windows_35.jpg| Premer en propiedades de '''Este PC'''.<br />
Image:Android_2013_windows_36.jpg| Ir a '''Configuración avanzada do sistema'''.<br />
Image:Android_2013_windows_37.jpg| Na lapela '''Opcións avanzadas''' premer en '''Variables de entorno'''.<br />
Image:Android_2013_adb_94.jpg| Editar a variable Path.<br />
Image:Android_2013_adb_95.jpg| O mellor que se pode realizar é copiar a ruta dos cartafois anteriores (tools e pltaform-tools) para non trabucarse.<br />
Image:Android_2013_adb_96.jpg| Pegar as rutas separadas por ";".<br />
Image:Android_2013_adb_97.jpg| Executar o comando path para ver o seu valor.<br />
</gallery><br />
<br />
<br />
*Tamén se podería engadir a ruta ao Eclipse para cando se executa dende a consola.<br />
<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=PDM:_Android._Obxectivos_e_escenarios_do_UNIDADE_2&diff=57094PDM: Android. Obxectivos e escenarios do UNIDADE 22015-07-24T11:41:36Z<p>Angelfg: </p>
<hr />
<div>*Nesta unidade vanse ver aspectos relacionados con:<br />
**Os elementos visuais, Interface de Usuario (UI).<br />
**Os elementos que compoñen unha pantalla: layouts e vistas<br />
**Configurar unha pantalla para que se adapte a distintos tamaños de pantalla física.<br />
**Formas de construír unha pantalla: layout.<br />
**Elementos que compoñen unha pantalla: botóns, checkbox, listas despregables, etiquetas, etc.<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Xesti%C3%B3n_de_proxectos_en_Eclipse&diff=57093Xestión de proxectos en Eclipse2015-07-24T11:41:18Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Antes de enfrascarse na creación de proxectos, imos ver como xestionalos en Eclipse.<br />
*Imos ver como importalos e as opcións existentes.<br />
*É bo botarlle unha ollada ao seguinte material, para evitarse sorpresas desagradables coa perda de proxectos.<br />
*Como xa se indicou recoméndase a lectura do seguinte documento: '''"Mi primera hora con Eclipse"''': http://ubuntulife.files.wordpress.com/2008/03/intro_eclipse_espanol.pdf<br />
<br />
<br />
===Iniciar Eclipse===<br />
*Como xa se viu na Unidade 1, imos comezar abrindo o Eclipse como se fose a primeira vez.<br />
*Escolleremos a perspectiva de Java.<br />
*O '''Workspace''' é o lugar onde Eclipse almacena por defecto os proxectos e información sobre estes nunha carpeta chamada '''.metadata''', que pode traer algunha que outra complicación.<br />
<br />
<gallery caption="Iniciar Eclipse" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_eclipse_01.jpg| Escoller se se desexa que pregunte polo directorio do '''Workspace''' a próxima vez que se inicie.<br />
Image:Android_2013_U2_eclipse_02.jpg| Pechar a pantalla de benvida.<br />
Image:Android_2013_U2_eclipse_03.jpg| Escoller a perspectiva Java.<br />
</gallery><br />
<br />
==Crear un proxecto==<br />
*Un usuario pode ter varios '''Workspaces''' ou outros cartafoles para organizar os seus proxectos. Así, pode ter proxectos de distintas materias ou distintas linguaxes en distintos Workspaces. <br />
*Un proxecto pódese crear no cartafol do '''workspace''' ou noutra calquera. En calquera caso, almacenarase información sobre os proxectos no cartafol '''.metadatos''' do '''Workspace''' co que se estea a traballar. <br />
*Agora imos traballar con proxectos ''lixo'' para estudar as distintas opcións, logo máis en diante explicarase os campos dos cadros de diálogo.<br />
*Estes proxectos borrarémolos ao finalizar este apartado.<br />
<br />
<gallery caption="Crear un proxecto lixo" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_eclipse_04.jpg| Creamos un novo proxecto de Android.<br />
Image:Android_2013_U2_eclipse_05.jpg| Indicamos nome da aplicación: '''Proxecto1'''.<br> '''OLLO! Edición 2015''': Indicar como SDK mínimo API 16.<br />
Image:Android_2013_U2_eclipse_06.jpg| Observar que o proxecto vaise crear dentro do '''Workspace'''.<br />
Image:Android_2013_U2_eclipse_07.jpg| Premer '''Next'''.<br />
Image:Android_2013_U2_eclipse_08.jpg| Premer '''Next'''.<br />
Image:Android_2013_U2_eclipse_09.jpg| Indicamos o nome da actividade: '''Proxecto1'''.<br />
Image:Android_2013_U2_eclipse_14.jpg| Proxecto creado no IDE Eclipse.<br />
Image:Android_2013_U2_eclipse_11.jpg| E na carpeta correspondente ao Workspace.<br />
Image:Android_2013_U2_eclipse_12.jpg| Proxecto1 dentro da carpeta do '''Workspace'''.<br />
Image:Android_2013_U2_eclipse_13.jpg| Contido do cartafol '''Proxecto1'''. Coincide co contido do Proxecto1 do IDE.<br />
</gallery><br />
<br />
==Cambiar de workspace==<br />
<gallery caption="Crear máis proxectos lixo" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_eclipse_15.jpg| Pechamos e abrimos Eclipse, indicamos un novo '''Workspace''' para outros proxectos: '''workspaces2'''.<br />
Image:Android_2013_U2_eclipse_16.jpg| Ao crear un novo Workspace, e iniciar Eclipse por primeira vez, aparece a ventá de Benvida. É como comezar de cero, pero nun novo workspace.<br />
Image:Android_2013_U2_eclipse_17.jpg| Igual que antes creamos un '''Proxecto2'''.<br> '''OLLO! Edición 2015''': Indicar como SDK mínimo API 16.<br />
Image:Android_2013_U2_eclipse_18.jpg| O proxecto creado no novo Workspace. Ollo non está o Proxecto1.<br />
Image:Android_2013_U2_eclipse_19.jpg| Premendo en '''File->Switch Workspace''' podemos cambiar de Workspace ou ver os dispoñibles, premendo en '''Other'''. Neste menú é onde se pode cambiar de workspace, cando na pantalla de inicio non temos habilitada a opción de escoller. <br />
Image:Android_2013_U2_eclipse_20.jpg| Tamén se pode pode engadir outro Workspace.<br />
Image:Android_2013_U2_eclipse_21.jpg| Neste caso imos engadir o '''workspace3'''.<br />
Image:Android_2013_U2_eclipse_22.jpg| Pechar Eclipse e volvelo abrir. Observar como agora ofrece os 3 workspaces. <br />
Image:Android_2013_U2_eclipse_23.jpg| Escoller o '''Workspace3''', será como partir de cero ...<br />
Image:Android_2013_U2_eclipse_24.jpg| Pero como saber en que Workspace estamos?. Hai a posibilidade de indicalo na barra de título.<br />
Image:Android_2013_U2_eclipse_25.jpg| O ficheiro '''<ruta instalación de eclipse>/eclipse.ini'''... <br />
Image:Android_2013_U2_eclipse_26.jpg| ... podemos editalo (A imaxe amosa como facelo en Linux. En Windows editar o ficheiro).<br />
Image:Android_2013_U2_eclipse_27.jpg| Engadir ao principio: '''-showlocation'''.<br />
Image:Android_2013_U2_eclipse_28.jpg| Pechar Eclipse e volvelo abrir. Observar a ruta do espazo de traballo na barra de título.<br />
Image:Android_2013_U2_eclipse_30.jpg| Aquí vemos os cartafois dos tres proxectos.<br />
</gallery><br />
<br />
==Organización de proxectos dentro dun workspace: Working Sets==<br />
*Xa vimos que se poden ter diferentes workspaces para que o usuario se organice como desexe.<br />
*Pero dentro de cada '''Workspace''', Eclipse, ofrece a posibilidade de organizar os proxectos en agrupamentos chamados: '''Working sets'''.<br />
*En todo momento podemos mover proxectos dun '''Working set''' a outro, ter un proxecto en varios '''Working sets''', decidir que '''Working sets''' amosar/ocultar, etc.<br />
<br />
<br />
<gallery caption="Crear workingsets" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_eclipse_29.jpg| No '''workspace3''' crear 2 proxectos Android: (Proxecto3 e Proxecto4) e un de Java (ProxectoJava1)<br />
Image:Android_2013_U2_eclipse_31.jpg| O contido do Workspace3.<br />
Image:Android_2013_U2_eclipse_32.jpg| Na '''Vista de Exploración de Proxectos''' premer no Menú da Vista ('''View Menu''')<br />
Image:Android_2013_U2_eclipse_33.jpg| Seleccionar '''Working Set...'''<br />
Image:Android_2013_U2_eclipse_34.jpg| Crear un '''Working Set''' novo.<br />
Image:Android_2013_U2_eclipse_35.jpg| Podemos crear '''Working Sets''' para agrupar, recursos, programas, etc. Neste caso imos escoller '''Java''', pois son proxectos de Java (Android) os que imos agrupar.<br />
Image:Android_2013_U2_eclipse_36.jpg| Poñer un nome ao agrupamento: neste caso '''Java'''.<br />
Image:Android_2013_U2_eclipse_37.jpg| Seleccionar que proxectos o compoñen ...<br />
Image:Android_2013_U2_eclipse_38.jpg| ... neste caso imos pasar o '''ProxectoJava1'''.<br />
Image:Android_2013_U2_eclipse_39.jpg| Crear outro agrupamento ...<br />
Image:Android_2013_U2_eclipse_40.jpg| ... neste caso co nome '''Platega Android'''. Nesta ocasión, a modo de exemplo, non engadimos ningún proxecto.<br />
Image:Android_2013_U2_eclipse_41.jpg| Seleccionamos os 2 agrupamentos. Premer en OK.<br />
Image:Android_2013_U2_eclipse_42.jpg| No Menú da Vista, imos indicar que queremos ver os proxectos organizados por Working Sets.<br />
Image:Android_2013_U2_eclipse_43.jpg| Podemos configurar que Workings Sets queremos configuar. Marcamos todos, entre eles: '''Other Projects'''. Tamén podemos indicar en que '''orde''' desexamos ver os agrupamentos na '''Vista de Exploración de Proxectos''', para iso usaremos os botóns '''Up''' e '''Down'''.<br />
Image:Android_2013_U2_eclipse_44.jpg| No agrupamento '''Other Projects''' podemos ver que están os proxectos que non se asignaron ao agrupamentos creados anteriormente.<br />
Image:Android_2013_U2_eclipse_45.jpg| Premendo en '''Select Working Set''' podemos editar e crear novos agrupamentos.<br />
Image:Android_2013_U2_eclipse_46.jpg| Editamos o agrupamento de '''Platega Android'''.<br />
Image:Android_2013_U2_eclipse_47.jpg| Asociamos os proxectos de Android a ese agrupamento. Observar como o ProxectoJava1, tamén se podería asignar a este '''working set''', de modo que ese proxecto estaría en 2 agrupamentos.<br />
Image:Android_2013_U2_eclipse_48.jpg| Premer en OK.<br />
Image:Android_2013_U2_eclipse_49.jpg| Os proxectos organizados nos Working Sets. Indicar que no canto de todo o anterior poderíase ter arrastrado e soltado os proxectos dun agrupamento a outro na presente pantalla. Volver a editar a configuración ...<br />
Image:Android_2013_U2_eclipse_50.jpg| Neste caso imos decidir que so queremos que se amosen os proxectos do agrupamento '''Platega Android'''.<br />
Image:Android_2013_U2_eclipse_51.jpg| E aí o esta !!!<br />
Image:Android_2013_U2_eclipse_52.jpg| Se queremos ver os proxectos independentemente de como estean agrupados, ... seguir o menú da imaxe.<br />
Image:Android_2013_U2_eclipse_53.jpg| Ou velos agrupados en agrupamentos.<br />
</gallery><br />
<br />
==Importar proxectos==<br />
*Os proxectos pódense levar dun equipo a outro simplemente copiando os cartafoles no que están.<br />
*Neste caso vanse copiar os proxectos contidos no Workspace3 a un novo cartafol chamado '''probas''' e logo importaranse.<br />
<br />
<gallery caption="Importar proxectos" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_eclipse_56.jpg| Copiar os proxectos contidos en '''workspace3''' a un cartafol chamado '''probas'''<br />
Image:Android_2013_U2_eclipse_57.jpg| Pechar Eclipse e seleccionar o Workspace '''workspace'''.<br />
Image:Android_2013_U2_eclipse_58.jpg| Este xa contiña o Proxecto1. Observar como non están os agrupamentos creado no '''workspace3'''.<br />
Image:Android_2013_U2_eclipse_59.jpg| Premer en '''File -> Import'''<br />
Image:Android_2013_U2_eclipse_60.jpg| Indicar que é un proxecto de Android.<br />
Image:Android_2013_U2_eclipse_61.jpg| Seleccionar o cartafol '''probas''' ... <br />
Image:Android_2013_U2_eclipse_62.jpg| ... e automaticamente busca os proxectos que hai na carpeta '''probas''' e nas súas subcarpetas (ideal para corrixir proxectos). Observar que non quere importar o proxecto de Java.<br />
Image:Android_2013_U2_eclipse_63.jpg| Indicar que queremos que copie os proxectos do cartafol orixe ao workspace. Co cal se se modifican os proxectos, estes serán os que estean no workspace e non no cartafol '''probas'''.<br />
Image:Android_2013_U2_eclipse_64.jpg| Proxectos importados ... <br />
Image:Android_2013_U2_eclipse_65.jpg| E tamén copiados ao Workspace. Observar que proxectos están/ou non en cada cartafol. A partir de agora co cartafol '''probas''' pódese realizar o que se desexe.<br />
</gallery><br />
<br />
<br />
<br />
==Proxectos fóra do Workspace==<br />
*Nesta ocasión imos ver como ter proxectos fóra do Workspace. Aínda así este é necesario para conter o cartafol '''.metadatos''' que conten información, entre outras cousas, sobre os proxectos.<br />
*Obviamente, tamén se poden ter outros proxectos dentro do Workspace.<br />
<br />
<gallery caption="Crear proxectos fóra do WorkSpace" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_eclipse_67.jpg| Abrir de novo Eclipse no espazo de traballo '''workspace2'''.<br />
Image:Android_2013_U2_eclipse_68.jpg| Contén no workspace o Procexto2 creado ao principio.<br />
Image:Android_2013_U2_eclipse_73.jpg| Crear un novo proxecto de Android ...<br />
Image:Android_2013_U2_eclipse_74.jpg| Nome '''Proxecto5'''.<br> '''OLLO! Edición 2015''': Indicar como SDK mínimo API 16.<br />
Image:Android_2013_U2_eclipse_75.jpg| Na ruta indicar que se desexa crear noutro cartafol fóra do workspace.<br />
Image:Android_2013_U2_eclipse_76.jpg| Ruta para o Proxecto5 fóra do espazo de traballo.<br />
Image:Android_2013_U2_eclipse_77.jpg| Nome da actividade Proxecto5.<br />
Image:Android_2013_U2_eclipse_78.jpg| Comparativa entre o IDE e os 2 cartafoles: o do workspace e o que conteń o proxecto5.<br />
</gallery><br />
<br />
<br />
<br />
<gallery caption="Importar proxectos fóra do Workspace" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_eclipse_70.jpg| Importar de novo ...<br />
Image:Android_2013_U2_eclipse_71.jpg| Proxectos de Android ...<br />
Image:Android_2013_U2_eclipse_72.jpg| Pero ... esta vez '''non''' copiar os proxectos ao espazo de traballo. O resultado será semellante ao anterior. Só que agora os cambios que se fagan nos proxectos 3 e 4 serán gardados no cartafol '''probas'''.<br />
Image:Android_2013_U2_eclipse_79.jpg| Observar como se distribúen os 4 proxectos do IDE: 1 en '''workspace2''', 1 no cartafol chamado ''''proxectos_fora''' e 2 no cartafol '''probas'''<br />
</gallery><br />
<br />
==Borrado de proxectos==<br />
*Os proxectos pódense borrar dende Eclipse:<br />
**Pódese borra só o enlace no IDE, sen borrar os ficheiros do proxecto, <br />
**Ou tamén o cartafol que o contén os ficheiros do proxecto.<br />
*Tamén se poden borrar os cartafoles directamente, pero teríase no IDE un enlace a un proxecto que non existe.<br />
<br />
<gallery caption="Borrar proxectos" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_eclipse_80.jpg| Borramos o Proxecto2.<br />
Image:Android_2013_U2_eclipse_81.jpg| Pero non o borramos en disco.<br />
Image:Android_2013_U2_eclipse_82.jpg| Unha advertencia ... Seguir...<br />
Image:Android_2013_U2_eclipse_83.jpg| Vemos que o IDE non ten o Proxecto2, pero este segue no cartafol '''workspace2'''.<br />
Image:Android_2013_U2_eclipse_84.jpg| Borramos o Proxecto2.<br />
Image:Android_2013_U2_eclipse_85.jpg| Esta vez si o borramos no disco.<br />
Image:Android_2013_U2_eclipse_87.jpg| Nin no IDE nin no cartafol '''probas''' está o Proxecto3.<br />
</gallery><br />
<br />
==Preferencias: workspaces==<br />
*Rematamos revisando onde se almacena a configuración relativa aos workspaces anteriores.<br />
<br />
<gallery caption="Preferencias" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_eclipse_92.jpg| Observar os espazos de traballo dispoñibles.<br />
Image:Android_2013_U2_eclipse_88.jpg| Premer en '''Window -> Preferences'''.<br />
Image:Android_2013_U2_eclipse_89.jpg| En '''General -> Startup and Shutdown -> Workspaces''' podemos eliminar a referencias aos espazos de traballo que se viñan usando até agora. Tamén podemos configurar se queremos que siga preguntado/ou non, ao iniciar Eclipse, polos espazos de traballo.<br />
Image:Android_2013_U2_eclipse_90.jpg| Deixamos só espazo de traballo '''workspace'''.<br />
Image:Android_2013_U2_eclipse_91.jpg| Agora xa só hai ese espazo de traballo.<br />
Image:Android_2013_U2_eclipse_93.jpg| Para limpar todo imos borrar os cartafoles que usamos até agora, salvo ...<br />
Image:Android_2013_U2_eclipse_94.jpg| ... '''workspace'''.<br />
</gallery><br />
<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Cartafoles_para_a_xesti%C3%B3n_de_proxectos_das_distintas_Unidades_do_curso&diff=57092Cartafoles para a xestión de proxectos das distintas Unidades do curso2015-07-24T11:41:07Z<p>Angelfg: </p>
<hr />
<div>*A continuación vaise:<br />
**Crear un cartafol para os proxectos de Eclipse. Ese cartafol estará organizado en función do tipo de proxectos.<br />
<br />
<br />
*O que vén a continuación é unha proposta, que cada quen o adapte ás súas necesidades e circunstancias. <br />
<br />
<gallery caption="Configuración Eclipse" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_uone_29.jpg| Crear un cartafol para tódolos proxectos de Eclipse<br />
Image:Android_2013_U2_uone_30.jpg| Crear un subcartafol para o tipo de proxectos<br />
Image:Android_2013_U2_uone_31.jpg| Crear outro cartafol para a Unidade 2<br />
Image:Android_2013_U2_uone_32.jpg| Abrir Eclipse e o workspace desexado. Nesta imaxe o Workspace vai estar nun cartafol distinto aos proxectos. Se alguén o desxa pode facer coincidir o Workspace co Unidade2 anterior.<br />
Image:Android_2013_U2_uone_33.jpg| Neste caso imos eliminar proxectos de probas anteriores.<br />
Image:Android_2013_U2_uone_35.jpg| Creamos un Working Set para os proxectos de Android da Unidade 2.<br />
Image:Android_2013_U2_uone_36.jpg| Organizamos a Vista en modo agrupamento. <br />
Image:Android_2013_U2_uone_37.jpg| Amosamos o agrupamento desexado. E aí imos crear tódolos proxectos da unidade 2.<br />
</gallery><br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=FrameLayout&diff=57088FrameLayout2015-07-24T11:40:20Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Un FrameLayout é usado normalmente para situar un único View na pantalla.<br />
*Se se poñen varios, a forma de determinar a súa posición faríase mediante o atributo '''android:layout_gravity''' ou a marxe.<br />
*Se se poñen varios na mesma posición estes superpóñense.<br />
<br />
<br />
*Referencias:<br />
**FrameLayout: http://developer.android.com/reference/android/widget/FrameLayout.html<br />
**LayoutParams: http://developer.android.com/reference/android/widget/FrameLayout.LayoutParams.html<br />
<br />
==Caso práctico==<br />
*Comezamos creando un novo proxecto: '''U2_03_Frame'''.<br />
<br />
*A continuación cambiamos o contido do XML do layout polo seguinte:<br />
<br />
<syntaxhighlight lang="xml" line highlight="1,14"><br />
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent" ><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="@string/hello_world" /><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:layout_margin="30dp"<br />
android:text="Texto 1" /><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:background="#0F0"<br />
android:text="Texto 2" /><br />
<br />
</FrameLayout><br />
</syntaxhighlight><br />
<br />
*Observar que o elemento Raíz é '''FrameLayout'''.<br />
*Observar como a segunda Vista (O TexView Texto 1) ten unha marxe para todos os lados de 30 dp.<br />
*Observar como a terceira Vista (TextView Texto 2) superponse sobre a primeira.<br />
<br />
<br />
*A imaxe amosa o resultado do '''XML''' anterior.<br />
[[Image:Android_2013_U2_03_Frame_01.jpg]]<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=RelativeLayout&diff=57086RelativeLayout2015-07-24T11:39:55Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Tamén é outro dos layouts máis comúns.<br />
*As vistas (views) poden '''posicionarse''' en relación:<br />
** a '''outras views''' (o que está arriba, abaixo, a dereita,...). Para iso vai facer falla usar '''IDs'''.<br />
***android:layout_above<br />
***android:layout_below<br />
***android:layout_toLeftOf<br />
***android:layout_toRightOf<br />
***android:layout_alignLeft<br />
***android:layout_alignRight<br />
***android:layout_alignTop<br />
***android:layout_alignBottom<br />
***android:layout_alignBaseline<br />
** ao seu '''contedor ou pai''', que é un layout (arriba, centrado, abaixo, ...).<br />
***android:layout_alignParentLeft<br />
***android:layout_alignParentRight<br />
***android:layout_alignParentTop<br />
***android:layout_alignParentBottom<br />
***android:layout_centerHorizontal<br />
***android:layout_centerVertical<br />
***android:layout_centerInParent<br />
<br />
<br />
[[Image:00_relativelayout.png]]<br />
<br />
<br />
*É un layout moi potente, que facilita o deseño e fai sinxelo entender o arquivo xml.<br />
*Como norma, se un layout ten varios LinearLayout aniñados, é necesario substituílos por un RelativeLayout.<br />
*Como se dixo, o posicionamento dun View faise en base a o seu contedor pai ou en base a outro View referenciado polo seu id. <br />
*Se non se referencia a posición, por defecto, todos as views fillas son postas na parte esquerda superior do seu contedor.<br />
<br />
Pódense consultar todas as opcións de posicionamento en:<br />
*Referencias:<br />
**RelativeLayout: http://developer.android.com/guide/topics/ui/layout/relative.html<br />
**Opcións de posicionamento: http://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html<br />
<br />
==Casos prácticos==<br />
*Comezamos creando un novo proxecto: '''U2_05_Relative'''<br />
<br />
===Vistas sen referencias de posición===<br />
*No seguinte xml as vistas (botóns neste caso) non teñen unha referencia de posición, polo tanto, todas van estar ubicadas na posición esquerda-superior.<br />
<br />
<syntaxhighlight lang="xml" line highlight="1,21"><br />
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent" ><br />
<br />
<Button<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Preme 1"/><br />
<br />
<Button<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Preme 2" /><br />
<br />
<Button<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Preme 3" /><br />
<br />
</RelativeLayout><br />
</syntaxhighlight><br />
<br />
[[Image:Android_2013_U2_05_Relative_01.jpg|300px]] <br />
<br />
<br />
<br />
<br />
===Vistas posicionadas en relación a outras vistas===<br />
*Para iso precisamos crear un identificador (ID) para a vista/s que se van usar como referencia.<br />
[[Image:Android_2013_U2_05_Relative_02.jpg|350px]] <br />
<br />
<br />
*E logo na vista que se desexa ubicar en relación a outra vista facer uso dese ID.<br />
[[Image:Android_2013_U2_05_Relative_03.jpg|350px]] <br />
<br />
<br />
*A continuación o contido XML do layout:<br />
<syntaxhighlight lang="xml" line highlight="7,13,19"><br />
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent" ><br />
<br />
<Button<br />
android:id="@+id/btBoton1"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Preme 1"/><br />
<br />
<Button<br />
android:layout_toRightOf="@id/btBoton1"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Preme 2" /><br />
<br />
<Button<br />
android:layout_below="@id/btBoton1"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Preme 3" /><br />
<br />
</RelativeLayout><br />
</syntaxhighlight><br />
<br />
*A imaxe amosa a representación gráfica do layout.<br />
[[Image:Android_2013_U2_04_Linear_03A.jpg|300px]]<br />
<br />
===Vistas posicionadas en relación ao pai e a outras vistas===<br />
<br />
<syntaxhighlight lang="xml" line highlight="7,13,19,25,32"><br />
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent" ><br />
<br />
<Button<br />
android:id="@+id/btBoton1"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Preme 1"/><br />
<br />
<Button<br />
android:layout_toRightOf="@id/btBoton1"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Preme 2" /><br />
<br />
<Button<br />
android:layout_below="@id/btBoton1"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Preme 3" /><br />
<br />
<Button<br />
android:id="@+id/btBoton4"<br />
android:layout_centerInParent="true"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Preme 4" /><br />
<br />
<Button<br />
android:layout_alignBaseline="@id/btBoton4"<br />
android:layout_alignParentRight="true"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Preme 5" /><br />
<br />
</RelativeLayout><br />
</syntaxhighlight><br />
<br />
*Observar os botóns '''Preme 4''' e '''Preme 5''' como teñen algunha referencia ao Pai para ser ubicados.<br />
[[Image:Android_2013_U2_05_Relative_04.jpg|300px]]<br />
<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Combinaci%C3%B3n_de_layouts&diff=57084Combinación de layouts2015-07-24T11:39:31Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Os layouts pódense combinar e aniñar uns dentro doutros.<br />
<br />
<br />
==Caso práctico==<br />
*Creamos un novo proxecto: U2_07_Combinados<br />
**'''NOTA Edición 2015''': Existe un programa U2_07_ con outro nome da edición 2013, que faremos na sección de controis dentro desta unidade. Para non renumerar todo o que vén a continuación para a edición 2015, teremos 2 programas U2_07: U2_07_Combinados e U2_07_ TextView (o faremos despois). <br />
<br />
===Combinación de layouts Relativos e Liniais===<br />
*A imaxe amosa a distribución que se quere ter: <br />
[[Image:Android_2014_U2_07_Combinados_01.jpg]]<br />
<br />
*O '''color malva''' é un LayoutRelative, que ten un recheo de 30dp.<br />
*Este layout contén:<br />
**Un botón: Botón 1<br />
**Un LinearLayout de '''cor verde''' (o que está cos bordes de cor azul cor verde é os cadradiños).<br />
**Este LinearLayout contén 3 Linears Layouts en disposición horizontal e cun peso igual para cada un deles para distribuír o ancho do que lle deixa o pai.<br />
***A altura deste linearlayout (cor verde) é a que lle deixa o pai.<br />
***Os tres layouts organízanse do seguinte modo:<br />
****O primeiro LinearLayout ('''Cor azul''') ten unha disposición horizontal (as views dentro del están unha á dereita da outra)<br />
*****A altura deste layout adáptase á altura dos elementos que contén. <br />
****O segundo LinearLayout ('''Cor rosa''') ten nunha disposición vertical (as views dentro del están unha debaixo da outra).<br />
*****A altura deste layout adáptase á altura dos elementos que contén. <br />
****O terceiro LinearLayout ('''Cor vermello''') ten nunha disposición vertical (as views dentro del están unha debaixo da outra).<br />
*****A altura deste layout adáptase á altura total do pai (Layout de cor verde). <br />
<br />
<br />
<br />
*Este exemplo traballa só con Relative e Linear layouts, pero poderíase traballar con calquera outro layout dos vistos e non vistos neste curso.<br />
<br />
===XML asociado ao Layout===<br />
<syntaxhighlight lang="xml" line highlight="1,10,15,18,20,22,24,25,27,32,38,40,42,43,45,50,61,63,65,68,78,79,81"><br />
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:background="#AAF"<br />
android:padding="30dp"<br />
tools:context="com.example.u2_07_combinados.U2_07_Combinados" ><br />
<br />
<Button<br />
android:id="@+id/Boton1"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Botón 1" /><br />
<br />
<LinearLayout<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:layout_below="@id/Boton1"<br />
android:background="#AFA"<br />
android:orientation="horizontal" ><br />
<br />
<LinearLayout<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:layout_weight="1"<br />
android:background="#3AF"<br />
android:orientation="horizontal" ><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Linear\nHorz. 1" /><br />
<br />
<Button<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="B2" /><br />
</LinearLayout><br />
<br />
<LinearLayout<br />
android:layout_width="match_parent"<br />
android:layout_height="wrap_content"<br />
android:layout_weight="1"<br />
android:background="#FAA"<br />
android:orientation="vertical" ><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="LinearLayout Vertical 2 \n... 2ª Liña" /><br />
<br />
<Button<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Botón 3" /><br />
<br />
<Button<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Botón 4" /><br />
</LinearLayout><br />
<br />
<LinearLayout<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:layout_weight="1"<br />
android:background="#F55"<br />
android:orientation="vertical" ><br />
<br />
<TextView<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="LinearLayout Vertical 3" /><br />
<br />
<ToggleButton<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content" /><br />
</LinearLayout><br />
</LinearLayout><br />
<br />
</RelativeLayout><br />
</syntaxhighlight><br />
<br />
*Explicación, liñas:<br />
**'''1 a 81''': onde se abre e se pecha o Relative Layout. Contén un botón e un linear layout que se abre na liña 15 e pécase na 79.<br />
**'''10''': Dáselle un ID ao botón.<br />
**'''15 a 81''': Ábrese un linear layout con disposición dos seus elementos (3 LinearLayouts) en horizontal (liña 20).<br />
**'''18''': Indica que o LinearLayout anterior se sitúe debaixo do botón.<br />
**'''22 a 38''': O primeiro LinearLayout que dispón os seus elementos en horizontal (Liña 27).<br />
**'''24, 42 e 65''': Observar como se indica a altura de cada un dos tres layouts. Nos dous primeiros casos que se adapte á altura dos elementos que contén e no terceiro á altura do pai.<br />
**'''25, 43 e 66''': Indícase o peso co que se distribúe cada un dos layouts (1/3 para cada un).<br />
**'''32 e 50''': Observar como se introduce un código de control (como en Java) para o salto de liña '''\n'''.<br />
*O resto das liñas marcadas, a bo seguro que o participante no curso é quen de interpretalas.<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=TextView._Definici%C3%B3n_de_recursos_XML&diff=57082TextView. Definición de recursos XML2015-07-24T11:39:02Z<p>Angelfg: </p>
<hr />
<div>==Introdución==<br />
*Un '''TextView''' é unha etiqueta de texto que serve para amosar texto na aplicación.<br />
*Este control é unha subclase da clase '''View'''.<br />
*Opcionalmente pódese permitir editar o contido.<br />
*A clase que implementa o control vén configurada para non permitir a edición.<br />
<br />
<br />
*Aproveitando que este é o primeiro control que imos ver, tamén imos explicar como se definen '''constantes''' para usar nos recursos XML.<br />
<br />
<br />
*'''Referencias''':<br />
**A clase '''View''': http://developer.android.com/reference/android/view/View.html<br />
***Antes de continuar é importante familiarizarse (non fai falla aprender nada) cos métodos, subclases e atributos que ten esta clase de que van colgar todos os demais controis. Co cal, aparte de pararse na seguinte imaxe, é aconsellable premer no enlace anterior.<br />
[[Image:00_Part_of_Android_View_Hierarchy.png|600px]]<br />
***Imaxe obtida de: http://www.itcsolutions.eu/2011/08/27/android-tutorial-4-procedural-vs-declarative-design-of-user-interfaces<br />
**Control TextView: http://developer.android.com/reference/android/widget/TextView.html<br />
***Observar no enlace anterior o valor do atributo '''editable'''.<br />
**Recomendacións de tipografía: http://developer.android.com/design/style/typography.html<br />
***Observar no enlace anterior o tamaño recomendado en px do lanzador dunha aplicación en Google Play.<br />
**Cores: http://developer.android.com/guide/topics/resources/more-resources.html#Color<br />
***Observar en que formatos se pode describir unha cor.<br />
<br />
<br />
<br />
<br />
===Casos prácticos===<br />
*Comezamos creando un novo proxecto: '''U2_07_TextView'''.<br />
*Imos comezar creando un layout con 2 TextViews, onde o segundo TextView se modifica en tempo de execución (ao iniciarse a aplicación).<br />
<br />
[[Image:Android_2013_U2_07_TextView_01.jpg|300px]]<br />
*A imaxe amosa en tempo de deseño os 2 TextViews.<br />
*Le o contido da etiqueta azul.<br />
<br />
*O XML do layout asociado a esa imaxe é:<br />
<syntaxhighlight lang="xml" line highlight="9,12,15,18,19" enclose="div"><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:padding="20sp"<br />
android:orientation="vertical" ><br />
<br />
<TextView<br />
android:id="@+id/tv_orixinal"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="@string/hello_world" /><br />
<br />
<TextView<br />
android:id="@+id/tv_java"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:textColor="#00F"<br />
android:text="Dá igual o que escribamos aquí. Neste exemplo, ao lanzar a aplicación, vaise cambiar este texto" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
*'''NOTA ECLIPSE''': os campos dos controis pódense poñer na orde que se desexe. Se se preme '''SHIFT+CTRL+F''' Eclipse vai organizar o código e ordenar os campos. Esa combinación de teclas pode usarse tanto en código XML como Java.<br />
*Nas liñas 9 e 15 asóciase un ID a cada control, TextView, que logo usaremos en Java.<br />
*Observar as diferenzas entre as liñas 12 e 19. A primeira amosará o texto que contén a constante definida en XML (noutro ficheiro XML), a segunda amosa o texto directamente.<br />
*Como xa se sabe, neste caso, a definición da constante '''@string/hello_world''' está no ficheiro de recursos: '''/res/values/strings.xml'''.<br />
<br />
[[Image:Android_2013_U2_07_TextView_02.jpg|150px]]<br />
<br />
<syntaxhighlight lang="xml" line highlight="6"><br />
<?xml version="1.0" encoding="utf-8"?><br />
<resources><br />
<br />
<string name="app_name">U2_07_TextView</string><br />
<string name="action_settings">Settings</string><br />
<string name="hello_world">Hello world!</string><br />
<br />
</resources><br />
</syntaxhighlight><br />
<br />
*Como xa se dixo é recomendable usar o primeiro caso, pero no material vaise ''abusar'' do segundo caso para que se entendan os exemplos máis facilmente.<br />
*No segundo caso, como xa se indicou, o IDE Eclipse dará unha advertencia na liña 19 porque recomenda que esa propiedade se declare a través dunha constante.<br />
<br />
<br />
*As liñas 9 e 15 están creando o ID para os controis para que poidan ser accedidos dende Java a través da Clase R.<br />
*Observar na imaxe a declaración deses IDs. <br />
[[Image:Android_2013_U2_07_TextView_04.jpg|600px]]<br />
*Isto xerase automaticamente cando se ten '''gardado o documento XML''' onde se declaran os controis.<br />
<br />
<br />
*Finalmente mirar como se define a cor azul (RGB), liña 18. Esta definición tamén podería estar usando unha constante declarada noutro ficheiro XML, como se verá ao final deste apartado.<br />
<br />
===Acceder e manipular o control dende Java===<br />
*A continuación imos acceder ao control EditText declarado en XML dende Java e imos realizar accións sobre o control.<br />
*Para iso imos á clase Java que lanza a aplicación. (Por agora só hai unha clase Java).<br />
[[Image:Android_2013_U2_07_TextView_03.jpg|600px]]<br />
<br />
*Como xa se indicou, podemos acceder aos elementos visuais declarados en XML a través do seu ID usando de intermediaria a clase R.<br />
[[Image:Android_2013_U2_07_TextView_04.jpg|600px]]<br />
<br />
<br />
*Dentro do método '''onCreate()''' que é o encargado de lanzar a Activity, como se verá máis adiante.<br />
[[Image:Android_2013_U2_07_TextView_05.jpg|600px]]<br />
*Comezamos a declarar un obxecto de tipo TextView.<br />
*A medida que imos escribindo o tipo se prememos '''CTRL+ Barra espaciadora''' xa sabemos que nos vai a autocompletar, pero ademais vai '''importar o paquete''' que define onde está declarada a clase. <br />
[[Image:Android_2013_U2_07_TextView_07.jpg|600px]]<br />
<br />
<br />
*Declaramos un obxecto de tipo TextView e queremos asocialo ao primeiro TextView do Layaout (ID:tv_orixinal).<br />
[[Image:Android_2013_U2_07_TextView_08.jpg|600px]]<br />
*Para iso precisamos o método '''findViewById()''':<br />
**'''Recibe como parámetro unha constante''' da Clase R: neste caso o id asociado a un elemento visual. (CTRL+Barra espaciadora, para localizar a constante).<br />
**'''Devolve un obxecto''' de tipo '''View'''.<br />
*Todo control visual é unha '''subclase''' de '''View''', por tanto como obtemos un obxecto View é preciso facer un '''casting''' '''(TextView)''' para que faga unha conversión de tipos ao tipo desexado, neste caso dun '''obxecto tipo View''' a un '''obxecto de tipo TextView'''.<br />
<br />
<br />
*A continuación amósase o código Java que vai manipular o TextView<br />
<syntaxhighlight lang="java" line highlight="15,16,18"><br />
package com.example.u2_07_textview;<br />
<br />
import android.app.Activity;<br />
import android.os.Bundle;<br />
import android.view.Menu;<br />
import android.widget.TextView;<br />
<br />
public class U2_07_TextView extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_07__text_view);<br />
<br />
final TextView tvOrixinal = (TextView) findViewById(R.id.tv_orixinal);<br />
final TextView tvJava = (TextView) findViewById(R.id.tv_java);<br />
<br />
tvJava.setText("Etiqueta modificada en java: "+tvOrixinal.getText());<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_07__text_view, menu);<br />
return true;<br />
}<br />
}<br />
</syntaxhighlight><br />
*Liña 15: temos un obxecto que apunta a TextView orixinal, ao primeiro TextView do Layout.<br />
*Liña 16: temos un obxecto que apunta ao novo TextView, ao segundo do Layout.<br />
*Liña 18: modificamos o texto do segundo TextView. O contido é unha cadea de texto concatenada (+) co texto que ten o primeiro TextView.<br />
**Observar a función dos métodos: '''setText()''' e '''getText()'''. No seguinte enlace pódense ver estes métodos públicos: http://developer.android.com/reference/android/widget/TextView.html#pubmethods. <br />
*Cando se lance a aplicación vaise executar ese código, co cal o texto do segundo TextView non vai ser o que se indicou no Layout en tempo de deseño senón o que se indica en tempo de execución.<br />
<br />
*A imaxe amosa a execución da aplicación:<br />
[[Image:Android_2013_U2_07_TextView_09.jpg|300px]]<br />
*Observar o contido da segunda liña, non é o que se asignou no Layout.<br />
<br />
===Manipulación html dunha etiqueta de texto===<br />
*As Etiquetas de texto non son texto (String) senón que son código semellante ao html.<br />
*Entón na liña 18 anterior parece que hai unha contradición: concatenar unha cadea con ''algo'' html.<br />
*Teríamos que ter usado o método '''toString()''': '''tvOrixinal.getText().toString()'''<br />
*Pero en Java non fai falla poñelo porque ese método chámase automaticamente sempre que o obxecto se concatene con outro String (Neste caso a cadea de texto).<br />
<br />
<br />
*Para obter a seguinte imaxe non se vai tocar o XML e vaise facer todo en Java.<br />
[[Image:Android_2013_U2_07_TextView_10.jpg|300px]]<br />
*Na segunda etiqueta cambiouse: cor, tamaño da fonte e púxose en '''negriña''' unha palabra.<br />
<br />
<br />
*Código JAVA ...<br />
<syntaxhighlight lang="java" line highlight="21-25"><br />
package com.example.u2_07_textview;<br />
<br />
import android.app.Activity;<br />
import android.graphics.Color;<br />
import android.os.Bundle;<br />
import android.text.Html;<br />
import android.view.Menu;<br />
import android.widget.TextView;<br />
<br />
public class U2_07_TextView extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_07__text_view);<br />
<br />
final TextView tvOrixinal = (TextView) findViewById(R.id.tv_orixinal);<br />
final TextView tvJava = (TextView) findViewById(R.id.tv_java);<br />
<br />
tvJava.setText("Etiqueta modificada en java: "+tvOrixinal.getText());<br />
tvJava.append(". Máis texto. ");<br />
tvJava.setTextColor(Color.RED);<br />
tvJava.setTextSize(20);<br />
tvJava.append(Html.fromHtml("<p><br>Isto está en <b>negriña</b> e noutra liña.</p>"));<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_07__text_view, menu);<br />
return true;<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
*Para importar os paquetes premer (SHIFT + CTRL + O)<br />
<br />
<br />
*Liña 21: engade contido á etiqueta polo final da mesma e amosa o contido final.<br />
*Liña 22: cambiar a cor usando unha constante estática.<br />
*Liña 23: cambiar o tamaño da fonte<br />
*Liña 24: devolve a cadea en formato HTML no que en Android se podería chamar ''Texto con estilo mostrable''<br />
<br />
<br />
<br />
*A continuación vaise modificar a aplicación para que poidamos recuperar o contido exacto dun ''TextView'', non o que amosa por pantalla.<br />
*Tamén se vai usar o método '''toString()''' para ver o seu resultado.<br />
<br />
<br />
*A imaxe amosa o deseño do Layout<br />
[[Image:Android_2013_U2_07_TextView_11.jpg|300px]]<br />
*Observar a liña de separación e despois desta, dúas etiquetas de texto.<br />
<br />
*O Ficheiro XML asociado<br />
<syntaxhighlight lang="xml" line highlight="21-24,26,32" enclose="div"><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical"<br />
android:padding="20sp" ><br />
<br />
<TextView<br />
android:id="@+id/tv_orixinal"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="@string/hello_world" /><br />
<br />
<TextView<br />
android:id="@+id/tv_java"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Dá igual o que escribamos aquí. Neste exemplo, ao lanzar a aplicación, vaise cambiar este texto"<br />
android:textColor="#00F" /><br />
<br />
<View<br />
android:layout_width="match_parent"<br />
android:layout_height="2sp"<br />
android:background="#000" /><br />
<br />
<TextView<br />
android:id="@+id/tv_html"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="Cadena html do tv_java. Realizarase en java" /><br />
<br />
<TextView<br />
android:id="@+id/tv_string"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="String do tv_java. Realizarase en java"<br />
android:textColor="#00F"<br />
android:textSize="16sp" /><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
*Observar as liñas marcadas<br />
<br />
*A imaxe amosa a aplicación en execución:<br />
[[Image:Android_2013_U2_07_TextView_12.jpg|300px]]<br />
*Observar como a primeira etiqueta despois da liña ten o contido do que almacena o EditText vermello.<br />
*A segunda etiqueta despois da liña amosa a etiqueta vermella pasada polo método '''toString'''. Observar como xa non hai negriña.<br />
<br />
<br />
*O código que fai iso posible é o seguinte:<br />
<syntaxhighlight lang="java" line highlight="21,22,33,35,36"><br />
package com.example.u2_07_textview;<br />
<br />
import android.R.string;<br />
import android.app.Activity;<br />
import android.graphics.Color;<br />
import android.os.Bundle;<br />
import android.text.Html;<br />
import android.text.Spanned;<br />
import android.view.Menu;<br />
import android.widget.TextView;<br />
<br />
public class U2_07_TextView extends Activity {<br />
<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_u2_07__text_view);<br />
<br />
final TextView tvOrixinal = (TextView) findViewById(R.id.tv_orixinal);<br />
final TextView tvJava = (TextView) findViewById(R.id.tv_java);<br />
final TextView tvHtml = (TextView) findViewById(R.id.tv_html);<br />
final TextView tvString = (TextView) findViewById(R.id.tv_string);<br />
<br />
tvJava.setText("Etiqueta modificada en java: "+tvOrixinal.getText());<br />
<br />
//tvJava.setText(tvJava.getText()+". Máis texto. ");<br />
tvJava.append(". Máis texto. ");<br />
tvJava.setTextColor(Color.RED);<br />
tvJava.setTextSize(20);<br />
tvJava.append(Html.fromHtml("<p><br>Isto está en <b>negriña</b> e noutra liña.</p>"));<br />
<br />
<br />
tvHtml.setText(Html.toHtml((Spanned)(tvJava.getText())));<br />
<br />
//tvString.setText(""+tvJava.getText());<br />
tvString.setText(tvJava.getText().toString());<br />
<br />
}<br />
<br />
@Override<br />
public boolean onCreateOptionsMenu(Menu menu) {<br />
// Inflate the menu; this adds items to the action bar if it is present.<br />
getMenuInflater().inflate(R.menu.u2_07__text_view, menu);<br />
return true;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*Liña 33: colle o valor da etiqueta vermella e a pasa a formato Html.<br />
*Liña 36: pasa a cadea vermella a String. Sería o equivalente á liña 35 (Concatenar cunha cadea).<br />
<br />
===Definición de constantes/recursos xml===<br />
*Como xa vimos na definición XML do Layout temos valores postos á ''ferro''.<br />
*Sería bo definir esas propiedades noutros ficheiros XML, deste xeito permítese a reutilización e a internacionalización.<br />
<br />
<br />
<gallery caption="Recursos string" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_07_TextView_13.jpg| Advertencia no XML indicando que ...<br />
Image:Android_2013_U2_07_TextView_14.jpg| usemos un recurso de tipo @string. <br />
Image:Android_2013_U2_07_TextView_15.jpg| Editamos o ficheiro '''res/values/strings.xml''' ou creamos un novo en '''/res/values'''<br />
</gallery><br />
*Engadimos os novos recurso de tipo string. Observar as liñas marcadas.<br />
<syntaxhighlight lang="xml" line highlight="8-10" enclose="div"><br />
<?xml version="1.0" encoding="utf-8"?><br />
<resources><br />
<br />
<string name="app_name">U2_07_TextView</string><br />
<string name="action_settings">Settings</string><br />
<string name="hello_world">Hello world!</string><br />
<br />
<string name="texto_tv_java">Dá igual o que escribamos aquí. Neste exemplo, ao lanzar a aplicación, vaise cambiar este texto</string><br />
<string name="texto_tv_html">Cadena html do tv_java. Realizarase en java</string><br />
<string name="texto_tv_string">String do tv_java. Realizarase en java</string> <br />
<br />
</resources><br />
</syntaxhighlight><br />
*Gardar o ficheiro<br />
<br />
<br />
<gallery caption="Uso recursos string" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_07_TextView_16.jpg| No layout facemos uso dos recursos anteriores: (CTRL + Barra espaciadora). Lembrar gardar antes o ficheiro de recursos anterior.<br />
Image:Android_2013_U2_07_TextView_17.jpg| Xa quedan menos advertencias: A da dimensión podería declararse no ficheiro '''/res/values/dimens.xml''' ou crear un novo.<br />
</gallery><br />
<br />
<syntaxhighlight lang="xml" line highlight="6"><br />
<resources><br />
<br />
<!-- Default screen margins, per the Android Design guidelines. --><br />
<dimen name="activity_horizontal_margin">16dp</dimen><br />
<dimen name="activity_vertical_margin">16dp</dimen><br />
<dimen name="alto_liña">2sp</dimen><br />
<br />
</resources><br />
</syntaxhighlight><br />
<br />
<br />
<br />
*A continuación vaise crear un ficheiro de recurso para as cores.<br />
<gallery caption="Crear ficheiro de recursos" widths="350" heights="300px" perrow="2"><br />
Image:Android_2013_U2_07_TextView_18.jpg| En '''/res/values''' creamos un novo ficheiro '''Android XML File'''<br />
Image:Android_2013_U2_07_TextView_19.jpg| Indicamos un nome significativo, vale calquera. Neste caso ''colors'' e gardamos.<br />
Image:Android_2013_U2_07_TextView_20.jpg| Imos ao ficheiro<br />
Image:Android_2013_U2_07_TextView_21.jpg| Engadimos un elemento<br />
Image:Android_2013_U2_07_TextView_22.jpg| Seleccionar '''Color''' e aceptar.<br />
Image:Android_2013_U2_07_TextView_23.jpg| Engadimos a definición dunha cor graficamente ...<br />
Image:Android_2013_U2_07_TextView_24.jpg| ... en modo texto.<br />
</gallery><br />
<br />
*Ficheiro de recurso de cores:<br />
<syntaxhighlight lang="xml" line highlight="3-4"><br />
<?xml version="1.0" encoding="utf-8"?><br />
<resources><br />
<color name="azul">#00F</color><br />
<color name="negro">#000</color><br />
<br />
</resources><br />
</syntaxhighlight><br />
<br />
<br />
<br />
*Uso dos recursos no layout. Como sempre, observar as liñas marcadas<br />
<syntaxhighlight lang="xml" line highlight="12,18,19,23,24,30,36,38"><br />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
xmlns:tools="http://schemas.android.com/tools"<br />
android:layout_width="match_parent"<br />
android:layout_height="match_parent"<br />
android:orientation="vertical"<br />
android:padding="20sp" ><br />
<br />
<TextView<br />
android:id="@+id/tv_orixinal"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="@string/hello_world" /><br />
<br />
<TextView<br />
android:id="@+id/tv_java"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="@string/texto_tv_java"<br />
android:textColor="@color/azul" /><br />
<br />
<View<br />
android:layout_width="match_parent"<br />
android:layout_height="@dimen/alto_liña"<br />
android:background="@color/negro" /><br />
<br />
<TextView<br />
android:id="@+id/tv_html"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:text="@string/texto_tv_html" /><br />
<br />
<TextView<br />
android:id="@+id/tv_string"<br />
android:layout_width="wrap_content"<br />
android:layout_height="wrap_content"<br />
android:textColor="@color/azul"<br />
android:textSize="16sp" <br />
android:text="@string/texto_tv_string"/><br />
<br />
</LinearLayout><br />
</syntaxhighlight><br />
<br />
*Anda!!! Quedounos na liña 37 un valor candidato a ser definido nunha constante tipo ''dimen''. Seguro que o participante no curso é quen de facelo.<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2015).</div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Archivo:Android_2013_olamundo_06.jpg&diff=57069Archivo:Android 2013 olamundo 06.jpg2015-07-22T11:30:33Z<p>Angelfg: Angelfg subió una nueva versión de «Archivo:Android 2013 olamundo 06.jpg»</p>
<hr />
<div></div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Archivo:Android_2013_avd_14.jpg&diff=57059Archivo:Android 2013 avd 14.jpg2015-07-22T08:36:05Z<p>Angelfg: Angelfg subió una nueva versión de «Archivo:Android 2013 avd 14.jpg»</p>
<hr />
<div></div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Archivo:Android_2014_ubuntu_35.jpeg&diff=57053Archivo:Android 2014 ubuntu 35.jpeg2015-07-14T08:38:49Z<p>Angelfg: Angelfg subió una nueva versión de «Archivo:Android 2014 ubuntu 35.jpeg»</p>
<hr />
<div></div>Angelfghttps://manuais.iessanclemente.net/index.php?title=Archivo:Android_2013_windows_29.jpg&diff=57047Archivo:Android 2013 windows 29.jpg2015-07-14T08:12:05Z<p>Angelfg: Angelfg subió una nueva versión de «Archivo:Android 2013 windows 29.jpg»</p>
<hr />
<div></div>Angelfg