如何在列表视图中保持CheckedTextView的状态和位置?

时间:2019-04-08 00:18:58

标签: android onitemclicklistener checkedtextview

我有一个使用自定义适配器填充了checkedtextview的列表视图,我遇到的问题是,例如,当我在列表视图中选中一个复选框或另一个复选框时,现在已经相当了解列表的概念视图以及视图的回收方式,那么我在这里做错了什么? 我遇到的另一个问题是,滚动时复选框的位置不断变化
 我已经尝试了多种解决方案并一直在尝试,对于了解此问题的任何帮助,我们都将不胜感激

这是checkedtextview xml

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

    <CheckedTextView
        android:id="@+id/checkedTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:checked="false"
        android:drawableLeft="?android:attr/listChoiceIndicatorMultiple"
        android:gravity="center"
        android:paddingBottom="@dimen/virtical_padding"
        android:textAppearance="?android:textAppearanceLarge"
        tools:text="Service 1" />

    <Button
        android:id="@+id/plus_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/check_box_list_margin"
        android:layout_marginLeft="@dimen/check_box_list_margin"
        android:focusable="false"
        android:text="@string/plus"
        android:textColor="#000"
        android:visibility="invisible" />

    <TextView
        android:id="@+id/quantity_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:text="@string/quantity_default"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="#000"
        android:visibility="invisible" />

    <Button
        android:id="@+id/minus_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:text="@string/minus"
        android:textColor="#000"
        android:visibility="invisible" />

</LinearLayout>

这是OnItemClickListener的代码

 mServiceListView.setOnItemClickListener( new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                //find the checkedTextView inside the relative view
                  ctv = (CheckedTextView) view.findViewById( R.id.checkedTextView );
                  mServiceQuantity = (TextView) view.findViewById( R.id.quantity_tv );
                  mMinusBtn = ( Button) view.findViewById( R.id.minus_btn );
                  mPlusBtn = (Button) view.findViewById( R.id.plus_btn );
                ((CheckedTextView) ctv).toggle();
                Service service = (Service) parent.getItemAtPosition(position);

                if (ctv.isChecked()) {
                    selectedServices.add(service.getServiceNum());
                    //make the quantity option visible
                    mMinusBtn.setVisibility( View.VISIBLE );
                    mPlusBtn.setVisibility( View.VISIBLE );
                    mServiceQuantity.setVisibility( View.VISIBLE );

                } else {
                    //remove the service and quantity from table
                    selectedServices.remove( service.getServiceNum() );

                    selectedServicesHash.remove( service.getServiceNum() );
                    //the quantity option will be invisible
                    mMinusBtn.setVisibility( View.INVISIBLE );
                    mPlusBtn.setVisibility( View.INVISIBLE );
                    mServiceQuantity.setVisibility( View.INVISIBLE );

                }
            }
        } );

这是自定义适配器的代码

package com.example.android.bookkeepingapp;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CheckedTextView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import org.w3c.dom.Text;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;


public class ServiceAdapterCheckBox extends ArrayAdapter<Service> {

    private Hashtable<String, Integer> selectedServicesHash;
    private  Set<String> serviceNums;

    public ServiceAdapterCheckBox(@NonNull Context context, int resource, List<Service> objects
            , Hashtable<String, Integer> selectedServiceHash) {
        super( context, resource, objects );
        this.selectedServicesHash = selectedServiceHash;
    }

    public void setSelectedServicesHash(Hashtable<String, Integer> selectedServices) {
        this.selectedServicesHash = selectedServices;
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        //Find the current object
            Service service = getItem(position);
          //put all the services name of the hashtable in a list
          serviceNums= selectedServicesHash.keySet();
            final ViewHolder holder;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.service_item_check_box,
                    parent, false);

            holder.textCheckBox = (CheckedTextView) convertView.findViewById(R.id.checkedTextView);
            holder.minBtn = (Button) convertView.findViewById( R.id.minus_btn );
            holder.plusBtn = (Button) convertView.findViewById( R.id.plus_btn );
            holder.quantityTv = (TextView) convertView.findViewById( R.id.quantity_tv );
            convertView.setTag(holder);
        }
        else {
            // the getTag returns the viewHolder object set as a tag to the view
            holder = (ViewHolder)convertView.getTag();
        }

        //supply the textViews with the correct data
        assert service != null;
        holder.textCheckBox.setText( service.getServiceName() );
        //set the quantity value set by the user

        holder.plusBtn.setOnClickListener( new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //holder.plusBtn.setFocusable( true );
                int quantityValue = Integer.parseInt(holder.quantityTv.getText().toString());
                quantityValue++;
                holder.quantityTv.setText( String.valueOf( quantityValue ) );


            }
        } );

        holder.minBtn.setOnClickListener( new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //holder.plusBtn.setFocusable( true );
                int quantityValue = Integer.parseInt(holder.quantityTv.getText().toString());
                if(quantityValue == 1){
                    quantityValue = 1;
                }
                else {
                    quantityValue--;
                }
                holder.quantityTv.setText( String.valueOf( quantityValue ) );


            }
        } );

        //if the there are services in the hash table
        if(serviceNums.size() != 0) {
            Log.v(this.getContext().toString(), "there are services selected");
            //put all the services name of the hashtable in a list
            for (String s : serviceNums) {
                if (service.getServiceNum().equals( s )) {
                    //set the check text with the current position to true
                    //holder.textCheckBox.setChecked( true );
                    //set the quantity text box to the correct value set by the user
                    //holder.quantityTv.setText(selectedServicesHash.get(s));
                    //set the quantity selectors to visible
                    holder.plusBtn.setVisibility( View.VISIBLE );
                    holder.minBtn.setVisibility( View.VISIBLE );
                    holder.quantityTv.setVisibility( View.VISIBLE );

                }
            }
        }

        else{
            Log.v(this.getContext().toString(), "no the list is empty");
            //set the quantity text box to the correct value set by the user
            holder.quantityTv.setText("1");
        }


        return  convertView;
    }

    public Hashtable<String, Integer> getSelectedServicesHash() {
        return selectedServicesHash;
    }

    /**
     * customizable toast
     *
     * @param message
     */
    private void toastMessage(String message) {
        Toast.makeText( getContext(), message, Toast.LENGTH_SHORT ).show();
    }

    private class ViewHolder {

        protected CheckedTextView textCheckBox;
        protected  Button plusBtn;
        protected  Button minBtn;
        protected TextView quantityTv;

    }
}

我想要做的就是获取具有正确位置的正确复选框 谢谢...

1 个答案:

答案 0 :(得分:1)

由于视图是在ListView中回收的,因此必须将视图状态更新为适配器代码中的状态。否则,视图将仅具有已重用的旧视图的选中状态。

因此,除了更新视图上的文本外,您还需要设置其选中状态。

//supply the textViews with the correct data
assert service != null;
holder.textCheckBox.setText( service.getServiceName() );

// ALSO UPDATE THE CHECKED STATE - FROM YOUR POSTED CODE, I ASSUME IT SHOULD BE
// CHECKED IF IT APPEARS IN THE "selectedServices" list
holder.textCheckBox.setChecked(selectedServices.contains(service));