Basic UI elements: Android Buttons (Basics) Marco Ronchetti Università degli Studi di Trento
Let s work with the listener Button button = ; button.setonclicklistener(new.onclicklistener() { public void onclick( v) { Log.d("TRACE", "Button has been clicked "); Anonymous ); Inner Class In Swing it was JButton button= button.addactionlistener (new ActionListener() { public void actionperformed(actionevent e) { 2 ); ;
Let s work with the listener Button button = ; button.setonclicklistener(new.onclicklistener() { public void onclick( v) { Log.d("TRACE", "Button has been clicked "); ); The event target Is passed MAIN DIFFERENCE 3 In Swing it was JButton button= button.addactionlistener (new ActionListener() { public void actionperformed(actionevent e) { ; ); The event is passed
An alternative The various classes expose several public callback methods that are useful for UI events. These methods are called by the Android framework when the respective action occurs on that object. For instance, when a (such as a Button) is touched, the ontouchevent() method is called on that object. However, in order to intercept this, you must extend the class and override the method. 4
Extending Button to deal with events Class MyButton extends Button { public boolean ontouchevent(motionevent event) { int eventaction = event.getaction(); switch (eventaction) { case MotionEvent.ACTION_DOWN: // finger touches the screen ; break; case MotionEvent.ACTION_MOVE: // finger moves on the screen ; break; 5 case MotionEvent.ACTION_UP: // finger leaves the screen ; break; // tell the system that we handled the event and no further processing is needed return true;
6 SimpleClick
Let s recap how to build an app 1) Define the Activity Resources 1) Choose a Layout 2) Add the components via XML 3) Define the strings 2) Code the activity 3) Add info to the Manifest (if needed) 7
UML Diagram Activity Layout Text Button 2 Text settitle() String String String 8
9 Let s define the aspect of layout1 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Text android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button1_label" /> <Text android:id="@+id/tf1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/output" /> </LinearLayout>
Let s define the strings <?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">this is Activity A1</string> <string name="app_name">simpleclick</string> <string name="button1_label">click me!</string> <string name="output">no results yet...</string> </resources> 10
SimpleClick A1 package it.unitn.science.latemar; import android.app.activity; import android.os.bundle; import android.view.; import android.widget.button; import android.widget.text; public class A1 extends Activity { int nclicks=0; protected void oncreate(bundle b) { super.oncreate(b); setcontent(r.layout.layout1); final Button button = (Button) findbyid(r.id.button1); final Text tf = (Text) findbyid(r.id.tf1); 11 button.setonclicklistener(new.onclicklistener() { public void onclick( v) { tf.settext("clicks :"+(++nclicks)); );
Calling Activities: Explicit Intents Marco Ronchetti Università degli Studi di Trento
startactivity(intent x) startactivity(intent x) (method of class Activity) starts a new activity, which will be placed at the top of the activity stack. takes a single argument which describes the activity to be executed. 13 An intent is an abstract description of an operation to be performed.
14 A simple example: A1 calls A2
Explicit Intents We will use the basic mode: Explicit starting an activity Explicit Intents specify the exact class to be run. Often these will not include any other information, simply being a way for an application to launch various internal activities it has as the user interacts with the application. 15
Intent The context of the sender The class to be activated new Intent(Context c, Class c); Remember that a Context is a wrapper for global information about an application environment, and that Activity subclasses Context 16 Equivalent form: Intent i=new Intent(); i.setclass(context c1, Class c2);
Let s define the aspect of layout1 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Text android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/activity1hellostring" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button1label" /> 17 </LinearLayout>
Let s define the strings <?xml version="1.0" encoding="utf-8"?> <resources> <string name="activity2hellostring">this is Activity TWO</string> <string name="app_name">buttonactivatedactions</string> <string name="activity1hellostring">this is Activity ONE</string> <string name="button1label">call Activity TWO</string> <string name="button2label">call Activity ONE</string> 18 </resources>
A1 and A2 package it.unitn.science.latemar; import android.app.activity; import android.content.intent; import android.os.bundle; import android.view.; import android.widget.button; public class A1 extends Activity { protected void oncreate(bundle icicle) { super.oncreate(icicle); package it.unitn.science.latemar; import android.app.activity; import android.content.intent; import android.os.bundle; import android.view.; import android.widget.button; public class A2 extends Activity { protected void oncreate(bundle icicle) { super.oncreate(icicle); setcontent(r.layout.layout1); final Button button = (Button) findbyid( R.id.button1); button.setonclicklistener( new.onclicklistener() { public void onclick( v) { Intent intent = new Intent(A1.this, A2.class); startactivity(intent); ); 19 Anonymous Inner Class setcontent(r.layout.layout2); final Button button = (Button) findbyid( R.id.button2); button.setonclicklistener( new.onclicklistener() { public void onclick( v) { Intent intent = new Intent(A2.this, A1.class); startactivity(intent); );
A1.this? What s that? button.setonclicklistener(new.onclicklistener() { public void onclick( v) { Intent intent = new Intent(A1.this, A2.class); startactivity(intent); ); final Activity me=this; button.setonclicklistener(new.onclicklistener() { ); public void onclick( v) { Intent intent = new Intent(me, A2.class); startactivity(intent); 20 final Intent intent = new Intent(this, A2.class); button.setonclicklistener(new.onclicklistener() { ); public void onclick( v) { startactivity(intent);
Let s declare A2 in the manifest <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="it.unitn.science.latemar" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="13" /> 21 <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name="a1" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> <activity android:name="a2"></activity> </application> </manifest>
How many instances? Marco Ronchetti Università degli Studi di Trento
How many instances? BACK BACK BACK BACK 23
public class A1 extends Activity { static int instances = 0; Text tf = null; protected void oncreate(bundle icicle) { super.oncreate(icicle); instances++; setcontent(r.layout.layout1); tf = (Text) findbyid(r.id.instancecount); final Button button = (Button) findbyid(r.id.button1); final Intent intent = new Intent(this, A2.class); button.setonclicklistener(new.onclicklistener() { public void onclick( v) { 24 startactivity(intent); ); The code protected void ondestroy() { super.ondestroy(); instances--; protected void onresume() { super.onresume(); if (tf!= null) tf.settext("instance count: A1 = " + A1.instances+" - count A2 = " + A2.instances);
Activity lifecycle States (colored), and Callbacks (gray) 25
The xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Text android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/activity1hellostring" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button1label" /> <Text android:id="@+id/instancecount" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/instancecount" /> 26 </LinearLayout> <?xml version="1.0" encoding="utf-8"?> <resources> <string name="activity2hellostring"> This is Activity TWO</string> <string name="app_name"> ButtonActivatedActions</string> <string name="activity1hellostring"> This is Activity ONE</string> <string name="button1label"> Call Activity TWO</string> <string name="button2label"> Call Activity ONE</string> <string name="instancecount"> Instance count: field not initialized</string> <string name="instancecount2"> Instance count: field not initialized</string> </resources>
Minimizing instances protected void oncreate(bundle icicle) { super.oncreate(icicle); instances++; setcontent(r.layout.layout2); tf2 = (Text) findbyid(r.id.instancecount2); final Button button = (Button) findbyid(r.id.button2); final Intent intent = new Intent(this, A1.class); intent.setflags(intent.flag_activity_clear_top); button.setonclicklistener(new.onclicklistener() { ); public void onclick( v) { startactivity(intent); 27 BACK
FLAG_ACTIVITY_CLEAR_TOP senza FLAG_ACTIVITY_CLEAR_TOP A B C D B con FLAG_ACTIVITY_CLEAR_TOP (C e D vengono distrutte) 28
For details see http://developer.android.com/reference/android/content/intent.html#flag_activity_brought_to_front FLAGS 29
Calling Activities with return values: startactivityforresults Marco Ronchetti Università degli Studi di Trento
31 Returning data
Calling activity package it.unitn.science.latemar; import public class CallingActivity extends Activity { int requestcode=100; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontent(r.layout.layout1); final Intent i = new Intent(this,CalledActivity.class); final Button button = (Button) findbyid(r.id.invokebutton); button.setonclicklistener(new.onclicklistener() { public void onclick( v) { startactivityforresult(i, requestcode); ); 32 protected void onactivityresult(int requestcode, int resultcode, Intent data) { super.onactivityresult(requestcode, resultcode, data); final Text tf = (Text) findbyid(r.id.output); if (resultcode==1){ tf.settext(data.getstringextra("payload")); else{ tf.settext("action cancelled"); The name should be qualified with the package
33 Called activity public class CalledActivity extends Activity { public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontent(r.layout.layout2); final Intent in = new Intent(); final Button button = (Button) findbyid(r.id.okbutton); final EditText tf = (EditText) findbyid(r.id.edittext1); button.setonclicklistener(new.onclicklistener() { public void onclick( v) { setresult(1,in); in.putextra("payload", tf.gettext().tostring()); finish(); ); final Button button_c = (Button) findbyid(r.id.cancelbutton); button_c.setonclicklistener(new.onclicklistener() { public void onclick( v) { setresult(0,in); finish(); ); package it.unitn.science.latemar; import The name should be qualified with the package
Remember to register the Activity! 34 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="it.unitn.science.latemar" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="13" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".callingactivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> <activity android:name="calledactivity"></activity> </application> </manifest>
Extras setextra(string name, #TYPE# payload) where #TYPE# = one of Primitive data types String or various types of serializable objects get Extra(String name) where is the name of the data types available in getters removeextra(string name) 35 replaceextra completely replace the Extras
Basic UI elements: s and Layouts, a deeper insight Marco Ronchetti Università degli Studi di Trento
Widgets examples 37 See http://developer.android.com/resources/tutorials/views/index.html
38 Layout examples
Defining layouts in XML Each layout file must contain exactly one root element, which must be a or Group object. Once you've defined the root element, you can add additional layout objects or widgets as child elements to gradually build a hierarchy that defines your layout. 39
A view of the s Group Absolute Layout Stub Analog Clock Frame Layout Surface Keyboard Grid Layout Texture Space Linear Layout Progress Bar Image Relative Layout Text Digital Clock Edit Text Button 40 Scroll Calendar And several more TimePicker Toggle Button Media Controller Switch Radio Button Compound Button Check Box
invisible, zero-sized that can be used to lazily inflate layout resources at A view of the s surface runtime. Group Absolute Layout Stub Analog Clock analogic clock with two hands for hours and minutes Frame Layout a dedicated drawing Surface Keyboard Grid Layout a keyboard used to display a content stream Texture Space used to create gaps Linear between components Layout a progress bar Progress Bar Image Displays an Relative arbitrary image, such Layout as an icon. Text Displays text to the user and optionally allows them to edit it. Digital Clock Edit Text Button 41 Scroll Calendar And several more TimePicker Toggle Button Media Controller Switch Radio Button Compound Button Check Box
42 A view of the s PLEASE READ THIS: http://developer.android.com/reference/android/widget/package-summary.html Group Absolute Layout Scroll Stub Analog Clock Frame Layout Calendar two-state toggle switch widget that can select between two options. And several more Displays checked/ unchecked states as a button Surface Keyboard Grid Layout TimePicker Toggle Button Texture Space Linear Layout Media Controller Switch Progress Bar Image An editable Text Relative a pushbutton Layout A button with two states Radio Button Text Like AnalogClock, but digital. Digital Clock Edit Text Button Compound Button Check Box
Android vs. Swing architectures Group Layout Layout Component Container 43
A view of the s block out an area on the screen Group to display a single item Absolute Layout A layout that lets you specify exact Scroll locations (x/y coordinates) of its children 44 DEPRECATED! Stub Analog Clock Frame Layout Calendar And several more Surface Keyboard Grid Layout places its children in a rectangular grid. TimePicker Toggle Button Texture Linear Layout Media Controller Switch Progress Bar arranges its children in a single column or Space a single row. Image Relative Layout Radio Button Text the positions of the children can be described in relation to each other or to the parent.. Digital Clock Edit Text Button Compound Button Check Box
A view of the s Group container for a view Absolute hierarchy that Layout can be scrolled Stub calendar widget for displaying and selecting dates Analog Clock Frame Layout Surface Keyboard A view for selecting the time of day, Grid Layout Texture Space A view containing controls for a MediaPlayer Linear Layout Progress Bar Image Relative Layout Text Digital Clock Edit Text Button 45 Scroll Calendar And several more TimePicker Toggle Button Media Controller Switch Radio Button Compound Button Check Box
Layout examples See several examples in http://luca-petrosino.blogspot.com/2011/03/android-view-e-layout.html We quickly discuss some of them here. 46
Layout properties - horizontal <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:text="invia" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content /> <Button android:text="cancella" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> 47
Layout properties - margin 48 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:text="invia" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content android:layout_marginleft="25px" android:layout_marginright="25px"/> <Button android:text="cancella" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
Layout properties fill_parent <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation= horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:text="invia" android:id="@+id/button1" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <Button android:text="cancella" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> 49
Layout properties weight 50 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation= horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:text="invia" android:id="@+id/button1" android:layout_width="fill_parent" android:layout_height="wrap_content android:layout_weight="1"/> <Button android:text="cancella" android:id="@+id/button2" android:layout_width="fill_parent" android:layout_height="wrap_content android:layout_weight= 2"/> </LinearLayout>
Layout properties - vertical <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:text="invia" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <Button android:text="cancella" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> 51
Basic operations on Set properties: e.g. setting the text of a Text (settext()). Available properties, getters and setters vary among the different subclasses of views. Properties can also be set in the XML layout files. Set focus: Focus is moved in response to user input. To force focus to a specific view, call requestfocus(). Set up listeners: e.g. setonfocuschangelistener (android.view..onfocuschangelistener). subclasses offer specialized listeners. 52 Set visibility: You can hide or show views using setvisibility(int). (One of VISIBLE, INVISIBLE, or GONE.) Invisible, but it still takes up space for layout purposes Invisible, and it takes no space for layout purposes
Size and location of a Although there are setters for posizition and size, theyr values are usually controlled (and overwritten) by the Layout. getleft(), gettop() : get the coordinates of the upper left vertex. getmeasuredheight() e getmeasuredwidth() return the preferred dimensions 53 getwidth() e getheight() return the actual dimensions.
Custom views To implement a custom view, you will usually begin overriding for some of the standard methods that the framework calls on all views (at least ondraw()). For more details, see http://developer.android.com/reference/android/ view/.html 54