Reputation: 177
I have a ListView that represents an order list, and a listAdapter that sets recieved data from DB to the listView, and I want to dynamically do:
*(with paint I mean setBackground color of item)
**(Order have an attribute "state" to know if they are Started or not)
Currently I'm doing this only when buttons are pressed, and I want to also update UI and repaint items when orders are received and if one order is started paint it
some code of OrdersActivity:
private void updateOrders() {
if (!listItemIsSelected) {
orderAdapter.clear();
orderAdapter.notifyDataSetChanged();
populateListView();
} else {
debugLog("item is selected, list not updated");
}
}
private void populateListView() {
try {
// Read items from server
Log.d("LSO", "Reading from Database");
ListObtainer listObtainer = new ListObtainer(this);
listObtainer.getTmOfsDTOList(user, orderAdapter); // this method returns list of objects from DB and populates adapter
} catch (Exception e) {
e.printStackTrace();
}
configureAdapter();
}
private void configureAdapter() {
// Configure listview
listView = (ListView) findViewById(R.id.lvOrdenes);
listView.setAdapter(orderAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
try {
OrderRO orderRO = (OrderRO) parent.getItemAtPosition(position);
listItemIsSelected = true;
lastChildSelected = currentChildSelected;
currentChildSelected = (View) listView.getChildAt(position);
uptadteUI();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void uptadteUI() {
try {
if (lastChildSelected != null) {
lastChildSelected.setBackgroundColor(getResources().getColor(R.color.transparent));
}
if (orderIsStarted) { // Block scroll, disable start, paint item
disableIniciarOrden();
disableBotonSalir();
enableTerinarOrden();
currentChildSelected.setBackgroundColor(getResources().getColor(R.color.light_orange));
listView.setEnabled(false);
} else {// if there is no started order
listView.setEnabled(true);
enableBotonSalir();
disableTerminarOrden();
if (listItemIsSelected) { // enable start, paint item
enableIniciarOrden();
currentChildSelected.setBackgroundColor(getResources().getColor(R.color.light_green));
}
}
} catch (Exception e) {
Log.e("error", "error updating UI" + e);
}
}
public class UpdateOrdersAsync extends AsyncTask {
@Override
protected Object doInBackground(Object[] params) {
while (updateService == true) {
try {
Thread.sleep(180000);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress();
}
return null;
}
@Override
protected void onProgressUpdate(Object[] values) {
//super.onProgressUpdate(values);
debugLog(". . . calling list update");
updateOrders();
}
}
This looks to me very dirty and I have a problem: if the DB changed and Adapter is updated I can receive an Order already started and I don't know how to paint it from activity, I'm new using custom adapters and I'm confused on what I should do, I can paint the started orders directly in adapter but this breaks the logic I already did in activity(posted code) because I don't know from the activity which orders are started(check the attribute of one item from activity).
Sorry if the question is difficult to understand or poorly explained, It's difficult to me to transmit my problem
Upvotes: 0
Views: 106
Reputation: 3313
first, you have to fill the data source that ListView gets the data from, and then, call the method:
listView.getAdapter().notifyDataSetChanged();
then the list will get all the new data filled in the data source
Upvotes: 0
Reputation: 1818
So, you want to update the list of items on a ListView when you receive more information, correct? I have modified your code a bit to enhance readability.
Lets say you have a list with the items :
List<Items> listItems = new List<Items>;
listItems.add(item1);
listItems.add(item2);
listItems.add(item3);
with an adapter associated to it. Then you just associated the adapter to your listView like :
ArrayAdapter<String> orderAdapter = new ArrayAdapter<String>(this,android.R.layout.listem_item, listItems);
listView.setAdapter(orderAdapter);
Now you have all your items. Lets say those items change like this :
listItems.remove(item1); // you remove item1
listItems.add(item4); // and you add item4
Now you want to inform the adapter that you have changed the base data.
You can do it like :
listView.getAdapter().notifyDataSetChanged();
What I strongly recommend is that you associate the background color to the Model instace of the row instead of the its view. This way, if the view gets re-drawn, the information will still be store inside the Model.
public class OrderRo
...
String color = "red";
boolean isOrderStarted = false;
...
...
public boolean isOrderStarted(){
return isOrderStarted;
}
public void setIsOrderStarted(boolean isOrderStarted){
this.isOrderStarted = isOrderStarted;
}
public String getColor(){
return this.color;
}
public void setColor(String color){
this.color = color;
}
....
and
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
try {
OrderRO orderRO = listView.getAdapter().getItem(position);
orderRO.setColor("orange");
orderRO.setIsOrderStarted(true);
uptadteUI(orderRO, (View) listView.getChildAt(position));
} catch (Exception e) {
e.printStackTrace();
}
}
});
private void uptadteUI(OrderRO order, View selectChild) {
try {
if (selectChild != null) {
selectChild.setBackgroundColor(getResources().getColor(R.color.transparent));
}
if (order.isOrderStarted()) { // Block scroll, disable start, paint item
disableIniciarOrden();
disableBotonSalir();
enableTerminarOrden();
selectChild.setBackgroundColor(getResources().getColor(R.color.light_orange));
listView.setEnabled(false);
} else {// if there is no started order
listView.setEnabled(true);
enableBotonSalir();
disableTerminarOrden();
if (listItemIsSelected) { // enable start, paint item
enableIniciarOrden();
selectChild.setBackgroundColor(getResources().getColor(R.color.light_green));
}
}
} catch (Exception e) {
Log.e("error", "error updating UI" + e);
}
}
Upvotes: 1
Reputation: 1637
Add status attribute to OrderRO
class like started, pressed etc. In your adapter, where inflate the listview items check this status and set view color. On onItemClick
method change item status and call adapter.notifyDataSetChanged()
.
Upvotes: 0
Reputation: 26
I think you should keep state in your OrderRO class.And when state is changed,call notifyDataSetChanged.In getView method,paint view with different colors according to the state in OrderRO.
Upvotes: 0