Diferencia entre revisiones de «Button. ToggleButton. Control de eventos II»
Ir a la navegación
Ir a la búsqueda
Línea 87: | Línea 87: | ||
==Casos prácticos== | ==Casos prácticos== | ||
− | * | + | |
+ | * Partimos que xa temos creado o proxecto inicial como [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa indicamos anteriormente]. | ||
+ | : Se non o temos creado antes, crea un paquete de nome '''UI''' como un subpaquete do teu paquete principal. | ||
+ | : Dentro do paquete UI, crearemos un novo paquete de nome: '''Buttons'''. | ||
+ | |||
+ | |||
+ | <br /> | ||
+ | * Dentro do paquete '''Buttons''' crear unha nova 'Empty Activity' de nome: '''UD02_01_Buttons''' de tipo Launcher e sen compatibilidade. | ||
+ | : Modifica o arquivo '''AndroidManifiest.xml''' e engade unha label á activity como [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa vimos na creación do proxecto base]. | ||
+ | |||
+ | |||
*Imos crear 3 botóns: | *Imos crear 3 botóns: | ||
Línea 105: | Línea 115: | ||
− | + | <br /> | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | </ | ||
− | |||
− | |||
− | |||
===Creación do layout=== | ===Creación do layout=== | ||
*O layout XML ten 3 botóns e 1 TextView: | *O layout XML ten 3 botóns e 1 TextView: | ||
Línea 124: | Línea 121: | ||
<syntaxhighlight lang="xml" line highlight="7,23,24,32,34"> | <syntaxhighlight lang="xml" line highlight="7,23,24,32,34"> | ||
+ | <?xml version="1.0" encoding="utf-8"?> | ||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
xmlns:tools="http://schemas.android.com/tools" | xmlns:tools="http://schemas.android.com/tools" | ||
Línea 136: | Línea 134: | ||
<Button | <Button | ||
− | android:id="@+id/ | + | android:id="@+id/btnBoton_UD02_01_buttons" |
android:layout_width="150sp" | android:layout_width="150sp" | ||
android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||
Línea 143: | Línea 141: | ||
<ToggleButton | <ToggleButton | ||
− | android:id="@+id/ | + | android:id="@+id/tbtnDosEstados_UD02_01_buttons" |
android:layout_width="100dp" | android:layout_width="100dp" | ||
android:layout_height="match_parent" | android:layout_height="match_parent" | ||
Línea 151: | Línea 149: | ||
<ImageButton | <ImageButton | ||
− | android:id="@+id/ | + | android:id="@+id/ibtnImagen_UD02_01_buttons" |
android:layout_width="55sp" | android:layout_width="55sp" | ||
android:layout_height="50sp" | android:layout_height="50sp" | ||
android:scaleType="fitXY" | android:scaleType="fitXY" | ||
− | android:src="@drawable/ | + | android:src="@drawable/ic_launcher_foreground" > |
</ImageButton> | </ImageButton> | ||
</LinearLayout> | </LinearLayout> | ||
Línea 162: | Línea 160: | ||
android:layout_width="wrap_content" | android:layout_width="wrap_content" | ||
android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||
− | android:text="@string/ | + | android:text="@string/texto_tv_string" /> |
</LinearLayout> | </LinearLayout> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
*Se cargamos este layout e non realizamos ningunha codificación en Java, non vai pasar nada cos botóns: | *Se cargamos este layout e non realizamos ningunha codificación en Java, non vai pasar nada cos botóns: | ||
− | + | : Isto é debido a que non temos codificado ningunha acción para cando se preme en cada un deles. | |
− | |||
− | |||
− | |||
− | |||
− | |||
==Eventos== | ==Eventos== |
Revisión del 08:52 6 oct 2018
Sumario
Introdución
- Os botóns (button) permiten ao usuario indicar á aplicación que realice unha acción.
- Os botóns poden ter Texto, unha imaxe ou as dúas cousas:
- Ben o texto ou a imaxe comunican claramente ao usuario cal é a función do botón.
- Estes controles son subclases de:
- Button de TextView
- ToogleButton de CompoundButton
- ImageButton de ImageView (que se verá proximamente)
- Imaxe obtida de: http://www.itcsolutions.eu/2011/08/27/android-tutorial-4-procedural-vs-declarative-design-of-user-interfaces
- Observar como se definen os tres tipos de botóns anteriores:
- Botón con texto:
1 <Button
2 android:layout_width="wrap_content"
3 android:layout_height="wrap_content"
4 android:text="@string/button_text"
5 ... />
- Botón con imaxe
1 <ImageButton
2 android:layout_width="wrap_content"
3 android:layout_height="wrap_content"
4 android:src="@drawable/button_icon"
5 ... />
- Botón con texto e imaxe. A propiedade android:drawableLeft indica onde se sitúa a imaxe.
1 <Button
2 android:layout_width="wrap_content"
3 android:layout_height="wrap_content"
4 android:text="@string/button_text"
5 android:drawableLeft="@drawable/button_icon"
6 ... />
- Os botóns teñen unha propiedade android:onClick="oMeuMetodo" que nos permite chamar ao método indicado cando o pulsamos.
- Ese método hai que declaralo en Java como public void oMeuMetodo (View v) { ... }
- Recibe o obxecto View de quen o chamou.
- Os botóns (Button) son subclases de TextView.
- Referencias:
- O Control botón: http://developer.android.com/reference/android/widget/Button.html
- Introdución aos botóns: http://developer.android.com/design/building-blocks/buttons.html
- Para programadores: http://developer.android.com/guide/topics/ui/controls/button.html
- Para descargar iconas: http://www.iconarchive.com
- Para descargar imaxes: http://www.openclipart.org
Botóns de 2 estados: ToggleButton/Switch
- Existe outro tipo de botón de 2 estados (ON/OFF).
- Un máis básico: <ToggleButton>
- E outro máis avanzado (versión Android 4.0 ou superior): <Switch/>
- Permiten cambiar o seu estado desprazando co dun estado a outro. O funcionamento é semellante ao control ToogleButton.
- Un obxecto ToogleButton/Switch herda da clase CompoundButton, quen, á súa vez, herda da clase Button.
- Por tanto funcionan da mesma maneira, pero ademais o este tipo de botóns:
- ten 2 estados (True/False), que pode podemos comprobar co método isChecked ()
- Para cada estado podemos amosar un texto distinto no botón: android:TextOn e android:TextOFF.
- Referencias:
- O control ToggleButton: http://developer.android.com/reference/android/widget/ToggleButton.html
- O control switch: http://developer.android.com/reference/android/widget/Switch.html
- Introdución as botóns de 2 estados: http://developer.android.com/guide/topics/ui/controls/togglebutton.html
Casos prácticos
- Partimos que xa temos creado o proxecto inicial como xa indicamos anteriormente.
- Se non o temos creado antes, crea un paquete de nome UI como un subpaquete do teu paquete principal.
- Dentro do paquete UI, crearemos un novo paquete de nome: Buttons.
- Dentro do paquete Buttons crear unha nova 'Empty Activity' de nome: UD02_01_Buttons de tipo Launcher e sen compatibilidade.
- Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.
- Imos crear 3 botóns:
- 1 Botón con texto
- 1 ToogleButton
- 1 botón con imaxe
Creación do layout
- O layout XML ten 3 botóns e 1 TextView:
- Observar como hai un layout dentro doutro: un dispón os elementos en vertical e o outro en horizontal.
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:tools="http://schemas.android.com/tools"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 android:orientation="vertical" >
7
8 <LinearLayout
9 android:layout_width="match_parent"
10 android:layout_height="wrap_content"
11 android:orientation="horizontal" >
12
13 <Button
14 android:id="@+id/btnBoton_UD02_01_buttons"
15 android:layout_width="150sp"
16 android:layout_height="wrap_content"
17 android:text="Preme aquí" >
18 </Button>
19
20 <ToggleButton
21 android:id="@+id/tbtnDosEstados_UD02_01_buttons"
22 android:layout_width="100dp"
23 android:layout_height="match_parent"
24 android:textOff="Apagado"
25 android:textOn="Aceso" >
26 </ToggleButton>
27
28 <ImageButton
29 android:id="@+id/ibtnImagen_UD02_01_buttons"
30 android:layout_width="55sp"
31 android:layout_height="50sp"
32 android:scaleType="fitXY"
33 android:src="@drawable/ic_launcher_foreground" >
34 </ImageButton>
35 </LinearLayout>
36
37 <TextView
38 android:layout_width="wrap_content"
39 android:layout_height="wrap_content"
40 android:text="@string/texto_tv_string" />
41
42 </LinearLayout>
- Se cargamos este layout e non realizamos ningunha codificación en Java, non vai pasar nada cos botóns:
- Isto é debido a que non temos codificado ningunha acción para cando se preme en cada un deles.
Eventos
- Nesta ocasión imos ver dun xeito sinxelo como capturar os eventos dos botóns. Máis adiante afondaremos no control de eventos.
- Un evento é algo que acontece nun control e que nos interesa capturar no sistema para desencadenar (ou non) unha serie de accións.
- Xa vimos no caso anterior (EditText) que podíamos controlar eventos que acontecen nos controis.
- Nesta ocasión para os Botóns imos facelo de dúas formas:
- Control de eventos dende o layout
- Control de eventos a través dunha clase anónima.
Control de eventos dende o layout
- É a forma máis sinxela de desencadear unha acción.
- Imos facelo de dúas formas:
- Creando un método para cada Botón.
- Creando un único método para tódolos botóns. Hai que controlar que botón foi o que se premeu.
Crear un método para cada botón
- Observar a propiedade: android:onClick nos controis dos botóns.
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:orientation="vertical" >
6
7 <LinearLayout
8 android:layout_width="match_parent"
9 android:layout_height="wrap_content"
10 android:orientation="horizontal" >
11
12 <Button
13 android:id="@+id/btn_boton"
14 android:layout_width="150sp"
15 android:layout_height="wrap_content"
16 android:onClick="onBotonClick"
17 android:text="Preme aquí" >
18 </Button>
19
20 <ToggleButton
21 android:id="@+id/tbtn_boton_2estados"
22 android:layout_width="100dp"
23 android:layout_height="match_parent"
24 android:onClick="onBoton2EstadosClick"
25 android:textOff="Apagado"
26 android:textOn="Aceso" >
27 </ToggleButton>
28
29 <ImageButton
30 android:id="@+id/ibtn_boton_imaxe"
31 android:layout_width="55sp"
32 android:layout_height="50sp"
33 android:contentDescription="Botón imaxe"
34 android:onClick="onBotonImaxeClick"
35 android:scaleType="fitXY"
36 android:src="@drawable/ok" >
37 </ImageButton>
38 </LinearLayout>
39
40 <TextView
41 android:id="@+id/tv_accion"
42 android:layout_width="wrap_content"
43 android:layout_height="wrap_content"
44 android:text="@string/texto_tv" />
45
46 </LinearLayout>
- Para cada botón defínese un método que xestione o evento onClick.
- Deixamos para o participante no curso a definición no ficheiro /res/values/strings.xml da constante "@string/texto_tv" do último TextView.
- Agora só queda definir os métodos en Java.
1 package com.example.u2_09_buttons;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.view.Menu;
6 import android.view.View;
7 import android.widget.Button;
8 import android.widget.ImageButton;
9 import android.widget.TextView;
10 import android.widget.ToggleButton;
11
12 public class U2_09_Buttons extends Activity {
13 private Button btnBoton;
14 private ToggleButton tbtnBoton2Estados;
15 private ImageButton ibtnBotonImaxe;
16 private TextView tvAccions;
17
18 @Override
19 protected void onCreate(Bundle savedInstanceState) {
20 super.onCreate(savedInstanceState);
21 setContentView(R.layout.activity_u2_09__buttons);
22
23 btnBoton = (Button) findViewById(R.id.btn_boton);
24 tbtnBoton2Estados = (ToggleButton) findViewById(R.id.tbtn_boton_2estados);
25 ibtnBotonImaxe = (ImageButton) findViewById(R.id.ibtn_boton_imaxe);
26 tvAccions = (TextView) findViewById(R.id.tv_accion);
27 }
28
29 public void onBotonClick(View v) {
30 tvAccions.setText("Premeches o primeiro botón\n");
31 tvAccions.append("O texto do botón é: " + btnBoton.getText());
32 }
33
34 public void onBoton2EstadosClick(View v) {
35 tvAccions.setText("Premeches o segundo botón\n");
36 if (tbtnBoton2Estados.isChecked())
37 tvAccions.append("O estado é: " + tbtnBoton2Estados.getTextOn());
38 else
39 tvAccions.append("O estado é: " + tbtnBoton2Estados.getTextOff());
40 }
41
42 public void onBotonImaxeClick(View v) {
43 tvAccions.setText("Premeches o terceiro botón\n");
44 tvAccions.append("O ancho é: " + ibtnBotonImaxe.getWidth());
45 }
46
47 @Override
48 public boolean onCreateOptionsMenu(Menu menu) {
49 // Inflate the menu; this adds items to the action bar if it is present.
50 getMenuInflater().inflate(R.menu.u2_09__buttons, menu);
51 return true;
52 }
53
54 }
- Liñas 13-16: declaración de atributos.
- Liñas 23-26: asignación de valores aos atributos mediante a clase R.
- Liñas 29-32: Define o método asociado ao evento android:onClick do primeiro botón. "\n" introduce un salto de liña.
- Liñas 34-40: Define o método asociado ao evento android:onClick do botón ToggleButton. Comprobamos se está activado o non.
- Liñas 42-45: Define o método asociado ao evento android:onClick do botón con Imaxe.
- Lanzar a aplicación e comprobar que sucede ao premer os botóns.
Crear un único método para tódolos botóns
- Hai que modificar o XML para que as propiedades android:onClick de tódolos botóns chamen ao mesmo método.
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:orientation="vertical" >
6
7 <LinearLayout
8 android:layout_width="match_parent"
9 android:layout_height="wrap_content"
10 android:orientation="horizontal" >
11
12 <Button
13 android:id="@+id/btn_boton"
14 android:layout_width="150sp"
15 android:layout_height="wrap_content"
16 android:onClick="onBotonClick"
17 android:text="Preme aquí" >
18 </Button>
19
20 <ToggleButton
21 android:id="@+id/tbtn_boton_2estados"
22 android:layout_width="100dp"
23 android:layout_height="match_parent"
24 android:onClick="onBotonClick"
25 android:textOff="Apagado"
26 android:textOn="Aceso" >
27 </ToggleButton>
28
29 <ImageButton
30 android:id="@+id/ibtn_boton_imaxe"
31 android:layout_width="55sp"
32 android:layout_height="50sp"
33 android:contentDescription="Botón imaxe"
34 android:onClick="onBotonClick"
35 android:scaleType="fitXY"
36 android:src="@drawable/ok" >
37 </ImageButton>
38 </LinearLayout>
39
40 <TextView
41 android:id="@+id/tv_accion"
42 android:layout_width="wrap_content"
43 android:layout_height="wrap_content"
44 android:text="@string/texto_tv" />
45
46 </LinearLayout>
- A definición do método:
1 package com.example.u2_09_buttons;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.view.Menu;
6 import android.view.View;
7 import android.view.View.OnClickListener;
8 import android.widget.Button;
9 import android.widget.ImageButton;
10 import android.widget.TextView;
11 import android.widget.ToggleButton;
12
13 public class U2_09_Buttons extends Activity {
14 // private Button btnBoton;
15 // private ToggleButton tbtnBoton2Estados;
16 // private ImageButton ibtnBotonImaxe;
17 private TextView tvAccions;
18
19 @Override
20 protected void onCreate(Bundle savedInstanceState) {
21 super.onCreate(savedInstanceState);
22 setContentView(R.layout.activity_u2_09__buttons);
23
24 tvAccions = (TextView) findViewById(R.id.tv_accion);
25
26 }
27
28 public void onBotonClick(View vista) {
29
30 switch (vista.getId()) {
31 case R.id.btn_boton:
32 tvAccions.setText("Premeches o primeiro botón\n");
33 tvAccions.append("O texto do botón é: "
34 + ((Button) vista).getText());
35 break;
36
37 case R.id.tbtn_boton_2estados:
38 tvAccions.setText("Premeches o segundo botón\n");
39 if (((ToggleButton) vista).isChecked())
40 tvAccions.append("O estado é: "
41 + ((ToggleButton) vista).getTextOn());
42 else
43 tvAccions.append("O estado é: "
44 + ((ToggleButton) vista).getTextOff());
45 break;
46
47 case R.id.ibtn_boton_imaxe:
48 tvAccions.setText("Premeches o terceiro botón\n");
49 tvAccions.append("O ancho é: " + ((ImageButton) vista).getWidth());
50 }
51 }
52
53 /*public void onBotonClick(View v) {
54 tvAccions.setText("Premeches o primeiro botón\n");
55 tvAccions.append("O texto do botón é: " + btnBoton.getText());
56 }*/
57
58
59 /*
60 public void onBoton2EstadosClick(View v) {
61 tvAccions.setText("Premeches o segundo botón\n"); if
62 (tbtnBoton2Estados.isChecked()) tvAccions.append("O estado é: " +
63 tbtnBoton2Estados.getTextOn()); else tvAccions.append("O estado é: " +
64 tbtnBoton2Estados.getTextOff()); }
65 */
66
67
68 /*
69 public void onBotonImaxeClick(View v) {
70 tvAccions.setText("Premeches o terceiro botón\n");
71 tvAccions.append("O ancho é: " + ibtnBotonImaxe.getWidth()); }
72 */
73
74 @Override
75 public boolean onCreateOptionsMenu(Menu menu) {
76 // Inflate the menu; this adds items to the action bar if it is present.
77 getMenuInflater().inflate(R.menu.u2_09__buttons, menu);
78 return true;
79 }
80
81 }
- Liñas 28-51:
- Na chamada ao método recibimos como parámetro unha View (vista) que apunta ao obxecto que o chamou.
- Collendo o ID da vista, podemos saber que botón foi o que iniciou o evento.
- Con switch - case, en función do botón que lanzou o evento executamos o código correspondente.
- Liñas 39, 41 e 43:
- Observar como se fai casting do obxecto recibido. Recíbese un obxecto de tipo View (vista) e precisamos convertelo á ToogleButton para acceder aos seus métodos específicos.
Control de eventos usando un listener. Clase anónima
- Nesta ocasión imos crear un Listener para o primeiro botón. Co cal, hai que eliminar a propiedade android:onClick do XML do primeiro botón
- O ficheiro XML:
- Observar que no primeiro botón non se xestiona o evento onClick e que os outros dous botóns seguen mantendo a propiedade android:onClick.
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:orientation="vertical" >
6
7 <LinearLayout
8 android:layout_width="match_parent"
9 android:layout_height="wrap_content"
10 android:orientation="horizontal" >
11
12 <Button
13 android:id="@+id/btn_boton"
14 android:layout_width="150sp"
15 android:layout_height="wrap_content"
16 android:text="Preme aquí" >
17 </Button>
18
19 <ToggleButton
20 android:id="@+id/tbtn_boton_2estados"
21 android:layout_width="100dp"
22 android:layout_height="match_parent"
23 android:onClick="onBoton2EstadosClick"
24 android:textOff="Apagado"
25 android:textOn="Aceso" >
26 </ToggleButton>
27
28 <ImageButton
29 android:id="@+id/ibtn_boton_imaxe"
30 android:layout_width="55sp"
31 android:layout_height="50sp"
32 android:contentDescription="Botón imaxe"
33 android:onClick="onBotonImaxeClick"
34 android:scaleType="fitXY"
35 android:src="@drawable/ok" >
36 </ImageButton>
37 </LinearLayout>
38
39 <TextView
40 android:id="@+id/tv_accion"
41 android:layout_width="wrap_content"
42 android:layout_height="wrap_content"
43 android:text="@string/texto_tv" />
44
45 </LinearLayout>
- Imos partir do código da primeira versión da ampliación.
- Comentaremos aquel código que afectaba ao primeiro botón e usaremos un Listener asociado ao primeiro botón.
1 package com.example.u2_09_buttons;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.view.Menu;
6 import android.view.View;
7 import android.view.View.OnClickListener;
8 import android.widget.Button;
9 import android.widget.ImageButton;
10 import android.widget.TextView;
11 import android.widget.ToggleButton;
12
13 public class U2_09_Buttons extends Activity {
14 private Button btnBoton;
15 private ToggleButton tbtnBoton2Estados;
16 private ImageButton ibtnBotonImaxe;
17 private TextView tvAccions;
18
19 @Override
20 protected void onCreate(Bundle savedInstanceState) {
21 super.onCreate(savedInstanceState);
22 setContentView(R.layout.activity_u2_09__buttons);
23
24 btnBoton = (Button) findViewById(R.id.btn_boton);
25 tbtnBoton2Estados = (ToggleButton) findViewById(R.id.tbtn_boton_2estados);
26 ibtnBotonImaxe = (ImageButton) findViewById(R.id.ibtn_boton_imaxe);
27 tvAccions = (TextView) findViewById(R.id.tv_accion);
28
29 btnBoton.setOnClickListener(new OnClickListener() {
30
31 @Override
32 public void onClick(View v) {
33 // TODO Auto-generated method stub
34 tvAccions.setText("Premeches o primeiro botón\n");
35 tvAccions.append("O texto do botón é: " + btnBoton.getText());
36 }
37
38 });
39
40 }
41
42 /* public void onBotonClick(View v) {
43 tvAccions.setText("Premeches o primeiro botón\n");
44 tvAccions.append("O texto do botón é: " + btnBoton.getText());
45 }
46 */
47
48 public void onBoton2EstadosClick(View v) {
49 tvAccions.setText("Premeches o segundo botón\n");
50 if (tbtnBoton2Estados.isChecked())
51 tvAccions.append("O estado é: " + tbtnBoton2Estados.getTextOn());
52 else
53 tvAccions.append("O estado é: " + tbtnBoton2Estados.getTextOff());
54 }
55
56 public void onBotonImaxeClick(View v) {
57 tvAccions.setText("Premeches o terceiro botón\n");
58 tvAccions.append("O ancho é: " + ibtnBotonImaxe.getWidth());
59 }
60
61 @Override
62 public boolean onCreateOptionsMenu(Menu menu) {
63 // Inflate the menu; this adds items to the action bar if it is present.
64 getMenuInflater().inflate(R.menu.u2_09__buttons, menu);
65 return true;
66 }
67
68 }
- Liñas 29-38: chamamos ao método setOnClickListener() do primeiro botón que se activará cando se fai click no botón.
- Creamos unha clase anónima asociada a interface OnClickListener e sobreescribimos o único método que ten: onClick.
- Como xa se dixo no anterior control (EditText), para coñecer o método asociado ao botón escribimos obxecto.setOn, prememos CTRL+Barra espaciadora e xa nos auto completa.
- O mesmo facemos para a creación da clase anónima.
- Premer CTRL + Barra espaciadora
- Clase anónima co seu método.
- Quedan presentados os listeners máis adiante afondaremos sobre eles.
-- Ángel D. Fernández González e Carlos Carrión Álvarez -- (2015).