Consider reading the more efficient solution which uses Volley library to achieve the same. Android Custom ListView with Image and Text using Volley
This is a tutorial about customizing listview with an image and text. For this tutorial I am using some of the classes from this link. In this tutorial I explained how to load images from remote url and update into listview. Also explained how to design listview with your custom styles and colors instead of using default listview style.
The Sample XML
For this tutorial I am using following sample XML which has some data and a thumbnail image url. You can get this XML by accessing https://api.androidhive.info/music/music.xml
<?xml version="1.0" encoding="UTF-8"?> <music> <song> <id>1</id> <title>Someone Like You</title> <artist>Adele</artist> <duration>4:47</duration> <plays>1662</plays> <thumb_url>https://api.androidhive.info/music/images/adele.png</thumb_url> </song> <song> <id>2</id> <title>Space Bound</title> <artist>Eminem</artist> <duration>4:38</duration> <plays>1900</plays> <thumb_url>https://api.androidhive.info/music/images/eminem.png</thumb_url> </song> . . . . </music>
Before going further make sure that you covered Android XML Parsing Tutorial and Android ListView Tutorial before
Creating New Project
1. Create new project in your Eclipse IDE and fill all the details. File ⇒ New Project
2. If you notice the screen shots I designed listview with gradient background. To define gradient style create three new XML files under drawable folder and name them as gradient_bg.xml, list_selector.xml and gradient_bg_hover.xml and fill with following code. Also the thumbnail image has white background, for this I used image_bg.xml
Right Click and drawable-hdpi ⇒ New ⇒ Android XML File
gradient_bg.xml – Default Background Gradient Style
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <gradient android:startColor="#f1f1f2" android:centerColor="#e7e7e8" android:endColor="#cfcfcf" android:angle="270" /> </shape>
gradient_bg_hover.xml – Gradient Style for on hover state
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <gradient android:startColor="#18d7e5" android:centerColor="#16cedb" android:endColor="#09adb9" android:angle="270" /> </shape>
list_selector.xml – Actual liststyle which combines the above two styles
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/gradient_bg" /> <item android:state_pressed="true" android:drawable="@drawable/gradient_bg_hover" /> <item android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/gradient_bg_hover" /> </selector>
image_bg.xml – is for white border around the image in listview
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item> <shape android:shape="rectangle"> <stroke android:width="1dp" android:color="#dbdbdc" /> <solid android:color="#FFFFFF" /> </shape> </item> </layer-list>
3. Now open your main.xml file and define a listview in it.
<?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"> <ListView android:id="@+id/list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="#b5b5b5" android:dividerHeight="1dp" android:listSelector="@drawable/list_selector" /> </LinearLayout>
4. Next step is to design single listrow. Create a new XML file under layout folder and name it as list_row.xml.
Right Click ⇒ New ⇒ Android XML File
In this tutorial I custom designed a listview which contains an image on leftside, time and arrow at the right end and a title in middle. I used RelativeLayout as parent node and placed all the remaining items using relative positioning properties. Check the following image
list_row.xml – Single ListRow Layout
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/list_selector" android:orientation="horizontal" android:padding="5dip" > <!-- ListRow Left sied Thumbnail image --> <LinearLayout android:id="@+id/thumbnail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="3dip" android:layout_alignParentLeft="true" android:background="@drawable/image_bg" android:layout_marginRight="5dip"> <ImageView android:id="@+id/list_image" android:layout_width="50dip" android:layout_height="50dip" android:src="@drawable/rihanna"/> </LinearLayout> <!-- Title Of Song--> <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="Rihanna Love the way lie" android:textColor="#040404" android:typeface="sans" android:textSize="15dip" android:textStyle="bold"/> <!-- Artist Name --> <TextView android:id="@+id/artist" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/title" android:textColor="#343434" android:textSize="10dip" android:layout_marginTop="1dip" android:layout_toRightOf="@+id/thumbnail" android:text="Just gona stand there and ..." /> <!-- Rightend Duration --> <TextView android:id="@+id/duration" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignTop="@id/title" android:gravity="right" android:text="5:45" android:layout_marginRight="5dip" android:textSize="10dip" android:textColor="#10bcc9" android:textStyle="bold"/> <!-- Rightend Arrow --> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/arrow" android:layout_alignParentRight="true" android:layout_centerVertical="true"/> </RelativeLayout>
The above XML will provide you output like below
5. Until now we completed designing part of the listview. Next step is to parse the xml and update the data into listview. Create a new java class file in your src folder. Right Click on src ⇒ New ⇒ Class and name it as LazyAdapter.java
package com.example.androidhive; import java.util.ArrayList; import java.util.HashMap; import android.app.Activity; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class LazyAdapter extends BaseAdapter { private Activity activity; private ArrayList<HashMap<String, String>> data; private static LayoutInflater inflater=null; public ImageLoader imageLoader; public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) { activity = a; data=d; inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); imageLoader=new ImageLoader(activity.getApplicationContext()); } public int getCount() { return data.size(); } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { View vi=convertView; if(convertView==null) vi = inflater.inflate(R.layout.list_row, null); TextView title = (TextView)vi.findViewById(R.id.title); // title TextView artist = (TextView)vi.findViewById(R.id.artist); // artist name TextView duration = (TextView)vi.findViewById(R.id.duration); // duration ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // thumb image HashMap<String, String> song = new HashMap<String, String>(); song = data.get(position); // Setting all values in listview title.setText(song.get(CustomizedListView.KEY_TITLE)); artist.setText(song.get(CustomizedListView.KEY_ARTIST)); duration.setText(song.get(CustomizedListView.KEY_DURATION)); imageLoader.DisplayImage(song.get(CustomizedListView.KEY_THUMB_URL), thumb_image); return vi; } }
6. Now open your MainActivity class and type the following code. In the following code I am getting xml from url and parsing it. While parsing I am storing all the xml data into HashMap and finally I am passing HashMap to LazyAdapter class.
package com.example.androidhive; import java.util.ArrayList; import java.util.HashMap; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; public class CustomizedListView extends Activity { // All static variables static final String URL = "https://api.androidhive.info/music/music.xml"; // XML node keys static final String KEY_SONG = "song"; // parent node static final String KEY_ID = "id"; static final String KEY_TITLE = "title"; static final String KEY_ARTIST = "artist"; static final String KEY_DURATION = "duration"; static final String KEY_THUMB_URL = "thumb_url"; ListView list; LazyAdapter adapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>(); XMLParser parser = new XMLParser(); String xml = parser.getXmlFromUrl(URL); // getting XML from URL Document doc = parser.getDomElement(xml); // getting DOM element NodeList nl = doc.getElementsByTagName(KEY_SONG); // looping through all song nodes <song> for (int I = 0; I < nl.getLength(); i++) { // creating new HashMap HashMap<String, String> map = new HashMap<String, String>(); Element e = (Element) nl.item(i); // adding each child node to HashMap key => value map.put(KEY_ID, parser.getValue(e, KEY_ID)); map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE)); map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST)); map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION)); map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL)); // adding HashList to ArrayList songsList.add(map); } list=(ListView)findViewById(R.id.list); // Getting adapter by passing xml data ArrayList adapter=new LazyAdapter(this, songsList); list.setAdapter(adapter); // Click event for single list row list.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { } }); } }
Add Permissions in AndroidManifest.xml
Open your AndroidManifest.xml file add two permissons INTERNET and WRITE_EXTERNAL_STORAGE.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.androidhive" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".CustomizedListView" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </manifest>
Also you need 5 more classes in order to run this project. I am giving the code for each class at the end of the article. After adding all the classes if you run the project it will show output like below
ListView Default State
ListView on Select State
Other Classes you needed to run this project
You also need to include following class which deals functionalities like fetching images from WEB, storing them in cache and clearing cache etc., Make sure that you included following files in your project.
XMLParser.java
package com.example.androidhive; import java.io.IOException; import java.io.StringReader; import java.io.UnsupportedEncodingException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import android.util.Log; public class XMLParser { // constructor public XMLParser() { } /** * Getting XML from URL making HTTP request * @param url string * */ public String getXmlFromUrl(String url) { String xml = null; try { // defaultHttpClient DefaultHttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(url); HttpResponse httpResponse = httpClient.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); xml = EntityUtils.toString(httpEntity); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // return XML return xml; } /** * Getting XML DOM element * @param XML string * */ public Document getDomElement(String xml){ Document doc = null; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { DocumentBuilder db = dbf.newDocumentBuilder(); InputSource is = new InputSource(); is.setCharacterStream(new StringReader(xml)); doc = db.parse(is); } catch (ParserConfigurationException e) { Log.e("Error: ", e.getMessage()); return null; } catch (SAXException e) { Log.e("Error: ", e.getMessage()); return null; } catch (IOException e) { Log.e("Error: ", e.getMessage()); return null; } return doc; } /** Getting node value * @param elem element */ public final String getElementValue( Node elem ) { Node child; if( elem != null){ if (elem.hasChildNodes()){ for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){ if( child.getNodeType() == Node.TEXT_NODE ){ return child.getNodeValue(); } } } } return ""; } /** * Getting node value * @param Element node * @param key string * */ public String getValue(Element item, String str) { NodeList n = item.getElementsByTagName(str); return this.getElementValue(n.item(0)); } }
ImageLoader.java
package com.example.androidhive; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Collections; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.widget.ImageView; public class ImageLoader { MemoryCache memoryCache=new MemoryCache(); FileCache fileCache; private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); ExecutorService executorService; public ImageLoader(Context context){ fileCache=new FileCache(context); executorService=Executors.newFixedThreadPool(5); } final int stub_id = R.drawable.no_image; public void DisplayImage(String url, ImageView imageView) { imageViews.put(imageView, url); Bitmap bitmap=memoryCache.get(url); if(bitmap!=null) imageView.setImageBitmap(bitmap); else { queuePhoto(url, imageView); imageView.setImageResource(stub_id); } } private void queuePhoto(String url, ImageView imageView) { PhotoToLoad p=new PhotoToLoad(url, imageView); executorService.submit(new PhotosLoader(p)); } private Bitmap getBitmap(String url) { File f=fileCache.getFile(url); //from SD cache Bitmap b = decodeFile(f); if(b!=null) return b; //from web try { Bitmap bitmap=null; URL imageUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection(); conn.setConnectTimeout(30000); conn.setReadTimeout(30000); conn.setInstanceFollowRedirects(true); InputStream is=conn.getInputStream(); OutputStream os = new FileOutputStream(f); Utils.CopyStream(is, os); os.close(); bitmap = decodeFile(f); return bitmap; } catch (Exception ex){ ex.printStackTrace(); return null; } } //decodes image and scales it to reduce memory consumption private Bitmap decodeFile(File f){ try { //decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeStream(new FileInputStream(f),null,o); //Find the correct scale value. It should be the power of 2. final int REQUIRED_SIZE=70; int width_tmp=o.outWidth, height_tmp=o.outHeight; int scale=1; while(true){ if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE) break; width_tmp/=2; height_tmp/=2; scale*=2; } //decode with inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize=scale; return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); } catch (FileNotFoundException e) {} return null; } //Task for the queue private class PhotoToLoad { public String url; public ImageView imageView; public PhotoToLoad(String u, ImageView i){ url=u; imageView=i; } } class PhotosLoader implements Runnable { PhotoToLoad photoToLoad; PhotosLoader(PhotoToLoad photoToLoad){ this.photoToLoad=photoToLoad; } @Override public void run() { if(imageViewReused(photoToLoad)) return; Bitmap bmp=getBitmap(photoToLoad.url); memoryCache.put(photoToLoad.url, bmp); if(imageViewReused(photoToLoad)) return; BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad); Activity a=(Activity)photoToLoad.imageView.getContext(); a.runOnUiThread(bd); } } boolean imageViewReused(PhotoToLoad photoToLoad){ String tag=imageViews.get(photoToLoad.imageView); if(tag==null || !tag.equals(photoToLoad.url)) return true; return false; } //Used to display bitmap in the UI thread class BitmapDisplayer implements Runnable { Bitmap bitmap; PhotoToLoad photoToLoad; public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;} public void run() { if(imageViewReused(photoToLoad)) return; if(bitmap!=null) photoToLoad.imageView.setImageBitmap(bitmap); else photoToLoad.imageView.setImageResource(stub_id); } } public void clearCache() { memoryCache.clear(); fileCache.clear(); } }
MemoryCache.java
package com.example.androidhive; import java.lang.ref.SoftReference; import java.util.Collections; import java.util.HashMap; import java.util.Map; import android.graphics.Bitmap; public class MemoryCache { private Map<String, SoftReference<Bitmap>> cache=Collections.synchronizedMap(new HashMap<String, SoftReference<Bitmap>>()); public Bitmap get(String id){ if(!cache.containsKey(id)) return null; SoftReference<Bitmap> ref=cache.get(id); return ref.get(); } public void put(String id, Bitmap bitmap){ cache.put(id, new SoftReference<Bitmap>(bitmap)); } public void clear() { cache.clear(); } }
Utils.java
package com.example.androidhive; import java.io.InputStream; import java.io.OutputStream; public class Utils { public static void CopyStream(InputStream is, OutputStream os) { final int buffer_size=1024; try { byte[] bytes=new byte[buffer_size]; for(;;) { int count=is.read(bytes, 0, buffer_size); if(count==-1) break; os.write(bytes, 0, count); } } catch(Exception ex){} } }
FileCache.java
package com.example.androidhive; import java.io.File; import android.content.Context; public class FileCache { private File cacheDir; public FileCache(Context context){ //Find the dir to save cached images if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"LazyList"); else cacheDir=context.getCacheDir(); if(!cacheDir.exists()) cacheDir.mkdirs(); } public File getFile(String url){ //I identify images by hashcode. Not a perfect solution, good for the demo. String filename=String.valueOf(url.hashCode()); //Another possible solution (thanks to grantland) //String filename = URLEncoder.encode(url); File f = new File(cacheDir, filename); return f; } public void clear(){ File[] files=cacheDir.listFiles(); if(files==null) return; for(File f:files) f.delete(); } }
Hi there! I am Founder at androidhive and programming enthusiast. My skills includes Android, iOS, PHP, Ruby on Rails and lot more. If you have any idea that you would want me to develop? Let’s talk: ravi@androidhive.info
HI!
i want to display orginal image as downloaded from url, which line i need to change ?
getting error in xml parser
04-22 15:43:31.903: E/Error:(739): expected: /meta read: head (position:END_TAG @15:10 in java.io.StringReader@40e2a9d8)
Hi, thank you very much for your fantastic code. A have a question, how i can load an image from sdcard or internal device? I’m trying it but i don’t find the correct answer. Sorry for my english and for my question, i’m beginner at android. Thank you very much again, bye bye
Sir while implementing the given code unfortunately my UI stopped.Logcat showing error in HttpResponse in XMLParser and String XML in Main Activity.How can I rectify that sir.Please reply me.
Thanks Ravi! It’s amazing that you have shared this brilliant piece of code here. Just typing this in, getting it to run and trying to understand the concepts you used have taught me more in one day than I would understand in weeks. Thanks again for the good work.
It would have been a much more honest tutorial if Ravi would have provided a link to the MIT licensed LazyList library that he has used for his lazy image loading caching concepts.
Can’t download the file. Any problems maybe?
I downloaded this tutorial but this is logcat with error:
Please help me, i need this tutorial ^^
05-04 19:58:16.561: E/Trace(1311): error opening trace file: No such file or directory (2)
05-04 19:58:17.511: E/Error:(1311): expected: /hr read: body (position:END_TAG @6:8 in java.io.StringReader@4121e2b8)
05-04 19:58:17.511: D/AndroidRuntime(1311): Shutting down VM
05-04 19:58:17.521: W/dalvikvm(1311): threadid=1: thread exiting with uncaught exception (group=0x40a13300)
05-04 19:58:17.531: E/AndroidRuntime(1311): FATAL EXCEPTION: main
05-04 19:58:17.531: E/AndroidRuntime(1311): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.androidhive/com.example.androidhive.CustomizedListView}: java.lang.NullPointerException
05-04 19:58:17.531: E/AndroidRuntime(1311): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
05-04 19:58:17.531: E/AndroidRuntime(1311): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
05-04 19:58:17.531: E/AndroidRuntime(1311): at android.app.ActivityThread.access$600(ActivityThread.java:130)
05-04 19:58:17.531: E/AndroidRuntime(1311): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
05-04 19:58:17.531: E/AndroidRuntime(1311): at android.os.Handler.dispatchMessage(Handler.java:99)
05-04 19:58:17.531: E/AndroidRuntime(1311): at android.os.Looper.loop(Looper.java:137)
05-04 19:58:17.531: E/AndroidRuntime(1311): at android.app.ActivityThread.main(ActivityThread.java:4745)
05-04 19:58:17.531: E/AndroidRuntime(1311): at java.lang.reflect.Method.invokeNative(Native Method)
05-04 19:58:17.531: E/AndroidRuntime(1311): at java.lang.reflect.Method.invoke(Method.java:511)
05-04 19:58:17.531: E/AndroidRuntime(1311): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
05-04 19:58:17.531: E/AndroidRuntime(1311): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
05-04 19:58:17.531: E/AndroidRuntime(1311): at dalvik.system.NativeStart.main(Native Method)
05-04 19:58:17.531: E/AndroidRuntime(1311): Caused by: java.lang.NullPointerException
05-04 19:58:17.531: E/AndroidRuntime(1311): at com.example.androidhive.CustomizedListView.onCreate(CustomizedListView.java:43)
05-04 19:58:17.531: E/AndroidRuntime(1311): at android.app.Activity.performCreate(Activity.java:5008)
05-04 19:58:17.531: E/AndroidRuntime(1311): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
05-04 19:58:17.531: E/AndroidRuntime(1311): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
05-04 19:58:17.531: E/AndroidRuntime(1311): … 11 more
I got the Same error. Used HttpGet httpPost=new HttpGet(url); instead of HttpPost httpPost = new HttpPost(url);inside getXmlFromUrl procedure. Worked fine.
because get data from url xml error.you shounld get data xml from other :).i try and run app ok 🙂
i’ve tried what you’ve said… but it’s still giving me nullpointerexception…..
YEAH, thanks
String xml = parser.getXmlFromUrl(URL); —> this error,return null :D,
you have to get data from other
from other what??? other xml????
i’m sorry… i’m new to this… i haven’t used xml parsing before…
create new xml and parsing xml yourself 🙂
Is it at all possible to add Async tasking to this so that it works in 4.0+?
Thanks
hello…i download this code and fix her properties but it does not work…it display (force close)…
change the HttpPost to HttpGet in getXmlFromUrl method in XmlParser class.. works like charm
still am getting same problem
Perfect!
Yes the problem is solved 🙂
You have to download the xml file and put it in your own server, and then change the HttpPost to HttpGet.
its working without downloading the xml.. Thanks..
this code has some problem at Activity a=(Activity)photoToLoad.imageView.getContext();in PhotosLoader class. Somehow it cannot take the activity of the imageView and doesn’t run the BitmapDisplayer on Ui thread. So I took the activity as parameter and called the runOnUiThread directly from activity and it worked. I couldn’t understand the reason but solution is this.
Can you please show in code what did you do? I am a beginner to Android and its been two days… the sample code never worked, I am using Mac, so I have no idea how all these people got it working!
Someone is selling this FREE excellent tutorial on chupamobile for $19. Here’s the link. http://www.chupamobile.com/products/details/795/Custom+ListView+with+Images+and+Text/
I am ready to buy it if it works!
Well it looks great tutorial. I have downloaded the source code tried to launch the project and didn’t work, with showing “Unfortunately, CustomizedListView has stopped…” so people can you please, for God Sake, stop asking repeated questions and let us just to get the solution for this issue!!!
Can you please tell me why the sample code is not working!
It’s not running throwing null pointer exception
This Amazing tutorial about ListView with Image And Text. I love androidHive
hi
i am rahul i have downloaded whole code and when i executed this project then i getting an error in CustomizedListView class at line 43 (NodeList nl = doc.getElementsByTagName(KEY_SONG);) error message is Caused by: java.lang.NullPointerException
so provide solution why i am getting error…………
yeah… me too… the logcat always give me a null pointer exception… how can i make it run??? please help… i really need help….
This xml parsing Error please change the URL and (KEY_SONG);) Nod and chield nod change………..
Very useful codes,But when I tried with other “URL” and key values it doesn’t work ,it gets stuck in a loading page when i try to run the app.So can you please give me some suggestions regarding what all changes I need to do get the app executing properly with the new Url.
Thanks in Advance
nice tutorial………..
nice tutorial thanx
Hi Amit Suro & & Dsireesha0309 ., i have passing image from one activity to another activity using following code.its working well…
ImageLoader imageLoader = new ImageLoader(getApplicationContext());
final ImageView ima = (ImageView) findViewById(R.id.icon);
imageLoader.DisplayImage(_Image, ima);
I tried onclick listener. But it is not working. I don’t what the problem in it. Even my eclipse not generating R.java. Please suggest any solution.
This is Nice Tutorial.
So, How can add Search view to this list. I try to used Text Watcher but it not success. here my code I used in Main Activity.
adapter = new CustomListViewAdapter(this,R.layout.list_row, rowItems);
listView.setAdapter(adapter);
listView.setTextFilterEnabled(true);
editText.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
}
public void afterTextChanged(Editable arg0) {
ActivityName.this.adapter.getFilter().filter(arg0);
}
});
Help me
Thank you.
pretty good tutorial !
Thanks for that …
Thanks Man!!
Why are you specifying “hdpi”? AFAIK, This is not resolution specific.
hi… im marco… i downloaded the code… but it didn’t work… then i try to simulate step by step of your tutorial, and i did also copy the codes posted here… but it still didn’t work… the logcat always give me a NullPointerException… what should i do to make it run??? please help….
hi ravi…. i have downloaded your code but when i run it,,, it gives me null pointer exception… why was that??? please need answer….
Can we use loading image jar to load the images?
Great tutorial.
One question, though. I want to use a list view to view an XML feed in a fragment and all I can get is a blank list view. My code is below – where am I going wrong?
package com.macbloke.fragmentlistview;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.net.*;
import java.io.*;
import java.util.*;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.app.ListFragment;
public class Fragment3 extends Fragment {
// All static variables
static final String URL = “http://www.someurl.com/rss/news”;
// XML node keys
static final String KEY_ITEM = “item”; // parent node
static final String KEY_TITLE = “title”;
static final String KEY_DATE = “pubDate”;
static final String KEY_LINK = “link”;
static final String KEY_DESC = “description”;
ListView rssListView;
LazyAdapter rssAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment3, container, false);
// Download the data
ArrayList<HashMap> rssArticleList = new ArrayList<HashMap>();
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_TITLE);
// looping through all article nodes
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap map = new HashMap();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_DATE, parser.getValue(e, KEY_DATE));
map.put(KEY_LINK, parser.getValue(e, KEY_LINK));
map.put(KEY_DESC, parser.getValue(e, KEY_DESC));
// adding HashList to ArrayList
rssArticleList.add(map);
}
rssListView=(ListView)root.findViewById(R.id.list);
// Getting adapter by passing xml data ArrayList
rssAdapter=new LazyAdapter(getActivity(), rssArticleList);
rssListView.setAdapter(rssAdapter);
return root;
}
}
D’Oh!
Replaced:
NodeList nl = doc.getElementsByTagName(KEY_TITLE);
with:
NodeList nl = doc.getElementsByTagName(KEY_ITEM);
All is now well.
indeed a good tutorial…as i am a beginner in android..and i am running the tutorial its not working..so wud u please tell me how can i get it working…ASAP..
Good Tutorial….
Hi Adroid, use notifyDataSetInvalidated() may resolve you problem.
This is one great post. Very elaborated tutorial. Good work !
Dear, friend. I have pass this tutorial code to my GitHub ( https://github.com/EdwardLee03/android_tutorial/tree/master/ListView ), that is run OK. Good luck!
IDE: Android Studio
Android Version: 4.0.3
The following is difference point:
MusicActivity.java
protected void onCreate(Bundle savedInstanceState) {
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.build());
}
super.onCreate(savedInstanceState);
…
AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
Map song = (Map) adapter.getItem(position);
ImageView thumbImage = (ImageView) view.findViewById(R.id.thumb_image);
ImageLoader imageLoader = adapter.getImageLoader();
imageLoader.displayImage(song.get(Song.THUMB_URL), thumbImage);
adapter.notifyDataSetInvalidated();
}
}
};
LazyAdapter.java
public View getView(int position, View view, ViewGroup viewGroup) {
…
this.notifyDataSetChanged(); // Important!
return view;
}
ImageLoader.java
private Bitmap getBitmap(String imageUrl) {
…
// from Web
try {
URL url = new URL(imageUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(3000);
conn.setReadTimeout(10000);
conn.setInstanceFollowRedirects(true);
conn.setRequestMethod(“GET”);
conn.setDoInput(true);
conn.connect();
InputStream in = conn.getInputStream();
OutputStream out = new FileOutputStream(file);
IOUtils.copy(in, out);
in.close();
out.close();
conn.disconnect();
bitmap = decodeFile(file);
…
}
Hi mate,
Thank you for this post. I am getting this error:
org.apache.harmony.xml.dom.ElementImpl cannot be cast to android.renderscript.Element
Any suggestion?
Dont worry. I fixed it. It was me mistake. Your code it perfect.
I found you articles form here as well http://www.9android.net/custom-listview-image-text/. its horrible copying some ones articles and publish.
And what about if I want NOT to read the uploaded xml file, but to have a static xml file in the resources of my app and read the information from that??????
How can I implement this?????
Hi ravi,
i realized that, it cant functioned without internet connection. may i know how to make it functioned without internet connection? means that the images and the data will store in device maybe cache when first time access to the internet?
Thanks!
I was able to run this project. But when im trying to use my own xml file and my own url it seems like there’s a problem because it kept on stopping when i try to run it 🙁
exceptions in the logcat here :
1- HttpResponse httpResponse = httpClient.execute(httpPost);
2- String xml = parser.getXmlFromUrl(URL);
when i try to run the application unfortunately has stopped , please help me as i am new in android
Some remarks and best practices:
Don’t use right-pointing carets on line items: http://developer.android.com/design/patterns/pure-android.html
Don’t use SoftReference starting from Android 2.3 (better: use the LruCache from the Support Library): http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
Don’t use DOM (better: use the XmlPullParser as recommended by Google): http://developer.android.com/training/basics/network-ops/xml.html
Even better than XML: use JSON to reduce bandwidth consumtion/battery drainage and Google’s Volley networking library (as presented at the Google IO 2013): http://www.youtube.com/watch?v=yhv8l9F44qo and https://android.googlesource.com/platform/frameworks/volley/+/master
Don’t use Apache’s DefaultHttpClient starting from Android 2.3: http://android-developers.blogspot.de/2011/09/androids-http-clients.html
And finally: free resources and/or close streams always in a try-finally-construct.
Nice post. I like it and am using it.
However i have a question.
Instead of having an xml file, i want to use JSON data generated by a php with data as sampled below
success: 1,size: 3,
details: [
{
id : 1,
title : “Someone Like You”,
artise : “Adele”,
duration : “4:47”
thumb_url : “http://api.androidhive.info/music/images/adele.png”
},
{
id : 2,
title : “Someone Like You 2”,
artise : “Adele”,
duration : “4:47”
thumb_url : “http://api.androidhive.info/music/images/adele.png”
},
{
id : 3,
title : “Someone Like You 3”,
artise : “Adele”,
duration : “4:47”
thumb_url : “http://api.androidhive.info/music/images/adele.png”
}
]
And what is the question? How to generate JSON on server side? How to parse JSON on Android? Btw. the JSON example above isn’t valid: success and size are part of an JSONObject, so the whole fragment should be enclosed in curly braces.
is very easy!! men!
http://www.androidhive.info/2012/01/android-json-parsing-tutorial/
Can u pls tell me how i can implement the above project using tab navigation and onclick to display the individual item the tab should still be visible, i tried to do it but onclick creates a new activity and the tab goes missing.
thnx
(Unfortunately, app has stopped)…
I changed HttpPost to HttpGet in XMLParser class but it showing me above error in AVD.
plz help….
Thanks! 😀 this source worked!
Thank you Ravi for the detailed description on Android Listview , there’s one more video I found on youtube link: https://www.youtube.com/watch?v=0zQCv0Xb3pk
other users should find this useful, it helped me alot
hi ravi
if i get image manual from folder drawable-hdpi
i dont use URL = “http://api.androidhive.info/music/music.xml”
how i can do it?
help me
so u can use image button instead of image
Nirmal, I have used the imagebutton and facing issues with listitem random selection please take look on stackoverflow (http://stackoverflow.com/questions/18182601/listview-item-with-button-random-selection-while-scrolling) I posted for some help.
Hello. I would like to know if it is possible to have 400 elements in the xml file but only load 20 at a time in my application. Everytime my user reaches the bottom of the screen by scrolling, then the next 20 elements will be loaded and displayed. If this is possible, could You please supply the code needed. Thanks