I have a listview
with edittext
widgets inside each row. I use a viewholder
inside my custom adapter
to keep track of all the views.
But my problem is that when i input a value inside my edittext
, pause until my screen times out, when you unlock the phone while still in the same activity
,the default edittext
value is refilled, overwriting my edits.
I followed this suggestion here (when listview scroll that time edittext set default value) considering that maybe i am not using the viewholder
right but still facing the same issue. It's like getView()
keeps getting called, completely redrawing my views.
Any ideas/suggestions on a workaround?
package com.shop.shopOfficer;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
import com.shopOfficer.R;
import java.util.ArrayList;
import java.util.List;
/**
* Created by steve on 2/15/16.
*/
public class ProductListAdapter extends BaseAdapter implements Filterable {
List<ProductModel> mStringFilterList;
ValueFilter valueFilter;
private Activity activity;
private LayoutInflater inflater;
private List<ProductModel> modelItems;
private AddRemoveProductInterface myActivityInterface;
public ProductListAdapter(Activity activity, List<ProductModel> modelItems, AddRemoveProductInterface myActivityInterface) {
this.activity = activity;
this.modelItems = modelItems;
mStringFilterList = modelItems;
this.myActivityInterface = myActivityInterface;
}
@Override
public int getCount() {
return modelItems.size();
}
@Override
public Object getItem(int location) {
return modelItems.get(location);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolderItem viewHolder;
if (convertView == null) {
// inflate the layout
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.product_item_row, null);
// well set up the ViewHolder
viewHolder = new ViewHolderItem();
viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tv2);
viewHolder.price = (TextView) convertView.findViewById(R.id.price);
viewHolder.p = (TextView) convertView.findViewById(R.id.p);
viewHolder.minus = (Button) convertView.findViewById(R.id.minus);
viewHolder.add = (Button) convertView.findViewById(R.id.add);
viewHolder.quantity = (EditText) convertView.findViewById(R.id.num);
viewHolder.quantity.addTextChangedListener(new MyTextWatcher(convertView, position));
viewHolder.add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//get the value of edittext
//add one item
int added_item = Integer.parseInt(viewHolder.quantity.getText().toString()) + 1;
viewHolder.quantity.setText("" + added_item);
}
});
viewHolder.minus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int removed_item = Integer.parseInt(viewHolder.quantity.getText().toString()) - 1;
if (removed_item >= 0) {
viewHolder.quantity.setText("" + removed_item);
} else {
}
}
});
// store the holder with the view.
convertView.setTag(viewHolder);
} else {
// we've just avoided calling findViewById() on resource everytime
// just use the viewHolder
viewHolder = (ViewHolderItem) convertView.getTag();
}
// object item based on the position
final ProductModel m = modelItems.get(position);
viewHolder.tvTitle.setText(m.getname());
viewHolder.price.setText("(" + m.getPrice() + ")");
viewHolder.p.setText(m.getPrice());
viewHolder.quantity.setTag(m);
viewHolder.quantity.setText(String.valueOf(m.getTQuantity()));
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(inflater.getContext(), EditProduct.class);
intent.putExtra("name", m.getname());
intent.putExtra("price", m.getPrice());
intent.putExtra("description", m.getproductDesc());
intent.putExtra("image_url", m.getImage_url());
inflater.getContext().startActivity(intent);
}
});
return convertView;
}
@Override
public Filter getFilter() {
if (valueFilter == null) {
valueFilter = new ValueFilter();
}
return valueFilter;
}
private class ValueFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<ProductModel> filterList = new ArrayList<>();
for (int i = 0; i < mStringFilterList.size(); i++)
if ((mStringFilterList.get(i).getname().toUpperCase())
.contains(constraint.toString().toUpperCase()) ||
(mStringFilterList.get(i).getproductDesc().toUpperCase())
.contains(constraint.toString().toUpperCase())) {
ProductModel m = new ProductModel(mStringFilterList.get(i)
.getname(), mStringFilterList.get(i)
.getproductId(), mStringFilterList.get(i)
.getImage_url(), mStringFilterList.get(i)
.getPrice(), mStringFilterList.get(i)
.getproductDesc());
filterList.add(m);
}
results.count = filterList.size();
results.values = filterList;
} else {
results.count = mStringFilterList.size();
results.values = mStringFilterList;
//show no results were picked
//(myActivityInterface).onSearchEmpty("No results found");
}
return results;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
//if(results)
modelItems = (List<ProductModel>) results.values;
if (modelItems.size() > 0) {
notifyDataSetChanged();
} else {
(myActivityInterface).onSearchEmpty("No results found");
}
}
}
static class ViewHolderItem {
TextView tvTitle, price, p;
Button add, minus;
EditText quantity;
}
private class MyTextWatcher implements TextWatcher {
View view;
int position;
public MyTextWatcher(View convertView, int position) {
this.view = convertView;
this.position = position;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
EditText qtyView = (EditText) view.findViewById(R.id.num);
// ProductModel m = modelItems.get(position);
String qtyString = s.toString().trim();
int quantity = qtyString.equals("") ? 0:Integer.valueOf(qtyString);
ProductModel m = (ProductModel)qtyView.getTag();
if(m.getTQuantity() != quantity) {
m.setTQuantity(quantity);
String price = ((TextView) view.findViewById(R.id.p))
.getText().toString();
String name = ((TextView) view.findViewById(R.id.tv2))
.getText().toString();
int database_position = 1 + position;
Log.d("my position", "" + position);
Log.d("my value", s.toString() + price);
(myActivityInterface).onAdded(s.toString().trim(), price, database_position, name);
}
}
}
}
Activity code:
public class ProductList extends AppCompatActivity implements AddRemoveProductInterface {
ListView listView, checkout_listview;
EditText inputSearch;
ProductListAdapter adapter;
ProductCheckoutAdapter checkout_adapter;
ProductHandler productDB;
String tag_json_obj = "json_obj_req";
TextView total;
String unformatted_number;
String c_phone, c_zip, c_name, total_amount, checkout_id;
Boolean c_extras;
fr.castorflex.android.smoothprogressbar.SmoothProgressBar progbar;
Button button;
byte[] b;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_list);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
total = (TextView) findViewById(R.id.total);
total.setText("0.00");
Intent i = getIntent();
Bundle extras = i.getExtras();
if (extras == null) {
//is null
c_extras = false;
} else {
//has extras
c_extras = true;
b = extras.getByteArray("picture");
c_phone = i.getStringExtra("phone");
c_zip = i.getStringExtra("zip");
c_name = i.getStringExtra("name");
total_amount = i.getStringExtra("total_amount");
checkout_id = i.getStringExtra("checkout_id");
if (total_amount == null) {
total.setText("0.00");
} else {
total.setText(total_amount);
}
// Toast.makeText(getApplicationContext(), total_amount, Toast.LENGTH_LONG).show();
}
productDB = new ProductHandler(this);
/* sbv = (SlideBottomPanel) findViewById(R.id.sbv);*/
progbar = (fr.castorflex.android.smoothprogressbar.SmoothProgressBar) findViewById(R.id.prog1);
listView = (ListView) findViewById(R.id.list);
// listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
checkout_listview = (ListView) findViewById(R.id.checkout_list);
// insert data into the list before setting the adapter
// otherwise it will generate NullPointerException - Obviously
productListRequest();
showProductFromTable();
inputSearch = (EditText) findViewById(R.id.inputSearch);
inputSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
/* ProductList.this.myList.getFilter().filter(cs);*/
if (cs.length() > 0) {
adapter.getFilter().filter(cs);
} else {
TextView search = (TextView) findViewById(R.id.no_results);
search.setVisibility(View.INVISIBLE);
adapter.getFilter().filter(cs);
}
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
final LinearLayout animated_layout = (LinearLayout) findViewById(R.id.list_animated);
//animating product sold list
button = (Button) findViewById(R.id.submit);
if (total.getText().toString().equals("0.00")) {
button.setEnabled(false);
} else {
button.setEnabled(true);
}
button.setOnClickListener(new View.OnClickListener() {
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onClick(View v) {
Log.d("JSON PROD:", productDB.composeProductSolddJSONfromSQLite());
Intent intent = new Intent(getApplicationContext(), CustomerIdentify.class);
intent.putExtra("total_sld", unformatted_number);
//send extras if exist to identify activity
if (c_extras) {
intent.putExtra("picture", b);
intent.putExtra("c_phone", c_phone);
intent.putExtra("c_extras", c_extras);
intent.putExtra("c_zip", c_zip);
intent.putExtra("c_name", c_name);
}
startActivity(intent);
}
});
}
private void showProductFromTable() {
//progbar.setVisibility(View.INVISIBLE);
ArrayList<ProductModel> modelArrayList = productDB.loadProduct();
//adding it to the list view.
adapter = new ProductListAdapter(this, modelArrayList, this);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
public void productListRequest() {
progbar.setVisibility(View.VISIBLE);
String url = "http://shopofficer.com/business/products/api";
JsonArrayRequest jsonObjReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
Log.d("product list response:", response.toString());
//listView.setVisibility(View.VISIBLE);
progbar.setVisibility(View.INVISIBLE);
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
String name = obj.getString("name");
String price = obj.getString("price");
String description = obj.getString("description");
String image = obj.getString("image");
String product_id = obj.getString("id");
/*Log.d("my data is", id + title + description);*/
productDB.addProduct(product_id, name, price, description, image, "0");
showProductFromTable();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("productlist error",
"Error: " + error.getMessage());
/* Crouton.makeText(AttendantList.this, "Something went wrong, please retry",
Style.ALERT, R.id.anchor).show();*/
progbar.setVisibility(View.INVISIBLE);
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("session_id", getapikey());
return headers;
}
};
ShopOfficer.getInstance().getRequestQueue().getCache()
.invalidate(url, true);
// Adding request to request queue
ShopOfficer.getInstance().addToRequestQueue(jsonObjReq, tag_json_obj);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_select_product, menu);
return true;
}
@Override
public void onResume() {
super.onResume();
showProductFromTable();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_add_product) {
Intent intent = new Intent(getApplicationContext(), AddNewProduct.class);
startActivity(intent);
return true;
}
if (id == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onAdded(String s, String price, int database_position, String name) {
if (s.equals("")) {
} else {
//set total
Double currentPrice = Double.valueOf(price);
Double quantity = Double.valueOf(s);
Double calculated = quantity * currentPrice;
//Double priceDiff = Double.valueOf(df.format(extPrice - currPrice));
productDB.update(database_position, "" + calculated);
DecimalFormat df = new DecimalFormat("0.00##");
//add commas thousands
unformatted_number = String.valueOf(df.format(productDB.getTotalOfAmount()));
double amount = Double.parseDouble(unformatted_number);
DecimalFormat formatter = new DecimalFormat("#,###.00");
total.setText("" + formatter.format(amount));
if (total.getText().toString().equals(".00")) {
total.setText("0.00");
}
//add product sold
if (quantity < 1) {
productDB.deleteSingleProductSold(Integer.valueOf(s));
} else {
productDB.addSale(database_position, name, String.valueOf(calculated), s);
}
if (total.getText().toString().equals("0.00")) {
button.setEnabled(false);
} else {
button.setEnabled(true);
}
}
}
@Override
public void onRemoved(String s) {
total.setText("");
}
@Override
public void onSearchEmpty(String s) {
// Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();
TextView search = (TextView) findViewById(R.id.no_results);
search.setVisibility(View.VISIBLE);
search.setText(s);
}
}