0

我有一个 ListView,每行都有一个 EditText(数量框)。当用户设置所需的数量时,新值会更新 SQLite 数据库中的相应列,然后我用修改后的值重新填充 ListView。为了触发这个过程,我在 EditText 上使用了addTextChangedListener,它工作得很好。

我的问题是每次滚动时都会调用监听器,这会触发上述过程,甚至没有触摸数量框。

如何避免在滚动时触发 addTextChangedListener?我的spinner.setOnItemSelectedListener 也会出现同样的问题。我试图让听众在 getView 方法之外,但没有任何运气...... :(

自定义列表视图:

public class PhotosListViewAdapter extends ArrayAdapter<ImageItemsSetter> {

        DeleteImageListener dListener;
        private Context context;
        private int layoutResourceId;
        private ArrayList<ImageItemsSetter> data = new ArrayList<ImageItemsSetter>();   

        //standard constructor
        public PhotosListViewAdapter(Context context, int layoutResourceId, ArrayList<ImageItemsSetter> data) {
            super(context, layoutResourceId, data);
            this.layoutResourceId = layoutResourceId;
            this.context = context;
            this.data = data;            
        }           

        static class ViewHolder {

            public ImageView Img; 
            public EditText quantity;
            public Spinner spinner;
            public Button delete;

        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            View row = convertView;
            ViewHolder holder = null;            

            ImageItemsSetter image = data.get(position);

        if (row == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);
            holder = new ViewHolder(); 

            holder.Img = (ImageView) row.findViewById(R.id.Img);

            holder.quantity = (EditText) row.findViewById(R.id.quantity);
            // holder.quantity.addTextChangedListener(new GenericTextWatcher(holder.quantity));           

            holder.spinner = (Spinner) row.findViewById(R.id.photo_format);
            holder.delete = (Button) row.findViewById(R.id.deleteImage);

            row.setTag(holder);
        } else {
            holder = (ViewHolder) row.getTag(); 
        }           

         holder.Img.setImageBitmap(image.getTheImage());            
         holder.quantity.setText(image.getQuantity());


        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context,
                R.array.formats_array, android.R.layout.simple_spinner_item);       
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);     
        holder.spinner.setAdapter(adapter);

        //The delete button
        holder.delete.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {           

                if (dListener != null) {  
                    dListener.onDeletePressed(position); 
                }       
            }           
            });      


        holder.spinner.setOnItemSelectedListener(new OnItemSelectedListener() {     

            @Override
            public void onItemSelected(AdapterView<?> parent, View view,
                    int pos, long id) {                         
                dListener.onFormatChanged(parent.getItemAtPosition(pos).toString(), data.get(position).getName());              
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                // TODO Auto-generated method stub              
            }

        });

        holder.quantity.addTextChangedListener(new TextWatcher() {

               @Override
               public void afterTextChanged(Editable s) { }

               @Override    
               public void beforeTextChanged(CharSequence s, int start,
                 int count, int after) {  }

               @Override    
               public void onTextChanged(CharSequence s, int start,
                 int before, int count) {
                   dListener.onQuantityChanged(s.toString(), data.get(position).getName());
                }
              });


        return row;
        }


        /*
         private class GenericTextWatcher implements TextWatcher {

                private View view;              
                private GenericTextWatcher(View view) {
                    this.view = view;
                }                           


                // 3. saving the quantity box before it gets outside the visible area
                @Override
                public void afterTextChanged(Editable s) { 
                     final EditText editText = (EditText) view; 
                     dListener.onQuantityChanged(editText.getText().toString(), "tom");

                }

                @Override
                public void beforeTextChanged(CharSequence s, int start,
                        int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start,
                        int before, int count) {


                }
            }
            */



        //Interface to send selected image's position for deletion
        public void setDeleteImageListener(DeleteImageListener listener) {  
            this.dListener = listener;  
        } 

        public static interface DeleteImageListener { 
            public void onDeletePressed(int position);
            public void onQuantityChanged(String quantity, String name);
            public void onFormatChanged(String format, String name);
        }               

主机活动部分(这里我使用 2 个自定义接口接收响应):

@Override
public void onQuantityChanged(String quantity, String name) {
    System.out.println("quantity set to: " + quantity + " " + name );
    datasource.updateImageQuantiry(name, quantity);
    rePopulateList(); 

}

@Override
public void onFormatChanged(String format, String name) {
    System.out.println("format set to: " + format + " name: " + name);

}
4

2 回答 2

1

向您的 ListView 添加一个滚动侦听器,并在某处设置一个标志以了解 ListView 是否正在滚动。
然后在 onTextChanged 中,在调用您的侦听器之前检查该标志。
这将起作用,因为方法 AbsListView.OnScrollListener.onScrollStateChanged 在滚动发生之前被调用。

公共抽象无效 onScrollStateChanged(AbsListView 视图,int scrollState)

滚动列表视图或网格视图时调用的回调方法。如果视图正在滚动,该方法将在滚动的下一帧渲染之前调用。特别是,它将在任何对 getView(int, View, ViewGroup) 的调用之前调用。

你甚至可以让你的 PhotosListViewAdapter 类实现 OnScrollListener 接口,然后将你的适配器设置为 ListView 的滚动监听器。这样您就可以管理适配器内的滚动标志状态。

public class PhotosListViewAdapter extends ArrayAdapter<String> implements AbsListView.OnScrollListener {

    public boolean scrolling;

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        scrolling = scrollState != SCROLL_STATE_IDLE ;
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

    }

    //...
    //TextWatcher.onTextChanged()
    //if(!scrolling) dListener.onQuantityChanged(s.toString(), data.get(position));
    //...
}

//In your activity or fragment:
//myListView.setOnScrollListener(myPhotoListViewAdapter);
于 2015-04-16T00:30:50.253 回答
0

这是因为您的适配器会在您滚动时在视图上设置文本,这应该会启动您的侦听器。

此外,您应该只设置一次听众,而不是每次getView()都被调用。

于 2015-04-16T00:28:09.147 回答