Android ListView with icons/images ….and “sharks with lasers”
Well what do they have in common ?……purely coincidence! I recently worked on a project that required a search functionality. The search however involved different categorized items.
I was thinking of a neat visual way to quickly distinguish between results from different categories. Totally COINCIDENTLY at that exact moment a colleague shouted …”sharks with lasers on their heads!”
Download : IconizedListView.zip
Some Notes:
- XML Parsing
- ArrayAdapter for modifying visual display of list items
File: listview.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ListView android:id="@+id/countryLV" android:layout_width="fill_parent" android:layout_height="fill_parent"> </ListView> </LinearLayout>
File: country_listitem.xml
<?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="wrap_content"> <ImageView android:id="@+id/country_icon" android:layout_gravity="left" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/country_name" android:text="Country Name" android:paddingLeft="10dip" android:layout_weight="0.5" android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/country_abbrev" android:text="Country Abbrev" android:layout_gravity="right" android:paddingRight="10dip" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
File: raw/countries.xml
<?xml version="1.0" encoding="utf-8"?> <countries> <country name="Australia" abbreviation="au" region="Asia" /> <country name="Austria" abbreviation="at" region="Europe" /> <country name="Belgium" abbreviation="be" region="Europe" /> <country name="Brazil" abbreviation="br" region="S. America" /> <country name="Canada" abbreviation="ca" region="N. America" /> <country name="China" abbreviation="cn" region="Asia" /> <country name="Denmark" abbreviation="dk" region="Europe" /> <country name="France" abbreviation="fr" region="Europe" /> <country name="Germany" abbreviation="de" region="Europe" /> <country name="Hong Kong" abbreviation="hk" region="Asia" /> <country name="India" abbreviation="in" region="Asia" /> <country name="Indonesia" abbreviation="id" region="Asia" /> <country name="Italy" abbreviation="it" region="Europe" /> <country name="Korea" abbreviation="kr" region="Asia" /> <country name="Netherlands" abbreviation="nl" region="Europe" /> <country name="Norway" abbreviation="no" region="Europe" /> <country name="Portugal" abbreviation="pt" region="Europe" /> <country name="Singapore" abbreviation="sg" region="Asia" /> <country name="Spain" abbreviation="es" region="Europe" /> <country name="Sweden" abbreviation="se" region="Europe" /> <country name="Switzerland" abbreviation="ch" region="Europe" /> <country name="Taiwan" abbreviation="tw" region="Asia" /> <country name="United Kingdom" abbreviation="uk" region="Europe" /> <country name="United States" abbreviation="us" region="N. America" /> </countries>
File: Main.java
import java.io.InputStream; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.widget.ListView; public class Main extends Activity { private List<Country> countryList= new ArrayList<Country>(); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Set the View layer setContentView(R.layout.listview); setTitle("TestIconizedListView"); // Create Parser for raw/countries.xml CountryParser countryParser = new CountryParser(); InputStream inputStream = getResources().openRawResource( R.raw.countries); // Parse the inputstream countryParser.parse(inputStream); // Get Countries List<Country> countryList = countryParser.getList(); // Create a customized ArrayAdapter CountryArrayAdapter adapter = new CountryArrayAdapter( getApplicationContext(), R.layout.country_listitem, countryList); // Get reference to ListView holder ListView lv = (ListView) this.findViewById(R.id.countryLV); // Set the ListView adapter lv.setAdapter(adapter); } }
File: Country.java
public class Country { public String name; public String abbreviation; public String region; public String resourceId; public Country() { // TODO Auto-generated constructor stub } public Country(String name, String abbreviation, String region, String resourceFilePath) { this.name = name; this.abbreviation = abbreviation; this.region= region; this.resourceId = resourceFilePath; } @Override public String toString() { return this.name; } }
File: CountryParser.java
import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import android.util.Log; public class CountryParser { private static final String tag = "CountryParser"; private static final String FILE_EXTENSION= ".png"; private DocumentBuilderFactory factory; private DocumentBuilder builder; private final List<Country> list; public CountryParser() { this.list = new ArrayList<Country>(); } private String getNodeValue(NamedNodeMap map, String key) { String nodeValue = null; Node node = map.getNamedItem(key); if (node != null) { nodeValue = node.getNodeValue(); } return nodeValue; } public List<Country> getList() { return this.list; } /** * Parse XML file containing body part X/Y/Description * * @param inStream */ public void parse(InputStream inStream) { try { // TODO: after we must do a cache of this XML!!!! this.factory = DocumentBuilderFactory.newInstance(); this.builder = this.factory.newDocumentBuilder(); this.builder.isValidating(); Document doc = this.builder.parse(inStream, null); doc.getDocumentElement().normalize(); NodeList countryList = doc.getElementsByTagName("country"); final int length = countryList.getLength(); for (int i = 0; i < length; i++) { final NamedNodeMap attr = countryList.item(i).getAttributes(); final String countryName = getNodeValue(attr, "name"); final String countryAbbr = getNodeValue(attr, "abbreviation"); final String countryRegion = getNodeValue(attr, "region"); // Construct Country object Country country = new Country(countryName, countryAbbr, countryRegion, countryAbbr + FILE_EXTENSION); // Add to list this.list.add(country); Log.d(tag, country.toString()); } } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } } }
File: CountryArrayAdapter.java
import java.io.IOException; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; public class CountryArrayAdapter extends ArrayAdapter<Country> { private static final String tag = "CountryArrayAdapter"; private static final String ASSETS_DIR = "images/"; private Context context; private ImageView countryIcon; private TextView countryName; private TextView countryAbbrev; private List<Country> countries = new ArrayList<Country>(); public CountryArrayAdapter(Context context, int textViewResourceId, List<Country> objects) { super(context, textViewResourceId, objects); this.context = context; this.countries = objects; } public int getCount() { return this.countries.size(); } public Country getItem(int index) { return this.countries.get(index); } public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; if (row == null) { // ROW INFLATION Log.d(tag, "Starting XML Row Inflation ... "); LayoutInflater inflater = (LayoutInflater) this.getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); row = inflater.inflate(R.layout.country_listitem, parent, false); Log.d(tag, "Successfully completed XML Row Inflation!"); } // Get item Country country = getItem(position); // Get reference to ImageView countryIcon = (ImageView) row.findViewById(R.id.country_icon); // Get reference to TextView - country_name countryName = (TextView) row.findViewById(R.id.country_name); // Get reference to TextView - country_abbrev countryAbbrev = (TextView) row.findViewById(R.id.country_abbrev); //Set country name countryName.setText(country.name); // Set country icon usign File path String imgFilePath = ASSETS_DIR + country.resourceId; try { Bitmap bitmap = BitmapFactory.decodeStream(this.context.getResources().getAssets() .open(imgFilePath)); countryIcon.setImageBitmap(bitmap); } catch (IOException e) { e.printStackTrace(); } // Set country abbreviation countryAbbrev.setText(country.abbreviation); return row; } }
Re-wrote this example:
1. xml for listview of countries
2. xml for each row item in listview with place holders for image, country_name, country_abbrev
3. Customized ArrayAdapter for using Country object.
4. Acessing image files in the assets/ directory using:
// Set country icon usign File path
String imgFilePath = ASSETS_DIR + country.resourceId;
try {
Bitmap bitmap = BitmapFactory.decodeStream(this.context.getResources().getAssets()
.open(imgFilePath));
countryIcon.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
Source code – download link posted above!
This was really helpful! Thanks.
However, I’m having trouble with using an OnClickListener on ListView lv.
so much complicated for a beginners.
Very Nice tutorial.
hi nice tutorial.
If I have to add new flag and country_name in the list using notification is it possible.. ?
It means create a notification and using notification send Flag and country name. when we press on notification that flag and country name added to above list view .
Please reply me on shirkeshashi04@gmail.com
Compilcated for new user
Really helpfull!
I’ll try as soon as possible
Thanks.
What an awesome tutorial!
I tried the above but the code populates the list view with only the last element in the array what might be the problem
Nice tutorial ,Actually i’m developing a project in which have need to view image from url and and display it in listview.No of image is not fix,So please reply on my id androiddilip78@gmail.com
Thanks
W2Davids: Great tutorial. Trying to figure out how to capture list item clicks… implementing onListItemClick does not work for me. Any suggestions on how to tweak this?
public void onListItemClick(ListView parent, View v, int position, long id) {
Toast.makeText(this, “you have selected ” + position, Toast.LENGTH_SHORT).show();
}
Hi i m also trying similar kind of application whereas i m showing list of countries with their flags and it is working fine , but i want to display the details of the country when i m clicking corresponding flag or text, is there any idea or sample for this?
thanks
the zip file was really helpfull for me thanks
hi… Very Helpful for me! Thank You for This Wonderful Tutorial!!!
Doesn’t work!!! I’ve copied all the project with -14 libraries and doesn’t work… Force close every time I run it.
thanks, that’s great.
very much thanks for you dear…… thanks thanks thanks alot….. it worths alot…. thank you……
Not sure if you would reply back but I have a strange event happening with remaking this code. I have the exact code but on the array adapter class textview keeps giving me a null error. I have verified that there is data before putting inside textview. Is there anything special you did?. I have explored almost all the possibilities could you reply me back with any data you did on this matter.
Your download site sucks!
Link is outdated since they closed down mediafire etc.
github: https://github.com/w2davids/Ghostdrive
click on zip
Thanks a lot! Used to view a list of installed apps on the phone, I’m a beginner so it took a night, but finally works, thanks!
Greate turtorial, i.m using right now and was very very helpful, but i need to implement onListItemClick listener. need help
Very good tutorial indeed but i have one query…
Can any1 tell me that how to implement onClick method on images ( not list iteam),,,I want to implement method when user click on particular image and I can implement further actions by knowing which listiteam’s image was clicked….
Thx in advance…
I can not do this part :
String imgFilePath = ASSETS_DIR + country.resourceId;
try {
Bitmap bitmap = BitmapFactory.decodeStream(this.context.getResources().getAssets()
.open(imgFilePath));
countryIcon.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
please help me . I am beginner for android so tell me simple this part.
duygu,
ASSETS_DIR ‘a resimlerin bulunduğu klasörün linki atadın mı?
Marhaba, Guneidin..hehe
My turkish is non-existent – so english please.
(My best friend is turkish- from Kayseri)
Sayfada editText alanı oluşturup, yazdıkça ülkeleri filtreleyen bir kısım yapmak mümkün mü acaba? Bir fikri olan varsa yazarsa sevinirim.
Is it possible to create an editText and search countries by filtering? Normally from a simple array its eeasier but when we take the data from XML its getting more complicated.
I would be grateful if someone gives an advice.
Thanks
Great tutorial 🙂 thanks a lot
I firmly convinced, that you are not right. Time will show.
P.S. Please review icons
Really good solution compared to a lot that are out there. I see myself replacing the XML with a database further down the line, and I’m able to just write code that creates a List from the db and it works without having to rewrite everything. Great code – but perhaps not good as an introduction for beginners – that said – I was able to follow the code and this is the first XML parser I’ve ever used
IF WE CAN’T USE onListItemClick METHOD THEN WHAT’S THE PURPOSE OF THIS TUTORIAL!!! YOU WASTED MY TIME
The answer is yes by adding to the Main.java after lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView arg0, View arg1, int arg2, long arg3) {
}
});
i’m beginner in android. i have to add the calendar events in my calendar application. so give me tips and procedure and also some coding parts.
i could not able to download this source code can you pls tell me how to download for free pls…
1 Pingback
GOOGLE
Recent Posts
Archives
Categories
Meta