2017-02-20 17 views
2

Хотя это поведение, которое я хочу, может кто-нибудь объяснить мне, почему это происходит?Почему модель данных не обновляется, когда строка ListView с CheckBox выходит за пределы экрана?

У меня есть ListView с пользовательскими рядами, состоящими из CheckBox и TextView. Вот код расположения строк:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_height="match_parent" 
    android:layout_width="match_parent" 
    android:orientation="horizontal"> 

    <CheckBox 
     android:id="@+id/shop_list_checkbox" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 

    <TextView 
     android:id="@+id/shop_list_textView" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Sample text" 
     /> 

</LinearLayout> 

Тогда я этот простая модель данных (опущены некоторые методы и поле), в основном магазин с названием и выбором состоянием:

public class ShopListItem { 

    //name of the shop 
    private String name; 

    //shop selection state 
    private boolean isSelected; 

    public ShopListItem(String shopKey, String name, boolean isSelected) { 
     this.shopKey = shopKey; 
     this.name = name; 
     this.isSelected = isSelected; 
    } 

    public boolean isSelected() { 
     return isSelected; 
    } 

    public void setSelected(boolean selectionState) { 
     this.isSelected = selectionState; 
    } 
} 

А вот соответствующий код из моего обычая ArrayAdapter:

public View getView(int position, View convertView, @NonNull ViewGroup parent) { 

     // Temporary view to be returned as converterView 
     View view; 

     // Checking if view is reused or not 
     if (convertView == null) { //new view is generated 

      // Inflate new view and associate its views with viewHodler 
      view = inflater.inflate(R.layout.row_shop_list, parent, false); 
      final ViewHolder viewHolder = new ViewHolder(); 
      viewHolder.shopNameTextView = (TextView) view.findViewById(R.id.shop_list_textView); 
      viewHolder.checkBox = (CheckBox) view.findViewById(R.id.shop_list_checkbox); 

      // Asign check change listener 
      viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
       @Override 
       public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
        Log.i("i", "isChecked value is: "+isChecked+", buttonView.isChecked() value is: "+buttonView.isChecked()); 

        // Get reference to the shop (data model) of checked row 
        ShopListItem shop = (ShopListItem) viewHolder.checkBox.getTag(); 

        // Update selection state in data model 
        shop.setSelected(buttonView.isChecked()); 

        listSelections(shopsArrayList); 

       } 
      }); 


      // Store viewHolder inside temporary view 
      view.setTag(viewHolder); 

      // Store reference to a shop (data model) of this row in the checkbox reference 
      viewHolder.checkBox.setTag(shopsArrayList.get(position)); 

     } else { //existing view reused 

      // Assign view from adapter to temporary view 
      view = convertView; 

      // Get viewholder from view which was stored while generating new view 
      ViewHolder storedHolder = (ViewHolder) view.getTag(); 

      //Store reference to a shop (data model) of this row in the checkbox reference 
      storedHolder.checkBox.setTag(shopsArrayList.get(position)); 

     } 

     // Get viewholder from view (from new view or converview) 
     ViewHolder holder = (ViewHolder) view.getTag(); 

     // Populate holder references with data from shops array list 
     holder.shopNameTextView.setText(shopsArrayList.get(position).getName()); 
     holder.checkBox.setChecked(shopsArrayList.get(position).isSelected()); 

     //return view 
     return view; 

    } 

тайна лежит в OnCheckedChangeListener. Всякий раз, когда я нажимаю флажок первой строки, слушатель получает правильное состояние и обновляет первый элемент списка массивов магазинов (либо true, либо false). Но, если я оставляю первый флажок установленным и списком прокрутки вниз, как только первая строка выходит за пределы экрана, OnCheckedChangeListener вызывается с состоянием false, но первый элемент списка массивов магазинов не обновляется до false. Почему это происходит? Почему он обновляется только при нажатии на кнопку, но не тогда, когда его вызываемый должен быть скрыт?

+0

Ребят, я забыл упомянуть, что, когда я прокручиваю список обратно вверх, первый элемент остается выбрано - все работает правильно. Я просто не понимаю, почему мой arraylist не обновляется до 'false', когда используется вид строки, и' OnCheckedChangeListener' вызывается с 'false'. – wilkas

ответ

1

Как только вы нажмете на флажок, активируется OnCheckedChangeListener. Когда вы прокручиваете вниз или вверх, вызывается ПРОЧИЕOnCheckedChangeListener для вызова NEW ROW, который подходит к экрану. OnCheckedChangeListener скрытой линии не вызывается.

В вашем случае, я полагаю, вы получаете значение флажка новой строки, выходящей на экран, и это путает вас. Постарайтесь определить, какой магазин объект идет речь в вашей OnCheckedChangeListener's линии:

ShopListItem shop = (ShopListItem) viewHolder.checkBox.getTag(); 
0

Добавить один флаг сохранить проверенный элемент данных в Списке данных>

public boolean isSelected() { 
    return selected; 
} 
public void setSelected(boolean selected) { 
    this.selected = selected; 
} 

И добавить код флажка в вашем GetView() адаптер

@Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

    ViewHolder holder = null; 
    Log.v("ConvertView", String.valueOf(position)); 

    if (convertView == null) { 
    LayoutInflater vi = (LayoutInflater)getSystemService(
    Context.LAYOUT_INFLATER_SERVICE); 
    convertView = vi.inflate(R.layout.country_info, null); 

    holder = new ViewHolder(); 
    holder.code = (TextView) convertView.findViewById(R.id.code); 
    holder.name = (CheckBox) convertView.findViewById(R.id.checkBox1); 
    convertView.setTag(holder); 

    holder.name.setOnClickListener(new View.OnClickListener() { 
    public void onClick(View v) { 
     CheckBox cb = (CheckBox) v ; 
     Country country = (Country) cb.getTag(); 
     Toast.makeText(getApplicationContext(), 
     "Clicked on Checkbox: " + cb.getText() + 
     " is " + cb.isChecked(), 
     Toast.LENGTH_LONG).show(); 
     country.setSelected(cb.isChecked()); 
    } 
    }); 
    } 
    else { 
    holder = (ViewHolder) convertView.getTag(); 
    } 

    Country country = countryList.get(position); 
    holder.code.setText(" (" + country.getCode() + ")"); 
    holder.name.setText(country.getName()); 
    holder.name.setChecked(country.isSelected()); 
    holder.name.setTag(country); 

    return convertView; 

    } 

для получения дополнительной информации смотрите ниже ссылки :

http://www.mysamplecode.com/2012/07/android-listview-checkbox-example.html

0

Как прокрутке литиево st, первый элемент отключается. Когда элемент уходит, вызывается getView и используется вид. Вы должны сохранить состояние этого конкретного объекта, чтобы правильно показывать на уровне пользовательского интерфейса

+0

Состояние этого конкретного объекта сохраняется - он остается выбранным при прокрутке вверх! Я просто не понимаю, почему элемент в ArrayList не изменяется на 'false', когда он выходит за пределы экрана. – wilkas

+0

Почему это должно быть изменено. Я имею в виду, когда вы сохраняете состояние, это то, что вам нужно –

+0

Когда я снимаю флажок, 'OnCheckedChangeListener' вызывается с' false', а массив обновляется до false.Когда я прокручиваю выделенное поле на экране, 'OnCheckedChangeListener' вызывается снова с' false', но массив не обновляется до false, он остается 'true'. Я не понимаю эту несогласованность. – wilkas