In this tutorial, we will create an app that will showcase some of the Adobe CC apps using a ListView component and an XML file. A ListView component is ViewGroup that displays a "list" of scrollable items when needed. Each list item is generated by an Adapter that translate the data from a data source (e.g., Array, XML, JSON, SQLite).
As in many objects that are created, we will:
In this second version of the Adobe Apps, we will drag-and-drop a ListView component onto the screen and the use an Adapter and an array to populate the ListView.
android:background="#5151fe">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/ListView"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" android:divider="#cccccc"
android:dividerHeight="1dp"/>
While you could have done this at the SAME time you created the ListView component above, we wanted to do it in a systematic approach. However, in real production, it would be best to create the components and give them names at the same time they are created.
IMPORTANT CONCEPT TO REMEMBER: It is important to name every component that will be used by Java code with an id. The id is used to store a reference of the element in a Java object as you will see later.
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/appsListView"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" android:divider="#cccccc"
android:dividerHeight="1dp"
/>
public class MainActivity extends AppCompatActivity {
private ListView myListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myListView = (ListView) findViewById(R.id.appsListView);
// Create a String Array to hold ListView items
final String[] appsStringArray = new String []{"Dreamweaver", "Photoshop", "Illustrator",
"InDesign", "Animate", "After Effects", "Premiere Pro", "LightRoom", "Muse", "Fuse",
"Acrobat Pro", "Audition", "PhoneGap Build"};
// Define Adaptor to "adapt" Array elements to List items
ArrayAdapter<String> appsAdapter = new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_list_item_1,android.R.id.text1, appsStringArray);
// Assign Adaptor to ListView
myListView.setAdapter(appsAdapter);
}
}
ArrayList<String> appsStringArray = new ArrayList<String>();- You may also see the data coming from a string resource and a _____ attribute used to call it.
appsStringArray.add("Dreamweaver");
appsStringArray.add("Photoshop");
appsStringArray.add("Illustrator");
appsStringArray.add("InDesign");
appsStringArray.add("Animate");
appsStringArray.add("After Effects");
appsStringArray.add("Premiere Pro");
appsStringArray.add("LightRoom");
appsStringArray.add("Muse");
appsStringArray.add("Fuse");
appsStringArray.add("Acrobat Pro");
appsStringArray.add("Audition");
appsStringArray.add("PhoneGap Build");
Similar to an onClickListener that are typically used for buttons and images, a ListView has the setOnItemClickListener.
// Assign Adaptor to ListViewNOTE: DO NOT COMPLETE THE CODE
myListView.setAdapter(appsAdapter);
//Set onItemClick Event Listener
myListView.setOnItemClickListener(new OnItemClick
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
})
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String clickedValue = myListView.getItemAtPosition(position).toString();
Toast.makeText(getApplicationContext(),clickedValue,Toast.LENGTH_SHORT).show();
}
});
As with most View components, you can customize them by creating a separate XML file as a template and then inflate it.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/custom_listview_selector"
android:orientation="horizontal"
android:padding="5dp">
<LinearLayout
android:id="@+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginRight="5dp"
android:orientation="vertical">
<ImageView android:id="@+id/list_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/ic_launcher" />
</LinearLayout>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/thumbnail"
android:layout_toRightOf="@id/thumbnail"
android:text="Adobe Dreamweaver"
android:textColor="#000000"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/sub_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/title"
android:layout_toRightOf="@id/thumbnail"
android:text="Web and Mobile"
android:textColor="#ffffff"
android:textSize="14sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/ic_media_play"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
// ArrayAdapter<String> appsAdapter = new ArrayAdapter<String>(getApplicationContext(), // android.R.layout.simple_list_item_1,android.R.id.text1, appsStringArray);
public class CustomListViewAdapter extends BaseAdapter {
}
public class CustomListViewAdapter extends BaseAdapter {
@Override
public int getCount() {
return 0;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;
}
}
public class CustomListViewAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<HashMap<String,String>> topics;
private static LayoutInflater inflater = null;
public CustomListViewAdapter(Context context,ArrayList<HashMap<String ,String>> data){
mContext = context;
topics = data;
inflater = (LayoutInflater)context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return topics.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (convertView == null){
view = inflater.inflate(R.layout.custom_listview_row, null);
}
TextView title = (TextView) view.findViewById(R.id.title);
TextView sub_title = (TextView) view.findViewById(R.id.sub_title);
HashMap<String, String> mTopic = new HashMap<>();
mTopic = topics.get(position);
title.setText(mTopic.get("title"));
sub_title.setText(mTopic.get("sub_title"));
return view;
}
}
public class MainActivity extends AppCompatActivity {
private ListView myListView;
private CustomListViewAdapter customListViewAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myListView = (ListView) findViewById(R.id.appsListView);
// Create a String Array to hold ListView items
final String[] appsStringArray = new String []{"Dreamweaver", "Photoshop", "Illustrator",
"InDesign", "Animate", "After Effects", "Premiere Pro", "LightRoom", "Muse", "Fuse",
"Acrobat Pro", "Audition", "PhoneGap Build"};
// Create a String Array to hold ListView items for sub_titles
final String[] descriptionArray = new String []{"Web and mobile design", "Image editing and compositing",
"Vector graphics and illustration", "Page design and layout", "Animation, video and games", "Visual effects and motion graphics", "Video production and editing",
"Photo processing and editing", "Website design without coding", "Custom 3D characters for Photoshop","Create and edit PDF and forms", "Audio recording and restoration", "Package mobile apps"};
// Define Adaptor to "adapt" Array elements to List items
// ArrayAdapter<String> appsAdapter = new ArrayAdapter<String>(getApplicationContext(),
// android.R.layout.simple_list_item_1,android.R.id.text1, appsStringArray);
final ArrayList<HashMap<String,String>> titleList = new ArrayList<>();
for (int i=0; i<13; i++){
HashMap<String,String> data = new HashMap<>();
data.put("title",appsStringArray[i]);
data.put("sub_title",descriptionArray[i]);
titleList.add(data);
}
// Assign Adaptor to ListView
customListViewAdapter = new CustomListViewAdapter(getApplicationContext(),titleList);
myListView.setAdapter(customListViewAdapter);
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String myItem = appsStringArray[position];
Toast.makeText(getApplicationContext(), myItem, Toast.LENGTH_SHORT).show();
}
});
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (convertView == null){
view = inflater.inflate(R.layout.custom_listview_row, null);
}
TextView title = (TextView) view.findViewById(R.id.title);
TextView sub_title = (TextView) view.findViewById(R.id.sub_title);
ImageView image = (ImageView) view.findViewById(R.id.list_icon);
HashMap<String, String> mTopic = new HashMap<>();
mTopic = topics.get(position);
title.setText(mTopic.get("title"));
sub_title.setText(mTopic.get("sub_title"));
if(position==0) {
image.setImageResource(R.drawable.dreamweaver);
}
if(position==1) {
image.setImageResource(R.drawable.photoshop);
}
if(position==2) {
image.setImageResource(R.drawable.illustrator);
}
if(position==3) {
image.setImageResource(R.drawable.indesign);
}
if(position==4) {
image.setImageResource(R.drawable.animate);
}
if(position==5) {
image.setImageResource(R.drawable.after_effects);
}
if(position==6) {
image.setImageResource(R.drawable.premiere_pro);
}
if(position==7) {
image.setImageResource(R.drawable.lightroom);
}
if(position==8) {
image.setImageResource(R.drawable.muse);
}
if(position==9) {
image.setImageResource(R.drawable.fuse);
}
if(position==10) {
image.setImageResource(R.drawable.acrobat_pro_dc);
}
if(position==11) {
image.setImageResource(R.drawable.audition);
}
if(position==12) {
image.setImageResource(R.drawable.photoshop);
}
return view;
}
}
It is important to note how these components will be knitted together. The listview state xml files are nested inside of the selector xml file which is inside of the row xml which is pulled inside (inflated) in the java file (e.g., CustomListViewAdapter.java):
Not only do you have to create a custom layout, you have to create a custom adaptor as well. In order to show the custom ListView, we will have to inflate it with Java.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient
android:angle="270" android:startColor="#f1f1f2"
android:centerColor="#7878fa"
android:endColor="#cfcfcf"> </gradient>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient
android:angle="270"
android:centerColor="#5454f5"
android:endColor="#cfcfcf"
android:startColor="#f1f1f2"> </gradient>
</shape>
<?xml version="1.0" encoding="utf-8"?>NOTE: The first <item> element is used if the list item has not been selected and have not been pressed--show the default background (e.g., custom_listview. The second <item> element is used if the list item is presses but not selected. The third <item> element is used if the list item is pressed and selected (user has press and then removed finger from selection).
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/custom_listview_normal"
android:state_pressed="false"
android:state_selected="false">
</item>
<item android:drawable="@drawable/custom_listview_hover"
android:state_pressed="true">
</item>
<item android:drawable="@drawable/custom_listview_hover"
android:state_pressed="true"
android:state_selected="true">
</item>
</selector>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp"
android:background="@drawable/custom_listview_selector">