列表视图中的编辑文本值在屏幕超时时更改为默认值

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 ?

以上是关于列表视图中的编辑文本值在屏幕超时时更改为默认值的主要内容,如果未能解决你的问题,请参考以下文章

如果值在 Android 中为空或 null,则显示默认文本

UIButton 标题更改为默认值

Xcode - 分段控制更改为默认值

在编辑超链接单击时将标签更改为文本框

SonataORMAdmin 列表视图上的默认自定义路由

使用javascript将光标更改为锚标记中的默认值