Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 53

Mobile Computing

Lecture #07
ListViews, RecyclerViews,
Adapters
Today’s Lecture
ListViews
ArrayAdapter
CustomAdapter
View and ViewGroup
View
1. View objects are the basic building blocks of User Interface(UI) elements in
Android.
2. View is a simple rectangle box which responds to the user's actions.
3. Examples are EditText, Button, CheckBox etc..
4. View refers to the android.view.View class, which is the base class of all UI
classes.

ViewGroup
5. ViewGroup is the invisible container. It holds View and ViewGroup
6. For example, LinearLayout is the ViewGroup that contains Button(View), and
other Layouts also.
7. ViewGroup is the base class for Layouts
View and ViewGroup
Layouts
 A layout defines the structure for a user interface in your app,
such as in an activity.
 All elements in the layout are built using a hierarchy of View and
ViewGroup objects.
 A View usually draws something the user can see and interact
with. Whereas a ViewGroup is an invisible container that defines
the layout structure for View and other ViewGroup objects.
Common Layouts
AdapterView and Adapter
AdapterView: An AdapterView is a group of widgets components in Android that include
the ListView, Spinner, GridView and Gallery.
AdapterView is a ViewGroup that display items loaded into an adapter.

Adapter: The Adapter is an interface, which bridge between an AdapterView and


underlying data for that view.

Adapter receive the data from source and send to an Adapter View
Building Layouts with an Adapter
List View
Grid View
ListViews & Adapters
A ListView is a view which groups several items and display them in
vertical scrollable list
The list items are inserted to the list using an Adapter
The Adapter pulls content from a source such as an array or database
The Adapter actually bridges between UI components and the data source
that fill data into UI Component
Adapter can be used to supply the data to like spinner, list view, grid view
etc.
Android provides several subclasses of Adapter that are useful for
retrieving different kinds of data and building views for an AdapterView
( ie. ListView or GridView)
Types of Adapter
Android provides several subclasses of Adapter that are useful for
retrieving different kinds of data and building views for an AdapterView
• BaseAdapter:
• ArrayAdapter:
• Custom ArrayAdapter
• SimpleAdapter
• CursorAdapter
ArrayAdapter
ArrayAdapter uses an array as data source
By default, ArrayAdapter creates a view for each array item by calling toString()
on each item and placing the contents in a TextView
ArrayAdapter can be created by providing layout definition of each string and
source of string data (such as array)
ArrayAdapter adapter = new ArrayAdapter<String>(this, R.layout.list_layout, data);
In above line:
1. “this” is the application context
2. “R.layout.list_layout” is xml based layout, its mean, arrayadapter use a TextView to display each item.
3. “data” is string array
ArrayAdapter …
Once ArrayAdapter has been instanciated, created ListView and set its adapter
as:
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);

R.id.listview could be
i) simple_list_item_1 or simple_list_item_2
ii) TextView id in a layout file
ArrayAdapter … Example
1. Define an Activity containing a ListView (MainActivity.java)
2. Create layout for Activity containing a ListView (activity_main.xml)
3. Create layout for the ListView items (list_item.xml)
4. Set layout definition of MainActivity.java
5. In MainActivity.java, define a String array (cities)
6. In MainActivity.java, instantiate an ArrayAdapter (adapter)
ArrayAdapter … Example … Activity Layout
1. Create layout for Activity containing a ListView (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"

xmlns:android="http://schemas.android.com/apk/res/android">

<ListView
android:id="@+id/cities_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:dividerHeight="2dp"
android:divider="@color/blue"/>

</LinearLayout>
ArrayAdapter … Example … List Item Layout
2. Create layout for the ListView items (list_item.xml)

<?xml version="1.0" encoding="utf-8"?>


<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/label"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="20dp"
android:textStyle="bold|italic" >
</TextView>
ArrayAdapter … Example … MainActivity.java
import android.widget.ListView;
import android.widget.TextView;
import android.view.View ;
import android.widget.ArrayAdapter;

public class MainActivity extends AppCompatActivty {


ListView list;
TextView textview;
String []cities = {"Lahore", "Faisalabad", "Peshawar", "Sialkot", "Islamabad", "Mardan", "Karachi"};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = (ListView) findViewById(R.id.cities_list);
textview = (TextView) findViewById(R.id.label);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item,, R.id.texview cities);
list.setAdapter(adapter);
}}
ArrayAdapter …
Example …
Output
Custom Adapter
You can also create custom adapter to display items as you want
ArrayAdapter … Example
1. Define an Activity containing a ListView (ContactsActivity.java)
2. Create layout for Activity containing a ListView (contacts_list.xml)
3. Create layout for the ListView items (contact_row.xml)
4. Set layout definition of ContactsActivity.java
5. In ContactsActivity.java, define a contactList
6. Populate contactList from your contact book
7. In ContactsActivity.java, instantiate an ContactAdapter (adapter)
8. Set the list adapter of already created list
Activity Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"

xmlns:android="http://schemas.android.com/apk/res/android">

<ListView
android:id="@+id/contacts_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:dividerHeight="2dp"
android:divider="@color/blue"/>

</LinearLayout>
List Item Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/contact_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:textSize="20dp"
android:textStyle="bold"
android:textColor="@color/blue"/>
<TextView
android:id="@+id/phone_number"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:textSize="16dp"
android:textColor="@color/colorAccent" />
</LinearLayout>
Model Class …. Contact.java
public class Contact {
private String contactName, phoneNumber;

public Contact(){
contactName = null;
phoneNumber = null;
}

public void setContactName(String name){


contactName = name;
}

public void setPhoneNumber(String phone){


phoneNumber = phone;
}

public String getContactName(){


return contactName;
}

public String getPhoneNumber(){


return phoneNumber;
}
}
ContactAdapter
public class ContactAdapter extends ArrayAdapter<Contact> {
private ArrayList<Contact> dataSet;
private Context mContext;

// View lookup cache


private static class ViewHolder {
TextView contactName;
TextView phoneNumber;
}

public ContactAdapter(ArrayList<Contact> data, Context context) {


super(context, R.layout.contacts_row, data);
this.dataSet = data;
this.mContext=context;
}


ContactAdapter …
public View getView(int position, View convertView, ViewGroup parent) {
Contact contact = getItem(position);
ViewHolder viewHolder; // view lookup cache stored in tag
final View result;
if (convertView == null) {

viewHolder = new ViewHolder();


LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.contacts_row, parent, false);
viewHolder.contactName = (TextView)convertView.findViewById(R.id.contact_name);
viewHolder.phoneNumber = (TextView)convertView.findViewById(R.id.phone_number);
result=convertView;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
result=convertView;
}
viewHolder.contactName.setText(contact.getContactName());
viewHolder.phoneNumber.setText(contact.getPhoneNumber());
// Return the completed view to render on screen
return convertView;
}
}
ContactsActivity.java …
public class ContactsActivity extends Activity {
private ListView list;
ArrayList<Contact> contactList;
private String []columns = {ContactsContract.Data.DISPLAY_NAME};
private int[] view_ids = {R.id.contact_name};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contacts_list);
contactList = getAllContacts();
ContactAdapter adapter = new ContactAdapter(contactList, getApplicationContext());
list = (ListView) findViewById(R.id.contacts_list);
list.setAdapter(adapter);
}
ContactsActivity.java …
private ArrayList getAllContacts() {
ArrayList<Contact> contacts = new ArrayList<Contact>();
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if ((cur != null ? cur.getCount() : 0) > 0) {
while (cur != null && cur.moveToNext()) {
String id = cur.getString (cur.getColumnIndex(ContactsContract.Contacts._ID);
String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
Contact contact = new Contact();
contact.setContactName(name);
if (cur.getInt(cur.getColumnIndex( ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{id}, null);
while (pCur.moveToNext()) {
String phoneNo =
pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contact.setPhoneNumber(phoneNo);
}
contacts.add(contact);
pCur.close();
}
}
}
if (cur != null) {cur.close();}
return contacts;
}
}
CustomAdapter …
Example …
Output
Recycler View
RecyclerView class is a modernized version of the ListView and the GridView
classes, that supports the display of a collection of data.
RecyclerView makes it easy to efficiently display large sets of data. As the name
implies, RecyclerView recycles those individual elements. When an item scrolls
off the screen.
For example, if a user scrolled down to a position where items 4 and 5 are
visible; items 1,2 and 3 would be cleared from the memory to reduce memory
consumption.
Recycler View

In Android 5.0 Lollipop, Android introduced RecyclerView widget.


RecyclerView is flexible and efficient version of ListView.
It is an container for rendering larger data set of views that can be recycled and
scrolled very efficiently. 
RecyclerView vs ListView
Required ViewHolder in Adapters - 
ListView adapters do not require the use of the ViewHolder pattern to
improve performance.
In contrast, implementing an adapter for RecyclerView requires the use of the
ViewHolder pattern for which it uses RecyclerView.Viewholder.
Customizable Item Layouts - 
ListView can only layout items in a vertical linear arrangement and this
cannot be customized.
In contrast, the RecyclerView has a RecyclerView.LayoutManager that allows
any item layouts including horizontal lists or staggered grids.
RecyclerView vs ListView
Easy Item Animations - 
ListView contains no special provisions through which one can animate the
addition or deletion of items.
In contrast, the RecyclerView has the RecyclerView.ItemAnimator class for
handling item animations.
Manual Data Source - 
ListView had adapters for different sources such as ArrayAdapter and
CursorAdapter for arrays and database results respectively.
In contrast, the RecyclerView.Adapter requires a custom implementation to
supply the data to the adapter.
RecyclerView vs ListView
Manual Item Decoration - 
ListView has the android:divider property for easy dividers between items in the
list.
In contrast, RecyclerView requires the use of a RecyclerView.ItemDecoration
object to setup much more manual divider decorations.
Manual Click Detection - 
ListView has a AdapterView.OnItemClickListener interface for binding to the click
events for individual items in the list.
In contrast, RecyclerView only has support for
RecyclerView.OnItemTouchListener which manages individual touch events but
has no built-in click handling.
Recycler View Component
LayoutManagers-
A layout manager positions item views inside a RecyclerView and determines
when to reuse item views that are no longer visible to the user.
(When an item scrolls off the screen, RecyclerView doesn't destroy its view.
Instead, RecyclerView reuses the view for new items that have scrolled
onscreen)
RecyclerView provides these built-in layout managers:
LinearLayoutManager shows items in a vertical or horizontal scrolling list.
GridLayoutManager shows items in a grid.
StaggeredGridLayoutManager shows items in a staggered grid.
Recycler View Component
RecyclerView.Adapter-
RecyclerView includes a new kind of adapter, which required ViewHolder

ItemAnimator-
RecyclerView.ItemAnimator will animate ViewGroup modifications such as
add/delete/select that are notified to the adapter.
RecyclerView
Like the ListView, uses an adapter

We normally use a CardView as the default


layout for each item in the list
Similar to a fragment
RecyclerView Implementation
To implement a basic RecyclerView three sub-parts are needed to be constructed
The Card Layout: The card layout is an XML layout, introduced in Android 7.0
which will be treated as an item for the list created by the RecyclerView. It can be
thought of as a FrameLayout with rounded corners and shadow based on its
elevation.
The ViewHolder: The ViewHolder is a java class that stores the reference to the
card layout views () that have to be dynamically modified during the execution of
the program by a list of data obtained either by online databases or added in
some other way.
The Data Class: The Data class is a custom java class that acts as a structure for
holding the information for every item of the RecyclerView.
Including
You need to include the them in the dependencies (build.gradle
module)
 Implementation 'androidx.recyclerview:recyclerview:1.0.0'
 Implementation 'androidx.cardview:cardview:1.0.0'
RecyclerView
Add the following to your layout
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list“
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
In you activity/fragment use the following code, (very similar to a listview)
mRecyclerView = (RecyclerView)findViewById(R.id.list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
setup the adapter, which is myAdapter, see the next slide for code.
 There is no simple adapter version, you need to extend it.
mAdapter = new myAdapter(values, R.layout.my_row, this);
mRecyclerView.setAdapter(mAdapter);
Recyclerview.Adapter
The recyclerview uses a viewHolder
public class myAdapter extends RecyclerView.Adapter<myAdapter.ViewHolder>{
private List<String> myList; private int rowLayout; private Context mContext;
public myAdapter(List<String> myList, int rowLayout, Context context) {
this.myList = myList; this.rowLayout = rowLayout; this.mContext = context;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(rowLayout, viewGroup, false);
return new ViewHolder(v); //this is the major change here.
}
@Override
public int getItemCount() {
return myList == null ? 0 : myList.size();
}
Recyclerview.Adapter
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView myName;
public ImageView Pic;
public ViewHolder(View itemView) {
super(itemView);
myName = (TextView) itemView.findViewById(R.id.Name);
Pic= (ImageView)itemView.findViewById(R.id.picture);
}
}
My_row.xml and cardView
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
<androidx.cardview.widget.CardView android:layout_width="match_parent"
android:layout_width="match_parent" android:layout_height="match_parent">

android:layout_height="match_parent" <ImageView
android:id="@+id/picture"
android:layout_margin="5dp"
android:layout_width="match_parent"
card_view:cardCornerRadius="5dp“ android:layout_height="100dp"
card_view:cardElevation="5dp" android:scaleType="centerCrop"
> android:tint="@color/photo_tint"
android:layout_centerInParent="true"
/>

Note, while I'm using a cardview, you don't have too. It's just recommended by google.
My_row.xml and cardView
<TextView
android:id="@+id/Name"
android:gravity="center"
android:background="?android:selectableItemBackground"
android:focusable="true"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="100dp"
android:textSize="24sp"
android:layout_centerInParent="true"
android:textColor="@android:color/white"
/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
Recyclerview.Adapter
• This method is the that setups whatever is in the view.
@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
String entry = myList.get(i);
viewHolder.myName.setText(entry);
viewHolder.myName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView tv = (TextView)v;
Toast.makeText(mContext,tv.getText(),Toast.LENGTH_SHORT).show();
}
});
viewHolder.Pic.setImageResource(R.drawable.phone);
} //mContext.getDrawable(country.getImageResourceId(mContext))
Looking like
Addition info
RecyclerView
addOnItemTouchListener(RecyclerView.OnItemTouchListener listener)
Add an RecyclerView.OnItemTouchListener to intercept touch events before
they are dispatched to child views or this view's standard scrolling behavior.
Demos:
RecyclerViewDemo is the code should here
RecyclerViewDemo2 uses the phonelist from the listview examples.
RecyclerViewDemo3 recreates all the listview demos with a recyclerview.
Most do not use a cardview, but instead use the same layout as the
original examples.
Refresh & Swipes
Swipes down from the top allows
a refresh
Swipe left or right can trigger
other actions
In the case, swipe right deletes
an item.
Swipe Down/refresh
• Uses the SwipeRefreshLayout wrapped around the recyclerview.
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/activity_main_swipe_refresh_layout"
…>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list“

/>

</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
Swipe Down/refresh (2)
• Java code, then setups a listener for it.
• And optionally set colors for the refresh loop.
mSwipeRefreshLayout = (SwipeRefreshLayout) myView.findViewById(R.id.activity_main_swipe_refresh_layout);
• setup some colors for the refresh circle. Optional.
mSwipeRefreshLayout.setColorSchemeResources(R.color.orange, R.color.green, R.color.blue);
• now setup the swiperefrestlayout listener where the main work is done.
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
• Do/Call refresh code here
}
});
• When the refresh is done, make this call to turn off the refresh UI.
mSwipeRefreshLayout.setRefreshing(false);
Swipe Left/Right Code

No changes to the xml are necessary.


 Uses the ItemTouchHelper callbacks
First setup a simplecallback (next slide)
Then attach the recyclerview to it.
ItemTouchHelper itemTouchHelper = new
ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);
ItemTouchHelper.SimpleCallback
• Create the callback
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
• For both Left and right use: ItemTouchHelper.RIGHT |ItemTouchHelper.LEFT
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
//likely allows to for animations? or moving items in the view I think.
return false;
}

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
if (direction == ItemTouchHelper.RIGHT) {
//Now remove the item from the list (likely in the adapter)
int item = viewHolder.getAdapterPosition(); //Which item it is in the list.
// don’t forget notifyDataSetChanged(); in the adapter as well.
//you can combine this with a snackbar as simple, Do you really want to delete this.
}
}
};
Demo Code

• To see all the demo code for the swipes


• See the RecyclerViewSwipeRefresh example

You might also like