列表视图中的编辑文本值在屏幕超时时更改为默认值
Posted
技术标签:
【中文标题】列表视图中的编辑文本值在屏幕超时时更改为默认值【英文标题】:Edittext values in listview changes to default on screen timeout 【发布时间】:2016-06-26 16:06:34 【问题描述】:我有一个listview
,每行都有edittext
小部件。我在custom adapter
中使用viewholder
来跟踪所有视图。
但我的问题是,当我在edittext
中输入一个值时,暂停直到我的屏幕超时,当你解锁手机时仍然在同一个activity
中,默认的edittext
值被重新填充,覆盖我的编辑。
我在这里遵循了这个建议(when listview scroll that time edittext set default value),考虑到我可能没有使用viewholder
,但仍然面临同样的问题。就像getView()
不断被调用,完全重绘了我的观点。
关于解决方法的任何想法/建议?
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);
活动代码:
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);
【问题讨论】:
您在 Activity 的生命周期中在哪里设置适配器? 在我的 onCreate() 函数中。 能否出示您的活动代码? @Fabio Venturi Pastor 完成。查看我的编辑。 你是否尝试删除 onResume() 的“showProductFromTable()” 【参考方案1】:视图和视图持有者只是暂时与一行相关联。这意味着任何编辑过的数据都需要存储在其他地方。 否则,每次重新构建视图或将视图重新用于不同的行时,信息都会丢失,例如滚动或重新构建视图时。
一种可能的解决方案是将其添加到模型中:
将数据(数量)添加到ProductModel
。 (the_quantity
)
将位置属性添加到查看器 (the_position
)。
这是必需的,因为侦听器是匿名类。他们看到(副本)position
参数的值及其实例化时的值。
这就是为什么编译器有时会抱怨position
参数不是最终的,这通常意味着有问题:您应该只在回调之外引用它。
UI -> 模型:将编辑后的值存储在模型中(在两个侦听器中)
public void onClick(View v)
//get the value of edittext
//add one item
int added_item = Integer.parseInt(viewHolder.quantity.getText().toString()) + 1;
// Store the value in the model
// We use the position from the viewholder,
// **not** the method's parameter (which contain
// the value when the listener was created)
modelItems.get(viewHolder.the_position).the_quantity = added_item;
viewHolder.quantity.setText("" + added_item);
Model -> UI : 每次更新 UI,不仅是在创建视图时
// object item based on the position
final ProductModel m = modelItems.get(position);
viewHolder.tvTitle.setText(m.getname());
// update the viewholder's position
viewHolder.the_position = position;
viewHolder.quantity.setText("" + m.the_quantity)
return convertView;
【讨论】:
我已经阅读了相关内容,但我不确定在哪里编辑我的代码而不弄乱它。我用完整的适配器代码编辑了我的代码。请参见上文。 好的,我以某种方式遵循了您的建议。请参阅上面的完整适配器代码 如果我理解正确,您现在正在从模型更新数量视图。看起来没问题。MyTextWatcher
使用编辑后的值更新模型。这看起来也不错。似乎它还会根据位置 (database_position
) 触发数据库更新。我认为有两个问题:-TextWatcher
包含(错误的)最终位置-无论如何适配器位置取决于过滤。使用某种 DB id 可能会更好,存储在 ProductModel
本身中
我也看到了,我现在使用的是productmodel附带的id,它也存储在db中
EditText 的数量是否仍然重置为 0 ?以上是关于列表视图中的编辑文本值在屏幕超时时更改为默认值的主要内容,如果未能解决你的问题,请参考以下文章