Android Studio - Listview OnClick активирует несколько флажков - PullRequest
0 голосов
/ 10 февраля 2020

Здравствуйте, я новичок в Androidstudio.

Я пытался создать ListView с флажком и TextView. На первый взгляд это выглядит так, как будто это работает, но проблема в том, что я установил флажок «Мои заметки: 0». "и флажок" My Note: 9 "установлен, я понятия не имею, почему и отладка не помогает.

Не только Note 9 проверяется каждый: проверяется кратность 8 +1. Таким образом, некоторые проверенные из них 9, 17, 25, 33,41,49,57,65,73,81 ......

enter image description here

ListView XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="100">

    <CheckBox android:gravity="center"
        android:text=""
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:id="@+id/checkBox_shopEntry"
        android:layout_weight="90"/>


    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="10">

        <TextView
            android:id="@+id/textView_feedbackName"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_gravity="left"
            android:fontFamily="casual"
            android:gravity="center|left"
            android:text="TextView1" />


    </LinearLayout>


</LinearLayout>

Адаптер ListView:

package com.example.fragment.Entity;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.example.fragment.R;

import java.util.ArrayList;



public class ShopListAdapter extends ArrayAdapter<ShoppingEntry> {

    private static final String TAG = "ShopListAdapter";

    private Context mContext;
    private int mResource;
    private int lastPosition = -1;

    /**
     * Holds variables in a View
     */
    private static class ViewHolder {
        TextView name;
        CheckBox checkBox;
    }

    public ShopListAdapter(Context context, int resource, ArrayList<ShoppingEntry> objects) {
        super(context, resource, objects);
        mContext = context;
        mResource = resource;
    }

    @Override
    public void add(@Nullable ShoppingEntry object) {
        super.add(object);
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //get the shop list information
        String name = getItem(position).getName();


        //Create the shopEntry object with the information
        ShoppingEntry shopEntry = new ShoppingEntry(name);

        //create the view result for showing the animation
        final View result;

        //ViewHolder object
        ViewHolder holder;


        if(convertView == null){
            LayoutInflater inflater = LayoutInflater.from(mContext);
            convertView = inflater.inflate(mResource, parent, false);
            holder= new ViewHolder();
            holder.name = (TextView) convertView.findViewById(R.id.textView_feedbackName);
            holder.checkBox = convertView.findViewById(R.id.checkBox_shopEntry);

            result = convertView;

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




        Animation animation = AnimationUtils.loadAnimation(mContext,
                (position > lastPosition) ? R.anim.load_down_anim : R.anim.load_up_anim);
        result.startAnimation(animation);
        lastPosition = position;

        holder.name.setText(shopEntry.getName());

        return convertView;
    }
}

И объект, используемый в адаптере

package com.example.fragment.Entity;


public class ShoppingEntry {
    private String name;


    public ShoppingEntry(String note) {
        this.name = note;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

Ответы [ 2 ]

1 голос
/ 10 февраля 2020

Проблема, с которой вы сталкиваетесь, связана с тем, как ListView перерабатывает представления.

Вы, вероятно, уже знаете об этом, поскольку реализовали метод getView() с учетом этого:

    if(convertView == null){
        // Inflate a new View
    }
    else{
        // reuse the recylced view
    }

Таким образом, ListView отображает столько элементов, сколько необходимо для заполнения экрана. Он не создает больше элементов, пока вы не начнете прокручивать, а когда вы do начнете прокручивать, ListView начнет повторно использовать уже раздутые представления, которые вышли из экрана.

Поэтому, когда вы прокручиваете вниз, представление для заметки 0 выходит за пределы экрана, и ListView повторно использует его для заметки 9, которая вот-вот выйдет на экран.

Это привело бы к тому, что вы снова увидите «Мои заметки: 0» снизу, но ваш код уже решает эту проблему, заново устанавливая текст элемента соответствующим образом:

holder.name.setText(shopEntry.getName());

Но это все тот же объект View, который использовался для Note 0. Даже если вы обновили текст с правильным номером «9», состояние флажка остается таким же, как и для примечания 0, потому что это все тот же объект.

Чтобы решить эту проблему, вам нужно будет сделать 2 вещи:

  1. Хранить состояние «проверено» каждого элемента входа в магазин где-нибудь
  2. Inisde getView(), установить состояние флажка в состояние отмеченного т Запись в вопросе

Примерно так:

// Store a list of checked items. Update as items are checked/unchecked
private ArrayList<ShopEntry> checkedEntries = new ArrayList();

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

    if(convertView == null){
        LayoutInflater inflater = LayoutInflater.from(mContext);
        convertView = inflater.inflate(mResource, parent, false);
        holder= new ViewHolder();
        holder.name = (TextView) convertView.findViewById(R.id.textView_feedbackName);
        holder.checkBox = convertView.findViewById(R.id.checkBox_shopEntry);

        // Update the list of checked items when the user checks or unchecks an item
        holder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView,
                    boolean isChecked) {
                if(isChecked && !checkedEntries.contains(shopEntry)) {
                    checkedEntries.add(shopEntry);
                } else {
                    checkedEntries.remove(shopEntry);
                }
            }
        });

        result = convertView;

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

    .
    .
    .


    holder.name.setText(shopEntry.getName());
    // reset the checbkox state too!
    holder.checkBox.setChecked(checkedEntries.contains(shopEntry));

    return convertView;
}

Предупреждение: в системе не установлена ​​Android Studio. Я пишу это, поэтому у меня нет не проверял этот код. Простите за это. Но я надеюсь, что передал общую идею. Возможно, вы захотите реализовать всю вещь «отслеживайте, какие элементы проверены» по-своему (лучше).

0 голосов
/ 10 февраля 2020

В основном я работал над видом переработчика, но я исправил эту проблему, просто замените класс адаптера

 class ShopListAdapter extends ArrayAdapter<ShoppingEntry> {

private static final String TAG = "ShopListAdapter";
private Context mContext;
ArrayList<ShoppingEntry> mList=new ArrayList<>();

public ShopListAdapter(Context context, ArrayList<ShoppingEntry> list) {
    super(context, R.layout.item_checkbox_issue, list);
    mContext = context;
    mList.addAll(list);
}

@Override
public void add(@Nullable ShoppingEntry object) {
    super.add(object);
}

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


       TextView textView;
       CheckBox checkbox;

        convertView = LayoutInflater.from(mContext).inflate(R.layout.item_checkbox_issue, parent, false);
        textView =  convertView.findViewById(R.id.textView_feedbackName);
        checkbox = convertView.findViewById(R.id.checkBox_shopEntry);
        boolean checked= mList.get(position).isChecked();
        String name = mList.get(position).getName();
        checkbox.setChecked(checked);
        textView.setText(name);

        checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                    mList.get(position).setChecked(isChecked);
                    notifyDataSetChanged();

            }

        });

    return convertView;
}

и выберите переменную, выбранную в вашей модели, потому что она управляет проверенным и непроверенным виджетом для конкретного пользователя. позиция

 class ShoppingEntry {
private String name;

private  boolean isChecked;


public ShoppingEntry(String note, boolean isChecked) {
    this.name = note;
    this.isChecked = isChecked;
}

public boolean isChecked() {
    return isChecked;
}

public void setChecked(boolean checked) {
    isChecked = checked;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...