En este apartado trataremos como comunicar
dos activities dentro del mismo proyecto. Para ello, lo primero es saber cómo
generar una nueva actividad. Simplemente en la sección de Project haremos click derecho à
New à Activity.
Bien, hecho esto, debemos saber que para
llamar desde una activity a otra usaremos la clase Intent. Permite desde una actividad invocar a otra (o varias), y
también pasar información a otras actividades y servicios y recibirla.
Existen dos tipos de Itents:
- Los explícitos, que nombran directamente el componente que se necesita. Por ejemplo, especifican la clase que será utilizada para realizar una determinada tarea.
- Los implíticitos, que sólo llaman a la actividad, sin indicar que método debe recogerlo.
Para el tipo explícito, en la Activity
madre el código que usaremos para abrir una nueva será
public void
onClick(View arg0){
Intent i = new Intent(this,
SegundaActividad.class);
startActivity(i);
}
Método explícito
Vamos a generar una aplicación que,
pulsando sobre un botón en la primera activity, se abra la segunda. Algo
sencillo.
El Layout de la primera activity es el
siguiente
Y el Layout de la segunda actividad, llamada
inteligentemente Segunda, es este:
Ahora, como se trata de un método explícito
sin más, solo necesito generar una función que agregaré al botón de la primera
actividad.
El código es el siguiente:
public void
onClick(View arg0){
Intent i = new Intent(this, Segunda.class);
startActivity(i);
}
Y al ejecutar el programa vemos el antes y
el después (que en imagen estática es pelín complicado de mostrarlo, pero ahí
lo dejo por si acaso).
Este
programa es muy simple, así que vamos a intentar hacer algo que quede
visualmente más atractivo.
Tercera aplicación. Calculadora de Indice de Masa Corporal
Vamos a desarrollar una aplicación que
calcule el IMC (sabiendo que IMC = kg/m2) utilizando dos interfaces
gráficas distintas.
La primera actividad usa como tema
Theme.AppCompat
Y la segunda será Base.Theme.AppCompat.Dialog.FixedSize.
Advertencia:
Aunque el enunciado no lo indique se da por supuesto que todo
buen programador controla los posibles errores (datos no introducidos,
divisiones por cero, edades negativas…).
Bueno, vayamos por pasos. Este es mi layout
principal, que he llamado IMC.
Y este el secundario, llamado IMCAyuda.
Dentro de IMCAyuda yendo a la pestaña texto
modifico el campo android:theme con el valor @style/Base.Theme.AppCompat.Dialog.FixedSize.
Y ahora vayamos al código. Primero, IMC.java. Como siempre, entre bordes el
código creado por mí.
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.text.DecimalFormat;
public class IMC extends AppCompatActivity {
private Button btnCalcula;
private Button btnAyuda;
private EditText txtKilos;
private EditText txtAltura;
@Override
protected void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_imc);
}
@Override
public boolean
onCreateOptionsMenu(Menu menu) {
// Inflate the
menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_imc, menu);
return true;
}
public void calcularIMC(View arg0){
btnCalcula = (Button)findViewById(R.id.btnCalcula);
btnAyuda = (Button)findViewById(R.id.btnAyuda);
txtKilos = (EditText)findViewById(R.id.txtKilos);
txtAltura = (EditText)findViewById(R.id.txtAltura);
if (txtKilos.getText().toString().equals("") ||
txtAltura.getText().toString().equals("")){
Toast.makeText(this, "Debe rellenar los campos de peso y
altura", Toast.LENGTH_SHORT).show();
}
else{
double peso = Double.parseDouble(txtKilos.getText().toString());
double altura = Double.parseDouble(txtAltura.getText().toString());
if (peso <= 0 || altura <=
0){
Toast.makeText(this, "El
valor 0 no es admisible. Usted ocupa más volumen que eso",
Toast.LENGTH_SHORT).show();
}
else{
altura = altura / 100; // Debo
calcular en metros, no centímetros
double imc = peso / (altura *
altura);
DecimalFormat f = new
DecimalFormat("#.##");
String resultado = "Indice
de masa corporal: " + f.format(imc);
if(imc < 16.00){
resultado = resultado +
". \nDelgadez severa";
Toast.makeText(this,
resultado, Toast.LENGTH_SHORT).show();
}
if(imc >= 16.00 &&
imc < 17.00){
resultado = resultado +
". \nDelgadez moderada";
Toast.makeText(this,
resultado, Toast.LENGTH_SHORT).show();
}
if(imc >= 17.00 &&
imc < 18.50){
resultado = resultado +
". \nDelgadez leve";
Toast.makeText(this,
resultado, Toast.LENGTH_SHORT).show();
}
if(imc >= 18.00 &&
imc < 25.00){
resultado = resultado +
". \nIMC normal";
Toast.makeText(this,
resultado, Toast.LENGTH_SHORT).show();
}
if(imc >= 25.00 &&
imc < 30.00){
resultado = resultado +
". \nTiene sobrepeso";
Toast.makeText(this,
resultado, Toast.LENGTH_SHORT).show();
}
if(imc >= 30.00 &&
imc < 35.00){
resultado = resultado +
". \nObesidad leve";
Toast.makeText(this,
resultado, Toast.LENGTH_SHORT).show();
}
if(imc >= 35.00 &&
imc < 40.00){
resultado = resultado +
". \nObesidad media";
Toast.makeText(this,
resultado, Toast.LENGTH_SHORT).show();
}
if(imc >= 40.00){
resultado = resultado +
". \nObesidad mórbida";
Toast.makeText(this,
resultado, Toast.LENGTH_SHORT).show();
}
}
}
}
public void onClick(View v){
Intent i = new Intent(this, IMCAyuda.class);
startActivity(i);
}
@Override
public boolean onOptionsItemSelected(MenuItem
item) {
// Handle action
bar item clicks here. The action bar will
// automatically
handle clicks on the Home/Up button, so long
// as you specify
a parent activity in AndroidManifest.xml.
int id =
item.getItemId();
//noinspection
SimplifiableIfStatement
if (id ==
R.id.action_settings) {
return true;
}
return
super.onOptionsItemSelected(item);
}
}
Como se puede ver, tengo dos funciones, calcularIMC(View arg0) que lo que hace
es coger los datos de los EditText y calcular el IMC correspondiente,
controlando los errores de campos vacíos o con números negativos, y otra función
onClick(View v) que simplemente hace
la llamada a la segunda Activity.
Veamos ahora IMCAyuda.java
import android.support.v4.view.MotionEventCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
public class IMCAyuda extends AppCompatActivity {
public static final
String DEBUG_TAG = "IMCAyuda";
@Override
protected void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_imcayuda);
}
@Override
public boolean
onCreateOptionsMenu(Menu menu) {
// Inflate the
menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_imcayuda, menu);
return true;
}
public boolean onTouchEvent(MotionEvent event){
int action = MotionEventCompat.getActionMasked(event);
switch(action){
case(MotionEvent.ACTION_DOWN):
this.finish();
return true;
case(MotionEvent.ACTION_UP):
this.finish();
return true;
case(MotionEvent.ACTION_MOVE):
this.finish();
return true;
default:
return
super.onTouchEvent(event);
}
}
@Override
public boolean
onOptionsItemSelected(MenuItem item) {
// Handle action
bar item clicks here. The action bar will
// automatically handle clicks on the
Home/Up button, so long
// as you specify
a parent activity in AndroidManifest.xml.
int id =
item.getItemId();
//noinspection
SimplifiableIfStatement
if (id ==
R.id.action_settings) {
return true;
}
return
super.onOptionsItemSelected(item);
}
}
Con el evento OnTouchEvent(MotionEvent event) hago que cualquier acción de
presionar, mover el dedo y levantarlo quede capturado y cierre el segundo
activity. Realmente con ACTION_DOWN
ya valdría, pero por cerciorarme que no sea.
Al ejecutar el programa podemos ver dos
pantallas, una en la que calcula el IMC y la de ayuda, tal que así:
Método implícito
O como pasar datos de una actividad a otra.
Deberemos enviar un “extra” cuando
generemos el Intent, y capturarlo en
la segunda actividad con la clase Bundle.
Esta clase recibe del Intent un
elemento identificado con dos valores, el primero la clave del dato y el
segundo el valor del dato, que puede usarse con los elementos de su activity
haciendo la llamada.
Pongamos que tenemos Activity A y B.
El código del activity A para enviar un
dato sería
public void
onClick(View v){
Intent i = new Intent(this,
SegundaActividad.class);
// Envía un único dato
i.putExtra("nombreDelDatoAEnviar",
txtInfo.getText().toString());
startActivity();
}
Con este código estamos mandando la
información contenida en el elemento txtInfo
en una cadena de texto (porque lo he querido así, Bundle admite todo tipo de datos). Y para recibirla en la activity
B, por ejemplo en un EditText
haremos lo siguiente.
EditText txtPrueba =
(EditText)findViewById(R.id.txtPrueba);
Bundle bundle =
getIntent().getExtras();
txtPrueba.setText(bundle.getString("nombreDelDatoAEnviar"));
Lo que hacemos es crear un Bundle y almacenar ahí la información
pasada del Intent. Luego referenciamos
con el nombre de la clave de dato en el elemento que queremos cargar la
información.
También podemos pasar más de un valor, en
cuyo caso en la actividad que envía lo haríamos de la siguiente manera:
Bundle bundle = new
Bundle();
Bundle.putString("nombre",
txtNombre.getNombre().toString);
Bundle.putInt("edad",
txtEdad.getEdad());
intent.putExtras(bundle);
Es decir, generamos un Bundle y almacenamos ahí la información que queramos. Luego
insertamos el propio Bundle en un Intent y lo pasamos a la segunda Activity. Ahí
lo manejaremos tal cual el primer ejemplo, pues siempre hay que referenciar por
la clave del dato.
Cuarta aplicación. “Navegador web” con WebView
WebView
es usado para cargar páginas web dentro de una aplicación Android. No es un
navegador web como tal pues no tiene cargada la barra de direcciones, pero sí
permite mostrar páginas (y creo que con paciencia se podría conseguir un
estilismo similar a un navegador web. Tal vez no todas sus funcionalidades,
pero podría intentarse).
El ejercicio será crear una activity con un
EditText en el que se escribirá una dirección
web, y pulsando un botón que se mande a una segunda actividad donde se cargará
dicha dirección en el WebView.
Hay que tener en cuenta que habrá que dar
permisos en el Manifest para que
nuestra aplicación tenga acceso a Internet.
Y un último dato. El uso de WebView está desansejado, a partir de
Enero de 2015, para las versiones de Android inferiores a KitKat (API 17).
Bien, dicho esto, estos son los diseños de
mis Layouts.
El principal, Navegador,simplemente recoge la URL en ese EditText y se envía al pulsar el botón.
El segundo Layout, Web, que contiene el WebView, queda tal que así
Y su configuración XML para conseguir
ocupar toda la pantalla correctamente es la siguiente:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
tools:context="es.claver.inazio.navegadorweb.Web"
android:background="#0288d1">
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/pagWeb"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
En el Manifiest escribimos los permisos justo
después de <manifiest>:
Y ahora a por el código.
En Navegador.java
la función programada que asigno al botón es:
public void
enviarPagina(View v){
btnGo = (Button)findViewById(R.id.btnGo);
txtURL = (EditText)findViewById(R.id.txtURL);
Intent i = new Intent(this, Web.class);
// Envío el dato
i.putExtra("pagina",
txtURL.getText().toString());
startActivity(i);
}
Y en Web.java
creo la función cargarWeb() y la
añado al onCreate().
protected void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
cargarWeb();
}
public void
cargarWeb(){
pagWeb =
(WebView)findViewById(R.id.pagWeb);
pagWeb.setWebViewClient(new
WebViewClient());
bundle = getIntent().getExtras();
pagWeb.loadUrl("http://" +
bundle.getString("pagina"));
// Habilitar JavaScript
WebSettings webSettings =
pagWeb.getSettings();
webSettings.setJavaScriptEnabled(true);
}
En cargarWeb()
con el método loadUrl() hago una
concatenación del protocolo “http://” más la página web que ha escrito el
usuario.
Y en las siguientes líneas habilito el
JavaScript del WebView por si acaso se requiere para la página web a visitar.
Al lanzar la aplicación el resultado es el
siguiente:
0 comments:
Publicar un comentario