I want to set the background color depending on the data for the row of the ListView. I implemented a ListActivity but I dont know how to get notified the load is completed so that I can access the rows of the ListView.
public class RouteList extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.route_list);
CommuteDb db = new CommuteDb(this);
Cursor cursor = db.getRouteList();
ListAdapter adapter = new SimpleCursorAdapter(this, // Context.
R.layout.route_row, //row template
cursor, // Pass in the cursor to bind to.
new String[] { BaseColumns._ID, "Name" }, //Columns from table
new int[] { R.id.id, R.id.name }, //View to display data
0); //FLAG_REGISTER_CONTENT_OBSERVER
setListAdapter(adapter);
ListView listView = (ListView) findViewById(android.R.id.list);
Log.i("RouteList","listView.getChildCount()=" + listView.getChildCount()); //returns always 0
//Loop will not execute because no row yet
for (int i=0; i < listView.getChildCount(); i++) {
View rowView = listView.getChildAt(i);
Log.i("RouteList",rowView.getClass().getName());
rowView.setBackgroundColor(0x88ff0000);
}
If I execute this loop later (for instance on user's request) I am able to get each row and assign the color I want. However I need to do this automatically after data are loaded in ListView.
Thanx for the hint guys.
It works after modifying the code this way:
I added a custom adapter (RouteAdapter) derived from SimpleCursorAdapter:
private class RouteAdapter extends SimpleCursorAdapter {
public RouteAdapter(Context context, int layout, Cursor c,
String[] from, int[] to, int flags) {
super(context, layout, c, from, to, flags);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//Let the default getView do the job (inflate the row layout and set views to their values from database
View view = super.getView(position, convertView, parent);
//Get the resulting view (route_row) and do custom loading
TextView isOffer = (TextView) view.findViewById(R.id.isOffer);
if (isOffer.getText().equals("0"))
view.setBackgroundColor(0x8800ff00); //seek=green
else
view.setBackgroundColor(0x88ff0000); //offer=red
return view;
}
}
Then in my original code I just replaced SimpleCursorAdapter by RouteAdapter:
ListAdapter adapter = new RouteAdapter(this, // Context.
Related
I'm creating an android book that has 6 season whithin sqlite database but listview take several seconds to load data.
I know that I sholud implement onscroll methode to do this,but I don't know how manage it
my code is:
public class list_story extends ListActivity{
private database db;
private String[] Name;
private String sea;
Context c;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.list_story);
db = new database(this);
Bundle ex = getIntent().getExtras();
sea = ex.getString("sea");
refresh();
setListAdapter(new AA());
}
class AA extends ArrayAdapter<String>{
public AA(){
super(list_story.this,R.layout.row_list,Name);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater in = getLayoutInflater();
View row = in.inflate(R.layout.row_list, parent,false);
txt.setText(Name[position]);
return (row);
}
}
private void refresh(){
db.open();
int s =db.Story_count("content", sea);
Name = new String[s];
Fav=new String[s];
Tasvir=new String[s];
Scientific=new String[s];
English=new String[s];
for (int i = 0; i < s; i++) {
Name[i]=db.Story_display(i, sea, "content", 1);
Fav[i]=db.Story_display(i, sea, "content", 4);
Tasvir[i]=db.Story_display(i, sea, "content", 5);
Scientific[i]=db.Story_display(i, sea, "content", 6);
English[i]=db.Story_display(i, sea, "content", 7);
}
db.close();
}
}
Basically every time you try to inflate a new view, you will literally inflate a new view. The problem with that is if you have 100 plus items to put into the list view, well that's 100+ views you've defined. That's extremely inefficient. Use the ViewHolder pattern for ListView, or use a the RecyclerView. Better yet use the RecyclerView. There's a lot of information on the web for both of those. Just look up "how to use ViewHolder in a list view"
If you are only using a single text field and a db i would recomend you to use a simpleCursorAdapter :
db = new DBAdapter(this);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1,
db.getAllTitles(),
new String[] { "title" },
new int[] { android.R.id.text1 });
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(adapter);
If you have further questions check this great example https://thinkandroid.wordpress.com/2010/01/09/simplecursoradapters-and-listviews/
In my application I read data from database, put it into cursor and pass it to ListView using adapter. These data are numbers from 1 to 12, but I need them to be presented in the ListView as names of months. How and on which step of reading and displaying these data can I intercept them and change from numbers to text?
You can modify the data, right before it the adapter sets the text to your TextView. It'll be done in adapter's getView method.
Try this
import java.text.DateFormatSymbols;
public String getMonth(int month) {
return new DateFormatSymbols().getMonths()[month-1];
}
You may right a custom adapter for that!. If your data is cursor object you can write custom adapter class extending from "CursorAdapter". Other wise you can extend from "BaseAdapter".
call it by:
ShowListCursorAdapter adapter = new ShowListCursorAdapter(getActivity(), R.layout.fragment_list_detail, cursor,
columns, views, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
getListView().setAdapter(adapter);
In custom Adapter extends cursorAdapter:
Constructor:
public ShowListCursorAdapter(Context context, int layout, Cursor cursor, String[] columns, int[] views, int flag) {
super(context,cursor,flag);
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mCursor = cursor;
mLayout = layout;
mTo = views;
mFrom = columns;
}
Implement 2 methods in CursorAdapter.
#Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {//This will be called once
mView = mInflater.inflate(mLayout, viewGroup, false);
return mView;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {//This is called no.of row times
for(int i = 0; i< mTo.length;i++) {//If you have single column no need of for loop
TextView content = (TextView) view.findViewById(mTo[i]);
content.setText(mCursor.getString(mCursor.getColumnIndex(mFrom[i])));////here you can convert number to month and display
}
}
Sorry if this seems stupid, but I'm sort of new to all this stuff. The situation is that i have a lot of data stored in a database that I need to present in list views. The first view pulls 15 rows and uses only two out of 14 columns in the db. I use this adapter to present this in a list view:
private class CustomListAdapter extends SimpleCursorAdapter {
private Cursor cursor;
public CustomListAdapter(Context context, int textViewResourceId, Cursor cursor, String from[], int to[]) {
super(context, textViewResourceId, cursor, from, to);
this.cursor = cursor;
}
#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.row, null);
}
cursor.moveToPosition(position);
if (cursor != null) {
TextView lt = (TextView) v.findViewById(R.id.lefttext);
TextView rt = (TextView) v.findViewById(R.id.righttext);
if (lt != null) {
lt.setText(/*cursor.getString(cursor.getColumnIndex(EwstableContentProvider.TIMESTAMP))*/cursor.getString(cursor.getColumnIndex(EwstableContentProvider._ID))); }
if (rt != null){
rt.setText(cursor.getString(cursor.getColumnIndex(EwstableContentProvider.TOTALEWS)));
}
}
return v;
}
}
}
This may even be stupid, but at least it works.
Now, on the next activity i need to present data from all the columns, but only from the row that the user selected on the previous activity. I was looking at putting it inside a list view like the one from http://www.softwarepassion.com/android-series-custom-listview-items-and-adapters/, which is also where i modified the adapter from.
this way, i would put data from two fields in the db into each item in the list view. this is perfect, it would be one data point and a comment that goes with it.
The problem is that at this point i only have one row in the cursor, so the bit after #Override is only executed once, so instead of the 7 items in the list view, I get one.
I'd really appreciate any help, even if it is to do it in an entirely different way.
Assuming that you know the number of columns, could you just use a for loop to iterate through all the columns, storing each string into a String array.
String[] arr = new String[cursor.getColumnCount()];
for(int i=0; i < cursor.getColumnCount(); i++)
arr[i] = cursor.getString(i);
Then use the String[] with an ArrayAdapter for your listview.
UPDATE: sorry didn't read the question carefully; see other answer.
You need to use a cursor adapter. I recommend the SimpleCursorAdapter (example below).
You will also need to change the "from" parameter to the column name (key) for the text you want displayed. An example from my personal code is below. This line,
new String[] { DBAdapter.KEY_NAME },
is the important one. It is defined in DBAdapter to be:
public static final String KEY_NAME = "name";
which matches the name of the first column in my own database.
DBAdapter dba = new DBAdapter(this);
dba.open();
Cursor c = dba.list_listMode();
SimpleCursorAdapter ca = new SimpleCursorAdapter(
this,
R.layout.list_item,
c,
new String[] { DBAdapter.KEY_NAME },
new int[] { R.id.list_item_text });
lv.setTextFilterEnabled(true);
lv.setAdapter(ca);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id_long) {
I have a ListFragment that is being called from a Tab Navigation in an ActionBar. I have a custom adapter to display two different textviews for each list item. I'm having trouble implementing my onItemClickListener. Here is my ListFragment code:
public class MaterialsListFragment extends SherlockListFragment {
public ERGAdapter db;
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.portrait_material_view, container, false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create new DBAdapter
db = new ERGAdapter(getActivity());
// ---- get all records
db.open(); // Open database
// Get all of the notes from the database and create the item list
Cursor c = db.getAllRecords();
String[] from = new String[] { ERGAdapter.KEY_IDNO, ERGAdapter.KEY_MATERIAL };
int[] to = new int[] { R.id.idno, R.id.materials };
// Now create an array adapter and set it to display using our row
MyListAdapter materials = new MyListAdapter(getActivity(), R.layout.list_cell, c, from, to);
setListAdapter(materials);
// get the list view and the set the listener
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Log.i("MATERIAL"," - position: "+Integer.toString(position));
}
});
}
public class MyListAdapter extends SimpleCursorAdapter {
public MyListAdapter(Context context, int layout, Cursor cursor, String[] from, int[] to) {
super(context, layout , cursor, from, to);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Create the idno textview with background image
TextView idno = (TextView) view.findViewById(R.id.idno);
String unidno = String.format("%1$.0f", cursor.getDouble(3));
idno.setText(unidno);
// create the material textview
TextView materials = (TextView) view.findViewById(R.id.materials);
materials.setText(cursor.getString(1));
}
}
}
I'm getting a fatal exception with this line: ListView lv = getListView();
Here is the pertinent logcat:
05-25 16:32:45.802: E/AndroidRuntime(660): Caused by: java.lang.IllegalStateException: Content view not yet created
05-25 16:32:45.802: E/AndroidRuntime(660): at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328)
05-25 16:32:45.802: E/AndroidRuntime(660): at android.support.v4.app.ListFragment.getListView(ListFragment.java:222)
05-25 16:32:45.802: E/AndroidRuntime(660): at com.cca.ergpro.MaterialsListFragment.onCreate(MaterialsListFragment.java:80)
I think that I need to make it part of my custom CursorAdapter, but I'm not sure how to proceed. Any suggestions would be greatly appreciated.
I was able to get it working using the solution from this question:
Creating custom simple cursor adapter
This is my code where im fetching the values from database a displaying them in their respective fields i have designed a customlist where i have 5 textviews and 3 buttons
My problem is how to make those buttons clickable and i want that row information in the next activity.
cursor = db.rawQuery("SELECT * FROM JOB_LIST_DISPLAY_TABLE",null);
adapter = new SimpleCursorAdapter(this,R.layout.customlist,cursor,
new String[] {"JOB_TITLE","JOB_START_DATE","JOB_END_DATE","JOB_STATE","JOB_SPECIALITY","JOBPERMANENT",},
new int[] {R.id.Title,R.id.StartDate,R.id.EndDate,R.id.State,R.id.Speciality,R.id.JobType});
listview.setAdapter(adapter);
Each Row in a listview consists these elements
Screen looks like below
TextView1
Textview2
Textview3
Textview4
Textview5
Button1 Button2 button3
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
where position is row number
If I have not misunderstood you have to implement
onListItemClick that have as parameter
position The position of the view in the list
then you can you
youradapter.getItem(position)
see the doc at:
getItem(int)
listview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Log.d("list item position","="+position);
/* If you want this position in next activity then put it in bundle extra and start the activity,ten fetch it from bundle in the next activity*/
}
});
In order to catch events from the List items, you're going to have to create a custom Adapter. Within the adapter you'll populate the data in the controls yourself. You can also register for events with those controls. To tell which row the control is from, you'll need to set the tag on the controls with either the row # or cursor value. You can then get that back from the control when an event is triggered.
Here is an example of a custom adapter. It might point you in the right direction:
public class MyAdapter extends ResourceCursorAdapter {
private static final class ViewHolder {
public TextView mControl1;
public TextView mControl2;
}
private int mData1Col;
private int mData2Col;
public MyAdapter(Context context, Cursor cursor) {
super(context, R.layout.history_entry, cursor, true);
// Store cursor column indexes for efficiency.
if ( null != cursor ) {
mData1Col = cursor.getColumnIndex(DATA1);
mData2Col = cursor.getColumnIndex(DATA2);
}
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// This method creates new views as needed. Most controls only create
// views they need to fill the visible display area, then they re-use them.
// Let the parent create the view we specified at construction.
View view = super.newView(context, cursor, parent);
// For efficiency, use a view holder to reference the child views.
// These find operations can be expensive so do it just once.
ViewHolder vh = new ViewHolder();
vh.mTitle = (TextView) view.findViewById(R.id.control1);
vh.mAt = (TextView) view.findViewById(R.id.control2);
view.setTag(vh);
return (view);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// This methods binds the specified cursor data with the provided view.
// Use the ViewHolder to find the controls we need and populate them.
ViewHolder vh = (ViewHolder) view.getTag();
// Populate the controls with the current cursor.
// Register to receive events from the controls.
// Set the tag on your controls with the cursor position so you
// have that info when the item is selected.
}
#Override
public Cursor swapCursor(Cursor newCursor) {
// Store column indexes for efficiency.
if (null != newCursor) {
mData1Col = newCursor.getColumnIndex(DATA1);
mData2Col = newCursor.getColumnIndex(DATA2);
} else {
mTitleCol = 0;
mResolvedAtCol = 0;
}
return (super.swapCursor(newCursor));
}
}