I am stuck with text parsing in android. I have to read a textfile from url and display the contents in a listview. The contents of textfile include images and texts which are seperated by delimeters (like ^, ~,|,~^~^~). How can i remove the delimeters and display in a listview with the help of array adapter class? Can anyone help with the code?
I think array adapter might be two simplistic to do this. I mean you could use it, but it will end up being more complicated than the overall problem. So I think you can figure out how to parse the text file into let's say Text and Image objects (for you to define). Then you need an adapter. There are few places out there with some code snippets. I think SimpleAdapter might work well for this scenario.
For simplistic reasons let's say you have a layout for a list row with both an ImageView and a TextView
layout.xml
<LinearLayout xmlns:android="..."
android:layout_height="wrap_content"
android:layout_width="fill_parent"
>
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
and now we need to use an adapter to fill that
So the constructor is the meat of the class for clients to use.
SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
So if going with the assumption that the file is now parsed and we have a list of Objects
final Context context = ...;
final ListView listView = ...;
List<Object> objects = ...;
List<Map<String, Object>> mappings = new ArrayList<Map<String, Object>>(objects.size());
for(Object o : objects) {
HashMap<String, Object> data = new HashMap<String,Object>();
mappings.add(data);
if (o instanceof Image) {
data.put("image", ((Image)o).getBitmap());
data.put("text", "");
} else {
data.put("image", null);
data.put("text", String.valueOf(o));
}
}
SimpleAdapter adapter = new SimpleAdapter(context, mappings, R.layout.layout, new String[] { "image", "text"}, new int[] {R.id.image, R.id.text});
adapter.setViewBinder(new SimpleAdapter.ViewBinder() {
public boolean setViewValue (View view, Object data, String textRepresentation) {
if ( data instanceof Bitmap && view instanceof ImageView) {
// This is the main reason for the ViewBinder
ImageView imageView = (ImageView) view;
imageView.setImageBitmap((Bitmap)data);
return true;
} else if (view instanceof TextView) {
TextView textView = (TextView)view;
textView.setText(textRepresenation);
return true;
}
return false;
}
});
listView.setAdapter(adapter);
Now if you need help parsing out the file, well you need to provide a better description since a text file with a deliminator doesn't seem like it's enough to tag two different types of data.
But if it is and you have the memory just load it as a string and split(deliminator). Then for each item if you decide it is a String cool, keep it as a string and put it in the list. If you decide it is an Image decode the bitmap and put it in the list. plug that list into the object list in the code above and I think it's all set.
four digit numbers which are there are the images ...... i.e 2531, 2215, 6574, 7158.
Related
I have searched for answers but none seemed to help in my case.
App min sdk - API 10
Problem - slow ListView with images.
Reasons - data loading is on the UI thread (without images everything works smoothly) and probbavly the way I get the image resource id.
I have a ListView with two TextViews and an ImageView. I populate the ListView texts from an inserted database with SQLiteAssetHelper.
The table example:
specie_table
_id | LITHUANIAN | LATIN
0 | Paprastasis varnėnas| Sturnus vulgaris
1 | Juodasis strazdas | Turdus merula
Image loading
I have PNG images saved in the drawable folder.
I get the image resource id from the data in the database:
in specie_table.db "Regulus regulus" -> getImageName(name) returns "regulus_regulus" -> getResId(name, class) returns the drawable id -> setImage(ImageView, name) sets the resource for the ImageView
Should I make a different approach?
List_item.xml
<ImageView
android:id="#+id/icon"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="6dip"
android:layout_marginLeft="6dip"
android:layout_marginRight="10dip"
android:src="#drawable/ic_bird_grey"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="100dp"
android:orientation="vertical"
android:layout_toRightOf="#id/icon"
android:paddingTop="15dp">
<TextView
android:id="#+id/firstLine"
android:layout_width="match_parent"
android:layout_height="35sp"
android:text="Lithuanian title"
android:textSize="20sp"
/>
<TextView
android:id="#+id/secondLine"
android:layout_width="match_parent"
android:layout_height="24dp"
android:text="Latin title"
android:textSize="12sp" />
</LinearLayout>
SpecieCursorAdapter.java
public class SpecieCursorAdapter extends CursorAdapter {
SpecieCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
SpecieHolder holder = null;
holder = new SpecieHolder();
holder.imgIcon = (ImageView) view.findViewById(R.id.icon);
holder.txtTitle1 = (TextView) view.findViewById(R.id.firstLine);
holder.txtTitle2 = (TextView) view.findViewById(R.id.secondLine);
String nameLT = cursor.getString(cursor.getColumnIndex(SpecieTable.LIT_COL));
String nameLOT = cursor.getString(cursor.getColumnIndex(SpecieTable.LAT_COL));
holder.txtTitle1.setText(nameLT);
holder.txtTitle2.setText(nameLOT);
setImage(holder.imgIcon, nameLOT); //this makes everything laggy but i dont know how to make it as seperate thread.
}
static class SpecieHolder
{
ImageView imgIcon;
TextView txtTitle1;
TextView txtTitle2;
}
public void setImage(ImageView mainImage, String resource){ //these methods are for getting the image resource id from String (latin name).
int id = getResId(getImageName(resource), R.drawable.class);
if(id != -1)
mainImage.setImageResource(id);
else
mainImage.setImageResource(R.drawable.ic_bird_grey);
}
public int getResId(String resourceName, Class<?> c) {
try {
Field idField = c.getDeclaredField(resourceName);
return idField.getInt(idField);
} catch (Exception e) {
return -1;
}
}
public String getImageName(String resource){
String string = resource.toLowerCase();
string = string.replace(' ', '_');
string = string.replace(".", "");
return string;
}}
ListActivity.java
public class ListActivity extends AppCompatActivity {
public final static String EXTRA_MESSAGE = "bird info";
ListView listView;
ListActivity context = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
listView = (ListView)findViewById(R.id.listView);
Intent intent = getIntent();
Habitats habitat = Habitats.detachFrom(intent); //this is an enum type sent as String, converted back to enum.
Cursor cursor;
DatabaseAccess databaseAccess = DatabaseAccess.getInstance(this);
databaseAccess.open();
cursor = databaseAccess.getCursorByHabitat(habitat);
databaseAccess.close();
SpecieCursorAdapter adapter = new SpecieCursorAdapter(this, cursor);
listView.setAdapter(adapter);// how to seperate the image loading?
}
Examples would help very mutch! I will insert any needed extra code.
Try using Volley HTTP library for faster data transferring and image loading.
Volley is an HTTP library that makes networking for Android apps easier and most importantly, faster.
Follow these links
https://developer.android.com/training/volley/index.html
An example listview with image loading using Volley library
You can either use an existing lib as proposed by #abhilash or implement it on your own
In android displaying an item with an image in a listview works like this (example):
The listview needs to display item that is at position #35
The listview asks its adapter for a filled listviewitemview for the item that is at position #35
listviewitemview is either recycled from an old listviewitemview that is not visible any more or a new listviewitemview is created
each listviewitemview has a corresponding viewHolder with imageID and a bitmap-gui element
the image in the listviewitemview is initally loaded with a placeholder-image that will be visible until the imagload is complete.
the adapter initiates loading the image in the background (async-task) that gets the viewHolder with imageID.
when loading of the image in the background is finished the viewholder-gui element gets the loaded image.
GridView and ListView work the same way.
Here is a working example from APhotoManager. It contains a GalleryCursorFragment with the gridview with an embedded GridCellViewHolder
As suggested by #Neil and #shelll I used the Glide library. I modified my code accordingly:
added to the build.gradle
compile 'com.github.bumptech.glide:glide:3.7.0'
modified the bindView() method by changing
setImage(holder.imgIcon, nameLOT);
to
int imageId = getResId(getImageName(nameLOT), R.drawable.class);
if(imageId == -1)
imageId = R.drawable.ic_bird_grey;
Glide
.with(holder.imgIcon.getContext())
.load(imageId)
.into(holder.imgIcon);
For asynchronous images loading (and caching) use a library created for that, like Glide or Fresco
I am trying to create ListView with custom data set as follows:
String superType = "random1";
String superTypea = "random12";
String superType12 = "random2";
String superType_amount = "child1";
String childtype_calulated = "2323";
String superType_amount = "child2";
String childtype_calulated = "23223";
String superType_amount = "child2";
String childtype_calulated = "amount3";
Now I want to create ListView with this set of data how to do that?
Here is the list structure...
row1=superType |superType_amount |childtype_calulated
row2=superTypea |superType_amount |childtype_calulated
row3=superType12|superType_amount |childtype_calulated
Is there any solution of this?
It is absolutely possible to do this. First, I would recommend putting your data into a collection. It would be preferable to put them into an object and then a collection of those objects. From there you can add a ListView to your main layout, define a custom layout for your list items, and populate your ListView using an ArrayAdapter.
Here is a really good example of how you can do this well. It includes examples of loading data from an external source, which you don't need.
However, if you're getting into development now I would suggest you look into RecyclerView as well. RecyclerView is new and included in the AppCompat v7 library for use on pre-Lollipop Android. A RecyclerView will be a little more complicated to implement for a simple list but is significantly more scalable and efficient. I believe it is Google's intention to replace ListView with RecyclerView entirely in the future.
Here is a pretty simple introduction to making a list with RecyclerView.
EDIT
Using an ArrayAdapter with a ListView. First you need to create a model to store your data, some kind of class that you can put into a collection, for example:
public class Item {
public String title;
public String sub1;
public String sub2;
public void Item(String t, String s1, String s2) {
title = t;
sub1 = s1;
sub2 = s2;
}
}
Then you need to define the layout for the item in your list:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/sub1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/sub2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Then in you need to make your custom ArrayAdapter by extending the ArrayAdapter class:
public class ItemAdapter extends ArrayAdapter<Item> {
public ItemAdapter(Context context, ArrayList<Item> items) {
super(context, 0, items);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Item item = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_layout, parent, false);
}
TextView title = (TextView) convertView.findViewById(R.id.title);
TextView sub1 = (TextView) convertView.findViewById(R.id.sub1);
TextView sub2 = (TextView) convertView.findViewById(R.id.sub2);
title.setText(item.title);
sub1.setText(item.sub1);
sub2.setText(item.sub2);
return convertView;
}
}
Then all you need to do is create an instance of the adapter in your main class and attach your collection to it:
ArrayList<Item> data = new ArrayList<Item>();
ItemAdapter adapter = new ItemAdapter(this, data);
ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
This should populate your ListView with all the items that you need in your list. I haven't run any of this code so there might be one or two small bugs for you to fix.
So I want to create a listview that consists of more than a column. I already succeed called the database, but the layouting still not work. I think this is because the all my data are put in one array and its difficult to make them in three columns. anyone can find solution for me?
My program result is like this in listview:
John Doe 12 Argentina
Marilyn Rose 32 Russia
Annabella 19 United States
However what I want is more like this:
John Doe 12 Argentina
Marilyn Rose 32 Russia
Annabella 19 United States
From what I read, we will need 2 XMLs. One for listview, and another is for layouting (give space between text). And One .JAVA called adapter to connect my MainActivity.java and layouting XML.
add:
I already tried using two XMLs. one XML, lets call it main.XML is for calling ListView. And grid.XML, is where i put android:layout_alignParentLeft="true" (to create spaces).
I used MyAdapter.JAVA to convertview in grid.XML. and in MainActivity.JAVA i called MyAdapter. However my code in MainActivity became error when its connected it MyAdapter.
this was my code that gave error java.lang.RuntimeException. So I had to delete it.. more information about it, please check two last code...
MainActivity.java (error)
public static ArrayList<String> arraydealer = new ArrayList<String>();
MyAdapter bohwat = new MyAdapter(MainActivity.this, arraydealer);
lvcustom.setAdapter(bohwat);
And here is the code that is working well. It uses class MainActivity, AstraDB, and MySetGet, and main.XML. Other class thats not working is MyAdapter and grid.xml
This is how I called my database:
public class MainActivity extends Activity
{
public static ArrayList<String> arraydealer = new ArrayList<String>();
AstraDB astrahandler = new AstraDB(this);
Spinner spDealer;
ListView lvcustom;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lvcustom = (ListView)findViewById(R.id.custom_lv);
ShowListView();
}
private void ShowListView()
{
astrahandler.getAllDealer();
ArrayAdapter<String> adapt = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, arraydealer);
lvcustom.setAdapter(adapt);
}
}
This code of ArrayList in Activity and String name in AstraDB are very important to connect my MainActivity with the database but it seems this create trouble in layouting. because they are contained in ONE array
And this is function to get all data in my DB. its on AstraDB.java:
public List<MySetGet> getAllDealer()
{
List<MySetGet> info = new ArrayList<MySetGet>();
db = DBHelper.getReadableDatabase();
// Select All Query
String selectQuery = "SELECT * FROM Dealer";
cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
MySetGet lets = new MySetGet();
lets.setDealerID(Integer.parseInt(cursor.getString(0)));
lets.setDealerName(cursor.getString(1));
lets.setDealerOwner(cursor.getString(2));
lets.setDealerWil(cursor.getString(3));
String name = cursor.getInt(0) +
"\u00A0 "+ cursor.getString(1)+
"\u00A0 "+ cursor.getString(2)+
"\u00A0 "+ cursor.getString(3);
MainActivity.arraydealer.add(name);
//add
info.add(lets);
} while (cursor.moveToNext());
}
// closing connection
cursor.close();
db.close();
//return contentdealer;
return info;
}
The MySetGet in getAllDealer() connects with MySetGet.java where I put setter and getter so the data can become object. which is more like this:
public int getDealerID(){ return DealerID;}
public void setDealerID(int DealerID) { this.DealerID = DealerID; }
Code to connect other XML with Java but still gave error:
grid_dealer.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_height="wrap_content"
android:layout_width="50dp"
android:id="#+id/col1"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text=""/>
<TextView
android:layout_height="wrap_content"
android:layout_width="100dp"
android:id="#+id/col2"
android:layout_toRightOf="#id/col1"
android:layout_centerVertical="true"
android:text=""/>
important code in MyAdapter.java:
public class MyAdapter extends BaseAdapter
{
Context context;
ArrayList<MySetGet> dealerlist;
public MyAdapter(Context context, ArrayList<MySetGet>list)
{
this.context = context;
dealerlist = list;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
MySetGet yay = dealerlist.get(position);
//this is to customize the layout of the listview
if(convertView == null)
{
LayoutInflater inflater = null;
inflater = (LayoutInflater)context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.grid_dealer, null);
}
TextView tvID = (TextView)convertView.findViewById(R.id.col1);
tvID.setText(yay.getDealerID());
TextView tvName = (TextView)convertView.findViewById(R.id.col2);
tvName.setText(yay.getDealerName());
TextView tvOwner = (TextView)convertView.findViewById(R.id.col3);
tvOwner.setText(yay.getDealerOwner());
return convertView;
}
}
Please help me. I am very new to this. Is there a way to modify my code without changing too much on how I called my database? The class and XML below works fine in showing database, but didnt create a neat layout space between columns
Working class : AstraDB, MainActivity, MySetGet
Working XML : main.xml
Im sorry, if the post becomes longer. I want to clarify several things so that there is no misunderstanding.
you can use android:layout_weight="" for better arrangement of views
Using SimpleCursorAdapter is the ideal solution in your case. Please checkout a tutorial here that will take you through the steps in achieving what you want.
In simple_list_item_1 layout if you arrange items relative to each other you will get the result what you are getting now. If you want proper formatting, relate the elements to left, center and right using android:layout_alignParentLeft="true", android:centerHorizontal="true" and android:layout_alignParentRight="true" respectively
I have followed various "how to" examples to the letter (or so I thought), but I still can't get my custom ListAdapter to work. I have a dialog with a list view containing strings which are references to an array of objects (of class "Notam"). I want to set the colour of each list item according to an attribute of the referenced object.
(Before you read my code, I have a quirk that the braces must line up or I can't see where the blocks are. I don't like the convention of putting an opening brace at the end of the same line.)
This is the code for the custom class (just as a test I am trying to set the text colour of each item to magenta):
private class GotoAdapter extends ArrayAdapter<String>
{
private ArrayList<String> items;
public GotoAdapter(Context context, int textViewResourceId, ArrayList<String> items)
{
super(context, textViewResourceId, items);
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
if (v == null)
{
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.goto_row, null);
}
String s = items.get(position);
if (s != null)
{
TextView tt = (TextView) v.findViewById(R.id.text1);
if (tt != null)
{
String s1 = (String)tt.getText(); // this is always an empty string!
tt.setTextColor(0xFF00FF); // this has no effect!
}
}
return v;
}
}
String s has the displayed text as expected (except you can't see it on the screen) when using this derived class), but the text in the returned TextView is always an empty string, and setting the colour has no effect.
This is the code that displays the dialog when a "Goto" button is clicked in my main view:
mGotoButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
// The pre-loaded array gets round a problem which I read about somewhere else
// (the ArrayList gets cleared again below)
String[] array = {"one", "two", "three"};
ArrayList<String> lst = new ArrayList<String>();
lst.addAll(Arrays.asList(array));
// custom dialog
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.goto_dialog);
dialog.setTitle("Choose Notam");
// Create the list view and adapter
final ListView list = (ListView) dialog.findViewById(R.id.goto_list);
// If I replace this reference to my custom adapter...
final GotoAdapter adapter = new GotoAdapter
(mContext, R.layout.goto_row, lst);
// ... with this normal one, everything works!
// (but of course now I can't get access to the objects.)
// final ArrayAdapter<String> adapter = new ArrayAdapter<String>
// (mContext, R.layout.goto_row, lst);
list.setAdapter(adapter);
// Populate the adapter
adapter.clear(); // first clear the silly preset strings
// Notam is my object class.
// Spine.mNotamsDisplayed is a public static NotamArray.
// class NotamArray extends ArrayList<Notam>
// Spine is my main activity where I keep my global (app-wide) stuff.
for (Notam notam : Spine.mNotamsDisplayed)
{
// This gets the reference string from the Notam object.
// This is what goes into the list.
String s = notam.getReference();
adapter.add(s);
}
// Sort into alphabetical order
adapter.sort(new Comparator<String>()
{
public int compare(String arg0, String arg1)
{
return arg0.compareTo(arg1);
}
});
list.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> a, View v, int pos, long id)
{
String s;
int i;
s = (String)a.getItemAtPosition(pos);
// This static function returns the index in Spine.mNotamsDisplayed
// which is referenced by the reference string s.
// I have to do this because I lost the one-for-one correlation of page
// indexes with list view entries when I did the sort.
i = NotamArray.findNotamIndexByReference(Spine.mNotamsDisplayed, s);
if (i >= 0)
{
// This is what the Goto button and dialog is all about: this
// just moves my main view's pager to the page that was selected.
mPager.setCurrentItem(i);
}
dialog.dismiss();
}
});
dialog.show();
}
});
This is my xml for the dialog (goto_dialog.xml):
<?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="fill_parent" >
<ListView
android:id="#+id/goto_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
And this is my xml for the list view row (goto_row.xml):
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#00FF00"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceMedium"
android:padding="2dp"
android:textSize="20dp"
/>
(I set the text colour to green so I could see that this bit was working if I used the standard list view adapter. (Sure enough the text of every entry was green. However no text could be seen if I used my custom adapter, although it was there - I assume black on black.)
There must be someone out there who can spot what must be a trivial error I have made - please!
From what I read, it seems like you want to set the text color of every list item to match the color you have in your array.
I want to set the colour of each list item according to an attribute of the referenced object.
However, your initial array is set as
String[] array = {"one", "two", "three"};
So this will lead to problems later when you are dynamically setting the text color based on your array. But I'm sure you meant to change that later.
When you use a standard array adapter, it just shows the items in the array as a text, that's why:
if I used the standard list view adapter. (Sure enough the text of every entry was green. However no text could be seen if I used my custom adapter
To see if your custom adapter is working (changing color), you can just start off by adding one line to your TextView of goto_row.xml file:
android:text="Test String"
Now it will show "Test String" with different colors, and the
String s1 = (String)tt.getText();
above line will get "Test String"
I found the trivial error that I hinted at at the end of my question. It was this line in the custom adapter:
tt.setTextColor(0xFF00FF);
It seems that 0xFF00FF is not a valid colour value, which is why I saw nothing on the screen.
Changing that to:
tt.setTextColor(Color.rgb(255, 0, 255);
fixes the problem, and the default green colour is changed to magenta, and I can set the text to the value I want. So I can now set the individual row colours to what they need to be.
Thanks to #LukasKnuth and #tigerpenguin for pointing me in the right direction.
Basically I'm trying to make a contact list like the one provided by Android. When populating the listview with items, using a SimpleCursorAdapter you can easily get all the names to appear in the R.id.textview of each item:
private void fillData() {
mCursor = mDbAdapter.fetchAllContacts();
startManagingCursor(mCursor);
String[] from = new String[] {DBAdapter.KEY_NAME};
int[] to = new int[] {R.id.contact_name};
SimpleCursorAdapter contacts = new SimpleCursorAdapter(this, R.layout.contact_view, mCursor, from, to);
this.setListAdapter(contacts);
}
Something like that. I've searched and found sample code for both getting images from online, or displaying a set number of images in the items (for instance you know you have 5 items so you get the 5 matching images). But I really don't know where I'd begin on getting images from my SD card, and displaying them in the proper item. The images are named according to the id of the contact, so I do have the means to call the proper image.
A push in the right direction would be much appreciated, thank you!
EDIT: #Jeff Gilfelt gave a great answer, but I went ahead and spoke too soon when saying I could figure out the rest on my own... haha. I have a default image declared in the xml for the contacts like Android does. When I implement the new Adapter, it like compresses the items into nothing, I figure because it finds an empty bitmap # that location. So I did the following:
#Override
public void setViewImage(ImageView v, String id) {
File root = Environment.getExternalStorageDirectory();
File path = new File(root, "path/images/thumbs/"+id+".jpg");
if(path.exists()) {
Bitmap bitmap = BitmapStatic.getThumb(id);
v.setImageBitmap(bitmap);
}
else {
super.setViewImage(v, id);
}
}
But this doesn't help either. Any ideas?
EDIT2: Figured out the above problem. Simply go like this:
else {
Resources res = mContext.getResources();
Drawable drawable = res.getDrawable(R.drawable.default);
v.setImageDrawable(drawable);
}
Hope this helps others! Remember for this solution you will have to add a Context member var, and the line mContext = context in the constructor.
Create a subclass of SimpleCursorAdaptor and override the setViewImage method such that it constructs the path to the appropriate file on the SD card from the id you feed it, then use BitmapFactory.decodeFile to create a Bitmap you use for the image view you are binding to:
public class MySimpleCursorAdapter extends SimpleCursorAdapter {
public MySimpleCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
}
#Override
public void setViewImage(ImageView v, String id) {
String path = "/path/to/sd/card/" + id + ".png";
Bitmap b = BitmapFactory.decodeFile(path);
v.setImageBitmap(b);
}
}
Then add your contact id from the cursor and the view id of your ImageView to the to/from arrays that you pass to the adapter. Example:
private void fillData() {
mCursor = mDbAdapter.fetchAllContacts();
startManagingCursor(mCursor);
String[] from = new String[] {DBAdapter.KEY_NAME, DBAdapter.ID};
int[] to = new int[] {R.id.contact_name, R.id.contact_image};
MySimpleCursorAdapter contacts =
new MySimpleCursorAdapter(this, R.layout.contact_view, mCursor, from, to);
this.setListAdapter(contacts);
}
Read this tutorial http://developer.android.com/guide/topics/data/data-storage.html
and this post http://www.brighthub.com/mobile/google-android/articles/64048.aspx
Have a two dimensional arraylist, the first element containing the contact name and the second containing the image.After you read the images into a bitmap, save the bitmap in your contacts arraylist. Have a custom arrayAdapter which contains a textView and a imageView as its row elements, set the contact name and image in the getView() of the array adapter. Refer this post for custom listViews http://www.androidpeople.com/android-custom-listview-tutorial-example/
This should help you get going.
You should read up on the external storage chapter on the Android development guide. By calling getExternalFilesDir() you will get a filepath to your SD card.
As a strategy, if you navigate to the folder containing the images and just pass in the ID of your contact to locate the file, you can load this into a data structure.
You can then create a custom adapter passing in the data structure containing your images. This will result in your ListView to contain only the images of your contacts.
This is just to give you a head start!
You don't need to create a subclass of SimpleCursorAdapter, just create a ViewBinder which handles the set up of the your image for each row.
ViewBinder.setViewValue will be called for all Views in your row (as specified in your layout xml) so make sure you return false for any view which is not an instance of ImageView.
ViewBinder viewBinder = new ViewBinder(){
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (view instanceof ImageView){
ImageView imageView = (ImageView) view;
String imageFilename = cursor.getString(columnIndex);
imageView.setImageURI(imageFilename);
return true;
}
return false;
}
};
cursorAdapter.setViewBinder(viewBinder);