带有复选框的可扩展ListView在没有用户检查的情况下检查随机复选框

时间:2017-03-06 20:23:03

标签: android listview expandablelistview android-adapter

我单独做一个大学项目,我偶然发现了一个问题...... 每次我在列表视图中选中一个复选框时,当我向下或向上滚动时,其他复选框都会被选中,我不知道如何解决这个问题。有人能帮助我吗?

请参阅下面的代码,它有效,我只是不知道如何维护只检查用户想要的复选框,而不检查和取消选中随机的其他人...

MAIN

import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ExpandableListView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.LinkedHashMap;

import static android.os.SystemClock.sleep;
import static android.widget.Toast.makeText;

public class Etapas extends AppCompatActivity {

    private LinkedHashMap<String, GroupInfo> subjects = new LinkedHashMap<String, GroupInfo>();
    private ArrayList<GroupInfo> deptList = new ArrayList<GroupInfo>();

    private CustomAdapter listAdapter;
    private ExpandableListView simpleExpandableListView;
    private static Button buttonSalvar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_etapas);
        setTitle("Etapas");
        onButtonClickListener();

        // add data for displaying in expandable list view
        loadData();

        //get reference of the ExpandableListView
        simpleExpandableListView = (ExpandableListView) findViewById(R.id.simpleExpandableListView);
        // create the adapter by passing your ArrayList data
        listAdapter = new CustomAdapter(Etapas.this, deptList);
        // attach the adapter to the expandable list view
        simpleExpandableListView.setAdapter(listAdapter);

        //expand all the Groups
        //expandAll();

        // setOnChildClickListener listener for child row click
        simpleExpandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                //get the group header
                GroupInfo headerInfo = deptList.get(groupPosition);
                //get the child info
                ChildInfo detailInfo = headerInfo.getProductList().get(childPosition);
                //display it or do something with it
//                Toast.makeText(getBaseContext(), " Clicked on :: " + headerInfo.getName()
//                        + "/" + detailInfo.getName(), Toast.LENGTH_LONG).show();
                return false;
            }
        });
        // setOnGroupClickListener listener for group heading click
        simpleExpandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
                //get the group header
                GroupInfo headerInfo = deptList.get(groupPosition);
                //display it or do something with it
//                Toast.makeText(getBaseContext(), "Etapa: " + headerInfo.getName(),
//                        Toast.LENGTH_LONG).show();

                return false;
            }
        });


    }

    public void onButtonClickListener(){
        buttonSalvar = (Button)findViewById(R.id.button5);
        buttonSalvar.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v){
                AlertDialog.Builder a_builder = new AlertDialog.Builder(Etapas.this);
                a_builder.setMessage("Deseja salvar?")
                        .setPositiveButton("OK",new DialogInterface.OnClickListener(){
                                public void onClick(DialogInterface dialog, int which){
                                    //Aqui tem que pegar as checkbox e dar update no banco
                                    makeText(Etapas.this,"Salvo com sucesso!",Toast.LENGTH_LONG).show();
                                   // makeText(Etapas.this,"Salvo com sucesso!",Toast.LENGTH_LONG).show();
                                    //sleep(500);
                                    finish();
                                }
                        })
                        .setNegativeButton("Cancelar", new DialogInterface.OnClickListener()
                        {
                            public void onClick(DialogInterface dialog, int which){
                                dialog.cancel();
                            }
                        });
                AlertDialog alert = a_builder.create();
                alert.show();

            }
        }
        );
    }

    //method to expand all groups
    private void expandAll() {
        int count = listAdapter.getGroupCount();
        for (int i = 0; i < count; i++) {
            simpleExpandableListView.expandGroup(i);
        }
    }

    //method to collapse all groups
    private void collapseAll() {
        int count = listAdapter.getGroupCount();
        for (int i = 0; i < count; i++) {
            simpleExpandableListView.collapseGroup(i);
        }
    }

    //load some initial data into out list
    private void loadData() {

        addProduct("Etapa 1", "Marcação da obra",false);
        addProduct("Etapa 1", "Valetas e brocas",false);
        addProduct("Etapa 1", "Alicerce e impermeabilização",false);
        addProduct("Etapa 1", "30 % alvenaria (altura de 1,20m)",false);
        addProduct("Etapa 1", "Contra-verga com canaleta e concreto armado com treliça",false);

        addProduct("Etapa 2", "Final da alvenaria",false);
        addProduct("Etapa 2", "Verga nas portas e janelas com canaleta e concreto armado com treliça",false);
        addProduct("Etapa 2", "Vigas de respaldo",false);
        addProduct("Etapa 2", "Colocação da laje",false);
        addProduct("Etapa 2", "Concretagem da laje",false);
        addProduct("Etapa 2", "Entrada de água e energia e colocação das caixinhas na laje",false);

        addProduct("Etapa 3", "Telhado (pulverizar madeira com cupicida)",false);
        addProduct("Etapa 3", "Elétrica ( eletrodutos e caixinhas nas paredes)",false);
        addProduct("Etapa 3", "Encanamento de água",false);
        addProduct("Etapa 3", "50% encanamento de esgoto e águas pluviais( Colocar Caixa de gordura)",false);
        addProduct("Etapa 3", "70 % chapisco e reboco interno",false);
        addProduct("Etapa 3", "Contra-piso interno",false);

        addProduct("Etapa 4", "Colocar os batentes e as janelas Sassazaki",false);
        addProduct("Etapa 4", "Terminar reboco interno",false);
        addProduct("Etapa 4", "70% reboco e chapisco externo",false);
        addProduct("Etapa 4", "100% azulejo",false);
        addProduct("Etapa 4", "50% piso",false);
        addProduct("Etapa 4", "Início da pintura (Selador nos cômodos liberados)",false);
        addProduct("Etapa 4", "Cimentado externo",false);
        addProduct("Etapa 4", "Final de hidráulica, esgoto",false);

        addProduct("Etapa 5", "Terminar reboco externo",false);
        addProduct("Etapa 5", "Terminar colocação do piso e rodapé; soleiras e peitoris",false);
        addProduct("Etapa 5", "Assentar portas e fechaduras",false);
        addProduct("Etapa 5", "Final da pintura",false);

        addProduct("Etapa 6", "Colocação do vaso sanitário, lavatório, pia e tanque",false);
        addProduct("Etapa 6", "Final da elétrica (enfiação, espelhos das caixinhas)",false);
        addProduct("Etapa 6", "Limpeza geral da casa",false);
        addProduct("Etapa 6", "Retirada do Habite-se",false);
        addProduct("Etapa 6", "Averbação em cartório.",false);

    }


    //here we maintain our products in various departments
    private int addProduct(String department, String product, boolean status) {

        int groupPosition = 0;
        status = false;

        //check the hash map if the group already exists
        GroupInfo headerInfo = subjects.get(department);
        //add the group if doesn't exists
        if (headerInfo == null) {
            headerInfo = new GroupInfo();
            headerInfo.setName(department);
            subjects.put(department, headerInfo);
            deptList.add(headerInfo);
        }

        //get the children for the group
        ArrayList<ChildInfo> productList = headerInfo.getProductList();
        //size of the children list
        int listSize = productList.size();
        //add to the counter
        listSize++;

        //create a new child and add that to the group
        ChildInfo detailInfo = new ChildInfo();
        detailInfo.setSequence(String.valueOf(listSize));
        detailInfo.setName(product);
        detailInfo.setStatus(false);
        productList.add(detailInfo);
        headerInfo.setProductList(productList);

        //find the group position inside the list
        groupPosition = deptList.indexOf(headerInfo);
        return groupPosition;
    }
}

ADAPTER

/**
 * Created by RicardoFernandes on 04/03/2017.
 */

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.CheckBox;
import android.widget.TextView;

import java.util.ArrayList;

public class CustomAdapter extends BaseExpandableListAdapter {

    private Context context;
    private ArrayList<GroupInfo> deptList;

    public CustomAdapter(Context context, ArrayList<GroupInfo> deptList) {
        this.context = context;
        this.deptList = deptList;
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        ArrayList<ChildInfo> productList = deptList.get(groupPosition).getProductList();
        return productList.get(childPosition);
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
                             View view, ViewGroup parent) {

        ChildInfo detailInfo = (ChildInfo) getChild(groupPosition, childPosition);
        if (view == null) {
            LayoutInflater infalInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = infalInflater.inflate(R.layout.child_items, null);
        }

        TextView sequence = (TextView) view.findViewById(R.id.sequence);
        sequence.setText(detailInfo.getSequence().trim() + ". ");
        CheckBox childItem = (CheckBox) view.findViewById(R.id.childItem);
        childItem.setText(detailInfo.getName().trim());
        if(childItem.isChecked()){
            childItem.setChecked(true);
        }
        return view;
    }

    @Override
    public int getChildrenCount(int groupPosition) {

        ArrayList<ChildInfo> productList = deptList.get(groupPosition).getProductList();
        return productList.size();

    }

    @Override
    public Object getGroup(int groupPosition) {
        return deptList.get(groupPosition);
    }

    @Override
    public int getGroupCount() {
        return deptList.size();
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isLastChild, View view,
                             ViewGroup parent) {

        GroupInfo headerInfo = (GroupInfo) getGroup(groupPosition);
        if (view == null) {
            LayoutInflater inf = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inf.inflate(R.layout.group_items, null);
        }

        TextView heading = (TextView) view.findViewById(R.id.heading);
        heading.setText(headerInfo.getName().trim());

        return view;
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }

}

GROUP INFO

import java.util.ArrayList;

/**
 * Created by RicardoFernandes on 04/03/2017.
 */

public class GroupInfo {
    private String name;
    private ArrayList<ChildInfo> list = new ArrayList<ChildInfo>();

    public String getName() {
        return name;
    }

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

    public ArrayList<ChildInfo> getProductList() {
        return list;
    }



    public void setProductList(ArrayList<ChildInfo> productList) {
        this.list = productList;
    }
}

儿童信息

/**
 * Created by RicardoFernandes on 04/03/2017.
 */

   public class ChildInfo {

    private String sequence = "";
    private String name = "";
    private boolean status = false;

    public String getSequence() {
        return sequence;
    }

    public void setSequence(String sequence) {
        this.sequence = sequence;
    }

    public String getName() {
        return name;
    }

    public boolean getProductStatus(){
        return true;
    }

    public void setStatus(boolean status) {this.status = status;}

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

    }

activity_etapas.xml - (主要XML)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_etapas"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="@color/colorMarrom"
    android:orientation="vertical">

    <ExpandableListView
        android:id="@+id/simpleExpandableListView"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:divider="#706e6e"
        android:childDivider="#a9afa9"
        android:dividerHeight="1dp"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:paddingBottom="60dp" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:text="Salvar"
            android:layout_height="50dp"
            android:id="@+id/button5"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:background="@mipmap/logo_v_1_5"
            android:elevation="17dp"
            android:backgroundTint="@color/colorMarrom"
            android:layout_width="80dp"
            android:textColor="@android:color/background_light"
            android:textStyle="normal|bold" />
    </RelativeLayout>


</RelativeLayout>

child_items.xml

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

    <TextView
        android:id="@+id/sequence"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:paddingLeft="35sp"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textStyle="normal|bold" />

    <CheckBox
        android:id="@+id/childItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@id/sequence"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:focusable="false"
        android:checked="false" />

</RelativeLayout>

group_items.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:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingEnd="10dp"
    tools:paddingBottom="10dp"
    android:paddingBottom="20dp"
    android:paddingTop="20dp"
    android:paddingRight="10dp">

    <TextView
        android:id="@+id/heading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="35sp"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textStyle="bold" />

</LinearLayout>

2 个答案:

答案 0 :(得分:0)

兄弟做一件事: -

CHILD INFO 类中创建一个getter setter方法

setisChecked(boolean ischecked); getisChecked();

并且,当您选中任何复选框时,调用list.get(position).setisChecked(true); 并且,在你的getChildView方法中执行以下操作: -

---
resources:
  - name: gist
    type: git
    source:
      uri: "git@bitbucket.org:snippets/foo/bar.git"
      branch: master
      private_key: {{private_git_key}}

jobs:
  - name: update
    plan:
      - get: gist
        trigger: true

      - task: update-gist
        config:
          platform: linux
          image_resource:
            type: docker-image
            source: {repository: concourse/bosh-cli}

          inputs:
            - name: gist

          outputs:
            - name: gist-upd
            - name: gist-out

          run:
            path: sh
            args:
              - -exc
              - |
                git config --global user.email "nobody@concourse.ci"
                git config --global user.name "Concourse"
                git clone gist gist-upd
                cd gist-upd
                echo `date` > test
                git commit -am "upd"
                cd ../gist
                echo "foo" > test
                cd ../gist-out
                echo "out" > test

      - put: gist
        params: {repository: gist-upd}

  - name: fetch-updated
    plan:
      - get: gist
        passed: [update]
        trigger: true

      - task: check-gist
        config:
          platform: linux
          image_resource:
            type: docker-image
            source: {repository: alpine}

          inputs:
            - name: gist
            #- name: gist-upd
            #- name: gist-out

          run:
            path: sh
            args:
              - -exc
              - |
                ls -l gist
                cat gist/test
                #ls -l gist-upd
                #cat gist-upd/test
                #ls -l gist-out
                #cat gist-out/test

多数民众赞成,它喜欢编码......

答案 1 :(得分:0)

在getChildView()中,您正在重用视图:

if (view == null) {
    LayoutInflater infalInflater = (LayoutInflater) 
        context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    view = infalInflater.inflate(R.layout.child_items, null);
}

因此,当您重复使用(即滚动或刷新列表时)时,您对复选框所做的任何更改都将可见。

要解决此问题,您需要处理条件语句的两种情况 - 即使用if后跟if,以确保您的视图重置为默认状态。

if (detailInfo.isChecked()){
    childItem.setChecked(true);
} else {
    childItem.setChecked(false);
}

// Equal to

childItem.setChecked(detailInfo.isChecked());

您需要在ChildInfo类中添加一个getter和setter,并使用复选框监听器对其进行更新:

childItem.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
   @Override
   public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        detailInfo.setChecked(isChecked);
   }
});