Professional Documents
Culture Documents
Applications
Ren-Shio Liu
Dept. of Industrial and Information Management
National Cheng Kung University
Overview
All user interface elements in an Android app are built using View
and ViewGroup objects
A View is an object that draws something on the screen that the
user can interact with
A ViewGroup is an invisible container that holds other View (and
ViewGroup) objects in order to define the layout of the interface
Layouts
User Interface Layout
To declare your layout, you can
instantiate View objects in code and start building a tree
but the easiest and most effective way to define your layout is with an XML file
The name of an XML element for a view is respective to the Android
class it represents
So a <TextView> element creates a TextView widget in your UI, and a
<LinearLayout> element creates a LinearLayout view group
User Interface Layout (cont.)
The advantage to declaring your UI in XML is that it enables you to
better separate the presentation of your application from the code
that controls its behavior
Your UI descriptions are external to your application code, which
means that you can modify or adapt it without having to modify
your source code and recompile.
For example, you can create XML layouts for different screen
orientations, different device screen sizes, and different languages.
Additionally, declaring the layout in XML makes it easier to visualize
the structure of your UI, so it's easier to debug problems
Working with XML
Using Android's XML vocabulary, you can quickly design UI layouts and
the screen elements they contain, in the same way you create web
pages in HTML with a series of nested elements.
Each layout file must contain exactly one root element, which must be a
View or ViewGroup object.
Once you've defined the root element, you can add additional layout
objects or widgets as child elements to gradually build a View hierarchy
that defines your layout.
Root element
<ViewGroup>
A container for other View elements.
There are many different kinds of ViewGroup objects and each one lets
you specify the layout of the child elements in different ways.
Different kinds of ViewGroup objects include LinearLayout,
RelativeLayout, and FrameLayout, etc.
Attributes
android:id A unique resource name for the element, which you can use to
obtain a reference to the ViewGroup from your application.
android:layout_height Required. The height for the group, as a dimension
value (or dimension resource) or a keyword (match_parent" or "wrap_content")
android:layout_width Required. The width for the element, as a dimension
value (or dimension resource) or a keyword (match_parent" or "wrap_content")
Common Layouts
Each subclass of the ViewGroup class provides a unique way to display
the views you nest within it
Some of the more common layout types that are built into the Android
platform:
Can be either
vertical or
horizontal
<View>
An individual UI component, generally referred to as a "widget".
Different kinds of View objects include TextView, Button, and CheckBox.
Attributes
android:id A unique resource name for the element, which you can use to
obtain a reference to the ViewGroup from your application.
android:layout_height Required. The height for the group, as a dimension
value (or dimension resource) or a keyword (match_parent" or "wrap_content")
android:layout_width Required. The width for the element, as a dimension
value (or dimension resource) or a keyword (match_parent" or "wrap_content")
<?xml version="1.0" encoding="utf-8"?>
Linear Layout
<LinearLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="Name"
android:ems="10"
android:layout_weight="1"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:id="@+id/editText" />
</LinearLayout>
Relative Layout
A relative layout is used for screen designs that require control elements
to be positioned in relation to one another
Relavtive Layout attributes
android:layout_above Positions the bottom edge of this view above the given anchor view ID.
android:layout_below Positions the top edge of this view below the given anchor view ID.
android:layout_alignBottom Makes the bottom edge of this view match the bottom edge of the given anchor
view ID.
android:layout_alignLeft Makes the left edge of this view match the left edge of the given anchor view ID.
android:layout_alignStart Makes the start edge of this view match the start edge of the given anchor view ID.
android:layout_alignParentTop If true, makes the top edge of this view match the top edge of the parent.
android:layout_alignParentLeft If true, makes the left edge of this view match the left edge of the parent.
SDK8 padding
<?xml version="1.0" encoding="utf-8"?> match_pfill_p
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" Note: fill_parent is deprecated.
android:paddingLeft="16dp" Use match_parent for SDK 8+
android:paddingRight="16dp" > and higher
<EditText
android:id="@+id/name" density p:
android:layout_width="fill_parent" view,
android:layout_height="wrap_content"
android:hint="Reminder" />
sp:
<Button
android:id="@+id/cancel"
android:layout_width="96dp" px:
android:layout_height="wrap_content"
android:layout_below="@id/name"
android:layout_alignParentRight="true"
android:text="Cancel" />
<Button
android:id="@+id/ok" ("Cancel")
android:layout_width="96dp"
android:layout_height="wrap_content"
android:layout_below="@id/name"
android:layout_toLeftOf="@id/cancel"
android:text="OK" />
</RelativeLayout>
FrameLayout
FrameLayout is designed to block out an area on the screen to display a
single item
Generally, FrameLayout should be used to hold a single child view,
because it can be difficult to organize child views in a way that's scalable
to different screen sizes without the children overlapping each other
Child views are drawn in a stack, with the most recently added child on
top
The size of the FrameLayout, if not specified, is the smallest rectangle
area that encompasses all the child views (plus padding)
<FrameLayout
xmlns:android="http://schemas.android.com/apk/r
es/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:src="@mipmap/ic_launcher" Size of the
android:scaleType="fitCenter" FrameLayout
android:layout_gravity="center"
android:layout_height="350px"
android:layout_width="350px"/>
<TextView
android:text="Frame Demo"
android:textSize="60px"
android:textStyle="bold"
android:textColor="@color/colorAccent"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:gravity="center"/>
</FrameLayout>
GridLayout
A layout that places its children in a rectangular grid
Children occupy one or more contiguous cells, as defined by their
rowSpec and columnSpec layout parameters
Each rowSpec/columnSpec defines the set of rows or columns that are
to be occupied; and how children should be aligned within the resulting
group of cells
If a child does not specify the row and column indices of the cell it
wishes to occupy, GridLayout assigns cell locations automatically using
its: orientation, rowCount and columnCount properties
Space between children may be specified either by using instances of the
dedicated Space view or by setting the leftMargin, topMargin,
rightMargin and bottomMargin layout parameters
GridLayout (cont.)
When the useDefaultMargins property is set, default margins around
children are automatically allocated based on the prevailing UI style
guide for the platform
As of API 21, GridLayout's distribution of excess space accommodates
the principle of weight
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:rowCount="6"
android:columnCount="4"
android:layout_margin="4dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView"
android:text="@string/zero"
android:textSize="70sp"
android:backgroundTint="@color/orange_cream"
android:layout_columnSpan="4"
android:layout_gravity="fill_horizontal"
android:gravity="end"/>
<Button
android:id="@+id/buttonPercent"
android:layout_gravity="fill_horizontal"
android:text="@string/percent"
android:minHeight="70dp"/>
<Button
android:id="@+id/buttonDivide"
android:text="@string/div"
android:minHeight="70dp"/>
A Side Note on DP and SP
dp
Density-independent Pixels - an abstract unit that is based on the physical
density of the screen
These units are relative to a 160 dpi screen, so one dp is one pixel on a 160 dpi
screen
The ratio of dp-to-pixel will change with the screen density, but not necessarily
in direct proportion.
Note: The compiler accepts both "dip" and "dp", though "dp" is more consistent
with "sp"
A Side Note on DP and SP (cont.)
sp
Scale-independent Pixels - this is like the dp unit, but it is also scaled by the
user's font size preference.
It is recommended you use this unit when specifying font sizes, so they will be
adjusted for both the screen density and user's preference.
Load the XML Resource
When you compile your application, each XML layout file is compiled
into a View resource.
You should load the layout resource from your application code, in your
Activity.onCreate() callback implementation.
Do so by calling setContentView(), passing it the reference to your
layout resource in the form of: R.layout.<layout_file_name> :
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
...
Attributes
Every View and ViewGroup object supports their own variety of XML
attributes. Some attributes are specific to a View object (for example,
TextView supports the textSize attribute), but these attributes are also
inherited by any View objects that may extend this class.
Some are common to all View objects, because they are inherited from
the root View class (e.g. the id attribute).
And, other attributes are considered "layout parameters, which are
attributes that describe certain layout orientations of the View object, as
defined by that object's parent ViewGroup object.
The ID Attribute
Any View object may have an integer ID associated with it, to uniquely
identify the View within the view hierarchy
When the application is compiled, this ID is referenced as an integer,
but the ID is typically assigned in the layout XML file as a string, in the
id attribute.
This is an XML attribute common to all View objects (defined by the
View class) and you will use it very often.
The syntax for an ID, inside an XML tag is:
android:id=@+id/my_button
The at-symbol (@) at the beginning of the string indicates that the
XML parser should parse and expand the rest of the ID string and
identify it as an ID resource.
The plus-symbol (+) means that this is a new resource name that
must be created and added to our resources (in the R.id file).
<Button
android:id="@+id/button1"
android:text="@string/button1"
android:onClick="onButton1Clicked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
Layout Parameters
Layout Parameters are used by views to tell their parents how they
want to be laid out
For example, you may specify the size of a view as follows:
<Button
android:id="@+id/button1" wrap_content tells your view to size itself to the
android:text="@string/button1" dimensions required by its content.
android:onClick="onButton1Clicked"
match_parent tells your view to become as big as
android:layout_width="wrap_content"
android:layout_height="wrap_content" its parent view group will allow
/> Alternatively, you can also specify size using
density-independent pixel units (dp)
There are also position related attributes (e.g.,
For more details, see this link left and top), but hard coding position should be
avoided
Connecting the XML with the code
In order to create views and reference them from the application, a
common pattern is to:
1. Define a view/widget in the layout file and assign it a unique ID:
<Button
android:id="@+id/button1"
android:text="@string/button1"
android:onClick="onButton1Clicked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
2. Then create an instance of the view object and capture it from the layout
(typically in the onCreate() method):
<EditText
android:id="@+id/phone"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="@string/phone_hint"
android:inputType="phone" />
<EditText
android:id="@+id/password"
android:hint="@string/password_hint"
android:inputType="textPassword"
... />
Texfields Enable Spelling Suggestions
In addition, if your text field is intended for basic text input, you should
enable auto spelling correction with the "textAutoCorrect" value
<EditText
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType=
"textCapSentences|textAutoCorrect"
... />
Textfields Specify the Input Method Action
Most soft input methods provide a user action button in the bottom
corner
By default, the system uses this button for either a Next or Done action
However, you can specify additional actions that might be more
appropriate for your text field, such as Send or Go
<EditText
android:id="@+id/search"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="@string/search_hint"
android:inputType="text"
Click here for the complete list of
android:imeOptions="actionSend" />
android:imeOptions
The Observer Pattern
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText textEdit = (EditText) findViewById(R.id.editText);
textEdit.addTextChangedListener(this);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
... // The text is uneditable
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
... // The text is uneditable
}
@Override
public void afterTextChanged(Editable s) {
... // The text is editable
}
}
Textfields Other Events
You can build other flexibility into EditText control in similar
ways:
OnFocusChangeListener: identify when the focus status of EditText
changes
Checkboxes
Checkboxes allow the user to select one or more options from a set
Typically, you should present each checkbox option in a vertical list.
Checkboxes (cont.)
<?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">
<CheckBox android:id="@+id/checkbox_meat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/meat"
android:onClick="onCheckboxClicked"/>
<CheckBox android:id="@+id/checkbox_cheese"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cheese"
android:onClick="onCheckboxClicked"/>
</LinearLayout>
Checkboxes (cont.)
public void onCheckboxClicked(View view) {
// Is the view now checked?
boolean checked = ((CheckBox) view).isChecked();
<TextView
android:id="@+id/textView"
android:text="@string/zero"
android:textSize="70dip"
android:backgroundTint="@color/orange_cream"
android:layout_columnSpan="4"
android:layout_gravity="fill_horizontal"
android:gravity="start"/>
<Button
android:id="@+id/buttonAC" <Button
android:layout_columnSpan="2" android:id="@+id/buttonMinus"
android:layout_gravity="fill_horizontal" android:text="@string/minus"
android:backgroundTint="@color/dusk_blue" android:minHeight="70dip"/>
android:text="@string/ac"
android:minHeight="70dip" <Button
android:onClick="onButtonClick"/> android:id="@+id/buttonPlus"
android:text="@string/plus"
<Button android:minHeight="70dip"/>
android:id="@+id/buttonPercent"
android:layout_gravity="fill_horizontal" <Button
android:text="@string/percent" android:id="@+id/button5"
android:minHeight="70dip"/> android:text="@string/five"
android:minHeight="70dip"/>
<Button
android:id="@+id/buttonDivide" <Button
android:text="@string/div" android:id="@+id/button6"
android:minHeight="70dip"/> android:layout_width="wrap_content"
android:layout_height="wrap_content"
<Button android:text="@string/six"
android:id="@+id/buttonMultiply" android:minHeight="70dip"/>
android:text="@string/multiply"
android:minHeight="70dip"/>
<Button
<Button
android:id="@+id/button7"
android:id="@+id/button1"
android:text="@string/seven"
android:text="@string/one"
android:minHeight="70dip"/>
android:minHeight="70dip"/>
<Button
<Button
android:id="@+id/button8"
android:id="@+id/button2"
android:text="@string/eight"
android:text="@string/two"
android:minHeight="70dip"/>
android:minHeight="70dip"/>
<Button
<Button
android:id="@+id/button9"
android:id="@+id/button3"
android:text="@string/nine"
android:text="@string/three"
android:minHeight="70dip"/>
android:minHeight="70dip"/>
<Button
<Button
android:id="@+id/button0"
android:id="@+id/button4"
android:layout_columnSpan="1"
android:text="@string/four"
android:text="@string/zero"
android:minHeight="70dip"/>
android:minHeight="70dip"/>
<Button
android:id="@+id/buttonPoint"
android:text="@string/point"
android:minHeight="70dip"/>
<Button
android:id="@+id/buttonEqual"
android:layout_columnSpan="2"
android:layout_gravity="fill_horizontal"
android:backgroundTint="@color/dusk_blue"
android:text="@string/equal"
android:minHeight="70dip"/>
</GridLayout>
The landscape orientation has
an extra . button
How can we deal with the
button? More specifically, how
can we tell if we are in portrait
or landscape layout?
Determine the Current Layout
Since your implementation of each layout will be a little different, one of
the first things you will probably have to do is determine what layout the
user is currently viewing
For example, you might want to know whether the user is in "single
pane" mode or "dual pane" mode. You can do that by querying if a given
view exists and is visible:
(adap-
tive design)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal" />
</LinearLayout>
Basic ListActivity (cont.)
Modify your activity class so that it extends ListActivity
Now, to display a list of names, do
public class BasicListActivity extends ListActivity {
private ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_basic_list);
setListAdapter(adapter);
}
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Parameters
l ListView: The ListView where the click happened
v View: The view that was clicked within the ListView
position int: The position of the view in the list
id long: The row id of the item that was clicked
Exercise
Modify the iTuneListener App we did last week so that is uses a
ListAcitivty to display the top 20 songs on iTune
No need to turn in, but youll need this for the next demo!
Solution
Make iTuneListener extend ListActivity and add the following variables to
iTuneListener class
LinearLayout layout;
ArrayList<String> titles;
ArrayAdapter<String> adapter;
//setContentView(R.layout.activity_i_tune_listener);
titles = new ArrayList<String>();
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, titles);
setListAdapter(adapter);
try {
URL url = new URL("http://ax.phobos.apple.com.edgesuite.net/WebObjects/" +
"MZStore.woa/wpa/MRSS/topsongs/limit=20/rss.xml");
new iTuneSAX(url, new ParserListener() {
@Override
public void setTitle(final String s) {
runOnUiThread(new Runnable() {
@Override
public void run() {
titles.add(s);
adapter.notifyDataSetChanged();
}
});
}
});
} catch (Exception e) {
e.printStackTrace();
Update onCreate() of iTuneListener
} as shown above
}
Demo: iTuneListener with Album
Cover Thumbnails
Demo: iTuneListener with Cover Thumbnail
Need to get URLs of the thumbnails first!
Modify iTuneSAX class as follows
Define a new boolean member variable imageFound
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
super.startElement(uri, localName, qName, attributes);
if (localName.equals("item")) {
itemFound = true;
}
if (itemFound && localName.equals("coverArt") && Note: Size of cover art can be 53, 60 or
attributes.getValue("height").equals(100")) { 100
imageFound = true;
}
element = "";
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if (itemFound && localName.equals("title")) {
delegate.setTitle(element);
} else if (imageFound && localName.equals("coverArt")) {
Log.i("URL", element);
imageFoud = false;
}
}
Demo: iTuneListener with Cover Thumbnail (cont.)
Now, for each URL, we need to create a thread to download its
corresponding image Better use ExecutorService!
However, before that, lets add another array in iTuneListener class to
hold the images
public class iTuneListener extends ListActivity {
LinearLayout layout;
iTuneListener listener = this;
ArrayList<String> titles;
ArrayList<Bitmap> covers;
ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@Override
public void setCover(final Bitmap b) {
runOnUiThread(new Runnable() {
@Override
public void run() { Note: You can click Code > Override Methods
covers.add(b); > setCover to add the method
adapter.notifyDataSetChanged();
}
});
}
});
Demo: iTuneListener with Cover Thumbnail (cont.)
OK, we are ready to download the album cover thumbnails
As each thumbnail has a different URL, we need to define a
runnable that connect to a distinct url and perform the
download
Right click on your package and create a new Java class called
iTuneRunnable that implements the Runnable interface
public class iTuneRunnable implements Runnable {
String mURL;
ParserListener mListener;
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
super.endElement(uri, localName, qName);
if (itemFound && localName.equals("title")) {
delegate.setTitle(element);
} else if (imageFoud && localName.equals("coverArt")) {
Log.i("URL", element);
service.execute(new iTuneRunnable(element, delegate));
imageFoud = false;
}
}
Demo: iTuneListener with Cover Thumbnail (cont.)
public iTuneListAdapter(
Context context, ArrayList<String> titles, ArrayList<Bitmap> covers) {
mContext = context;
mTitles = titles;
mCovers = covers;
}
Demo: iTuneListener with Cover Thumbnail (cont.)
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textView"
android:layout_weight="1"
android:paddingLeft="8dp"
/>
</LinearLayout>
Demo: iTuneListener with Cover Thumbnail (cont.)
Implement the getView, getItem, getItemId and getCount method in
the custom adapter
@Override
public int getCount() {
@Override
return mCovers.size();
public long getItemId(int i) {
} return i;
}
@Override
public Object getItem(int i) {
return mCovers.get(i);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater =
(LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.itune_list_item, null);
return itemView;
}
Demo: iTuneListener with Cover Thumbnail (cont.)
LinearLayout layout;
iTuneListener listener = this;
ArrayList<String> titles;
ArrayList<Bitmap> covers;
iTuneListAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Toast.makeText(this, titles.get(position), Toast.LENGTH_LONG).show();
}
Lab Assignment
Add another activity to iTuneListener and do the following:
When a song is selected from the list, start the new activity and play the preview
of the song.
The new activity need to display a larger album cover thumbnail and its title
Pause the music when your app is paused
Resume the music when it is resumed
Upload your code to moodle no later than 11/17
PS. See this example of streaming mp3 media file from URL using Android
MediaPlayer class
Swipe to Refresh
Define the swipe to refresh layout and list view to show the feed
response
Create a new layout file inside res/layout folder (right click > Layout
Resource File), name it as activity_swipe_refresh.xml and paste the
below code snippets
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</android.support.v4.widget.SwipeRefreshLayout>
How dose it work?
The ListView is placed as a child view to SwipeRefreshLayout
This allows user the ability to show the loading spinner when user swipes
the ListView edge.
All the functionality of displaying loading bar is encapsulated inside
SwipeRefreshLayout class
When user swipes down, the OnRefreshListener events gets fired. You
can handle this event to write the logic for downloading or refreshing
data
Note that, once data is downloaded, user has to manually call
setRefreshing(false) to hide the refresh spinner
Swipe to Refresh (cont.)
Add a listView variable in the iTuneListener class
LinearLayout layout;
iTuneListener listener = this;
ArrayList<String> titles;
ArrayList<Bitmap> covers;
iTuneListAdapter adapter;
ListView listView;
SwipeRefreshLayout mSwipeRefreshLayout;
downloadList();
}
Swipe to Refresh (cont.)
Before implementing the downloadList() method, add two new methods
to the ParserListener interface:
interface ParserListener {
void start();
void setTitle(final String s);
void setCover(final Bitmap b);
void finish();
}
protected void downloadList() {
//Refreshing data on server
try {
URL url = new URL("http://ax.phobos.apple.com.edgesuite.net/WebObjects/" +
"MZStore.woa/wpa/MRSS/topsongs/limit=20/rss.xml");
new iTuneSAX(url, new ParserListener() {
@Override
public void setTitle(final String s) {
titles.add(s);
// Only UI thread can update the UI
runOnUiThread(new Runnable() {
@Override
public void run() {
// Be sure to import TextView
adapter.notifyDataSetChanged();
}
});
}
@Override
public void setCover(Bitmap b) {
covers.add(b);
runOnUiThread(new Runnable() {
@Override
public void run() {
// Be sure to import TextView
adapter.notifyDataSetChanged();
}
});
}
@Override
public void start() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
}
});
}
@Override
public void finish() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(false);
}
});
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
Swipe to Refresh (cont.)
Override startDocument() and endDocument() methods in iTuneSAX
class:
@Override
public void startDocument() throws SAXException {
super.startDocument();
delegate.start();
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
delegate.finish();
}
Animation
Overview
The Android framework provides two animation systems: property
animation (introduced in Android 3.0) and view animation
Both animation systems are viable options, but the property animation
system is the preferred method to use, because it is more flexible and
offers more features
In addition to these two systems, you can utilize Drawable animation,
which allows you to load drawable resources and display them one frame
after another.
Drawable animation
Drawable animation involves displaying Drawable resources one after
another, like a roll of film. This method of animation is useful if you want to
animate things that are easier to represent with Drawable resources, such
as a progression of bitmaps
View Animation
View Animation is the older system and can only be used for Views. It is
relatively easy to setup and offers enough capabilities to meet many
application's needs.
Property Animation
Introduced in Android 3.0 (API level 11), the property animation system lets
you animate properties of any object, including ones that are not rendered
to the screen. The system is extensible and lets you animate properties of
custom types as well