我有一个带有复选框和文本框的列表视图。当我勾选复选框并上下滚动时,它会自动取消选中。
如何在listview中解决这个问题?请给我解决方案。
下面我把我的屏幕截图和代码。
activity_main.xml中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/lvMain"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="@+id/btnSelectAll"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="Select All" >
</Button>
</LinearLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<CheckBox
android:id="@+id/cbItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:buttonTint="#000000">
</CheckBox>
<TextView
android:id="@+id/tvItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000">
</TextView>
</LinearLayout>
MainActivity.java
package com.example.checkallcheckbox;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
public class MainActivity extends Activity {
ListView lvMain;
String[] name = { "Jenis", "Pratik", "Jaydeep", "Hiren", "Himansu",
"yagnik", "Atul", "Prakas", "Nihal", "Darshan", "Chetan", "Sagar",
"Nikhil", "Sanket", "Rahul", "Jigar" };
Button btnSelectAll;
boolean isSelectAll = true;
ListAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvMain = (ListView) findViewById(R.id.lvMain);
btnSelectAll = (Button) findViewById(R.id.btnSelectAll);
btnSelectAll.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if(isSelectAll)
{
adapter = new ListAdapter(getApplicationContext(), name, true);
lvMain.setAdapter(adapter);
adapter.notifyDataSetChanged();
btnSelectAll.setText("ClearAll");
isSelectAll=false;
}
else
{
adapter = new ListAdapter(getApplicationContext(), name, false);
lvMain.setAdapter(adapter);
adapter.notifyDataSetChanged();
btnSelectAll.setText("CheckAll");
isSelectAll=true;
}
}
});
adapter = new ListAdapter(getApplicationContext(), name,false);
lvMain.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
ListAdapter.java
package com.example.checkallcheckbox;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.TextView;
public class ListAdapter extends BaseAdapter {
Context mContext;
String[] name;
private static LayoutInflater inflater = null;
Boolean state=false;
public ListAdapter(Context c, String[] name, boolean isSelectAll) {
// TODO Auto-generated constructor stub
mContext = c;
this.name = name;
inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
state=isSelectAll;
}
@Override
public int getCount() {
return name.length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public class ViewHolder {
TextView tvName;
CheckBox cbName;
}
@Override
public View getView(int position, View convertView, ViewGroup arg2) {
// TODO Auto-generated method stub
ViewHolder viewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item, null);
viewHolder = new ViewHolder();
viewHolder.tvName = (TextView) convertView
.findViewById(R.id.tvItem);
viewHolder.cbName = (CheckBox) convertView
.findViewById(R.id.cbItem);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.tvName.setText(name[position]);
if(state){
viewHolder.cbName.setChecked(true);
}else{
viewHolder.cbName.setChecked(false);
}
return convertView;
}
}
答案 0 :(得分:2)
问题是因为正在重新制作ListView视图。当你在屏幕外滚动它们时,android不会保留它们(列表可能真的很长,所以这意味着你看不到很多看不见的视图)。
因此,每当您在屏幕上滚动某个项目时,Android会再次调用getView
并返回一个未选中复选框的视图。
您需要做的是在每个列表项上设置一个单击/检查的侦听器,以便能够记住它们何时被选中。然后,当android要求您查看视图时,您可以检查是否应该检查它。
您可以看到getItem
方法已经在那里为您提供帮助。您可以尝试覆盖ArrayAdapter
,因为这样可以存储一些可以保持“点击”状态的简单对象。请参阅:http://developer.android.com/reference/android/widget/ArrayAdapter.html
这就是为什么Aditya会问你模特课的位置。目前您只有一个学生列表,您想要的是学生列表以及他们是否已被选中。也许这样的课程:
class Student
{
private String mName;
public Boolean selected;
public Student(String name)
{
mName = name;
}
public String getName()
{
return mName;
}
}
然后你可以有一个这样的数组。单击某个项目时,您会在相关学生项目上设置selected
。
您的getView
可能如下所示:
@Override
public View getView(int position, View convertView, ViewGroup arg2) {
// TODO Auto-generated method stub
ViewHolder viewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item, null);
viewHolder = new ViewHolder();
viewHolder.tvName = (TextView) convertView
.findViewById(R.id.tvItem);
viewHolder.cbName = (CheckBox) convertView
.findViewById(R.id.cbItem);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
Student thisStudent = students[position];
viewHolder.tvName.setText(thisStudent.getName());
if(state || thisStudent.selected){
viewHolder.cbName.setChecked(true);
}else{
viewHolder.cbName.setChecked(false);
}
return convertView;
}
有很多关于此的指南,这里有一个这样的指南,解释了视图回收如何在列表中工作(您的问题)以及如何使用ArrayAdapter
https://github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView
答案 1 :(得分:1)
声明一个布尔数组,用于保存每个列表项的选中状态。
在构造函数中初始化(使用for循环)此数组(全部分配为false)。
记录setOnCheckedChangeListener()
内部的更改。
在setChecked()
之后致电setOnCheckedChangeListener()
。
答案 2 :(得分:0)
尝试使用RecycleView,
public class CardViewActivity extends ActionBarActivity {
private Toolbar toolbar;
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private List<Student> studentList;
private Button btnSelection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
btnSelection = (Button) findViewById(R.id.btnShow);
studentList = new ArrayList<Student>();
for (int i = 1; i <= 15; i++) {
Student st = new Student("Student " + i, "androidstudent" + i
+ "@gmail.com", false);
studentList.add(st);
}
if (toolbar != null) {
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("Android Students");
}
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
// create an Object for Adapter
mAdapter = new CardViewDataAdapter(studentList);
// set the adapter object to the Recyclerview
mRecyclerView.setAdapter(mAdapter);
btnSelection.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String data = "";
List<Student> stList = ((CardViewDataAdapter) mAdapter)
.getStudentist();
for (int i = 0; i < stList.size(); i++) {
Student singleStudent = stList.get(i);
if (singleStudent.isSelected() == true) {
data = data + "\n" + singleStudent.getName().toString();
/*
* Toast.makeText( CardViewActivity.this, " " +
* singleStudent.getName() + " " +
* singleStudent.getEmailId() + " " +
* singleStudent.isSelected(),
* Toast.LENGTH_SHORT).show();
*/
}
}
Toast.makeText(CardViewActivity.this,
"Selected Students: \n" + data, Toast.LENGTH_LONG)
.show();
}
});
}
有关详情,请参阅this
对于ListView,请参阅this
答案 3 :(得分:0)
如果您使用的是apply plugin: 'com.android.library'
apply plugin: 'com.jfrog.artifactory'
apply plugin: 'maven-publish'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
minSdkVersion 9
targetSdkVersion 23
versionCode 1
versionName "0.0.1"
}
publishNonDefault true
buildTypes {
debug {
minifyEnabled false
debuggable true
}
release {
minifyEnabled false
debuggable false
}
snapshot {
minifyEnabled false
debuggable false
}
}
}
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
classifier = 'javadoc'
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}
artifacts {
archives androidSourcesJar
archives androidJavadocsJar
}
publishing {
publications {
android.buildTypes.all { variant ->
"${variant.name}"(MavenPublication) {
def manifestParser = new com.android.builder.core.DefaultManifestParser()
groupId manifestParser.getPackage(android.sourceSets.main.manifest.srcFile)
if("${variant.name}".equalsIgnoreCase("release")){
version = manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile)
}else if ("${variant.name}".equalsIgnoreCase("debug")){
version = manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile).concat("-${variant.name}".toUpperCase().concat("-SNAPSHOT"))
}else{
version = manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile).concat("-${variant.name}".toUpperCase())
}
artifactId project.getName()
artifact("$buildDir/outputs/aar/${project.getName()}-${variant.name}.aar")
artifact androidJavadocsJar
pom.withXml {
def dependencies = asNode().appendNode('dependencies')
configurations.getByName("_releaseCompile").getResolvedConfiguration().getFirstLevelModuleDependencies().each {
def dependency = dependencies.appendNode('dependency')
dependency.appendNode('groupId', it.moduleGroup)
dependency.appendNode('artifactId', it.moduleName)
dependency.appendNode('version', it.moduleVersion)
}
}
}
}
}
}
android.buildTypes.all { variant ->
model {
tasks."generatePomFileFor${variant.name.capitalize()}Publication" {
destination = file("$buildDir/publications/${variant.name}/generated-pom.xml")
}
}
def publicationName = "${variant.name}"
def taskName = "${variant.name}Publication"
task "$taskName"() << {
artifactoryPublish {
doFirst {
tasks."generatePomFileFor${variant.name.capitalize()}Publication".execute()
publications(publicationName)
clientConfig.publisher.repoKey = "${variant.name}".equalsIgnoreCase("release") ? "libs-release-local" :
"libs-snapshot-local"
}
}
}
tasks."assemble${variant.name.capitalize()}".dependsOn(tasks."$taskName")
}
artifactory {
contextUrl = 'http://172.16.32.220:8081/artifactory'
publish {
repository {
username = "admin"
password = "password"
}
defaults {
publishPom = true
publishArtifacts = true
properties = ['qa.level': 'basic', 'dev.team': 'core']
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
}
,那么您的适配器应该实现listView
,以便在复选框状态中保存更改。在您必须实现OnCheckedChangeListener
的方法(在getView()中编写)中,您必须从SharedPreferences获取该复选框的状态并更新它。
如果你寻找这种方法,你会发现一些例子,这里是one
答案 4 :(得分:0)
我能够解决我的问题,这可能对您也有帮助。
当在RecyclerView上绑定的复选框的ArrayList中滚动时,我遇到了自动选择和取消选择的相同问题。
问题是因为在我的RecyclerView适配器中,我在将数据绑定到视图时将ArrayList中的每个复选框项设置了一个OnCheckedChange侦听器,这使复选框在滚动时自动选择和取消选择自身。
请参阅下面的我的初始代码;
holder.subCategoriesCheckBox.setOnCheckedChangeListener((compoundButton, b) -> {
if (holder.subCategoriesCheckBox.isChecked()){
holder.subCategoriesCheckBox.setChecked(false);
subCategory.setSelected(false);
}
else {
holder.subCategoriesCheckBox.setChecked(true);
subCategory.setSelected(true);
}
});
解决方案是在复选框上设置一个OnClickListener,而不是如下所示的OncheckedChange侦听器;
holder.subCategoriesCheckBox.setOnClickListener(view -> {
if (holder.subCategoriesCheckBox.isSelected()){
holder.subCategoriesCheckBox.setSelected(false);
subCategory.setSelected(false);
}
else {
holder.subCategoriesCheckBox.setSelected(true);
subCategory.setSelected(true);
}
});
希望这会让您对自己的想法有所了解
答案 5 :(得分:0)
您应该使用 recyclerView 并控制列表中的检查状态,您可以添加一个 isDefault 布尔值是井,它会在不同行发生更改时更新。 我有一个教程here
holder.checkBox.setOnCheckedChangeListener { _, isChecked ->
if (item.isChecked != isChecked) {
setCheckboxTextColor(isChecked, holder)
item.isChecked = isChecked
when (item.rowType) {
RowType.TopHeader -> {
val indexList = mutableListOf<Int>()
productList.filter { it.rowType != RowType.TopHeader }.forEach {
it.isChecked = isChecked
indexList.add(productList.indexOf(it))
}
indexList.forEach {
notifyItemChanged(it)
}
}
RowType.CatHeader -> {
val indexList = mutableListOf<Int>()
productList.filter { it.rowType == RowType.ProductRow && it.category == item.category }
.forEach {
it.isChecked = isChecked
indexList.add(productList.indexOf(it))
}
indexList.forEach {
notifyItemChanged(it)
}
isAllItemsSameStatus() //for header
}
RowType.ProductRow -> {
isAllItemsSameStatus(item.category) //set prep area accordingly
isAllItemsSameStatus() //set top header
}
}
}
}
}
private fun setCheckboxTextColor(isChecked: Boolean, holder: TableViewHolder) {
if (isChecked) {
holder.checkBox.setTextColor(context.getColor(R.color.black))
} else {
holder.checkBox.setTextColor(context.getColor(R.color.grey))
}
}
private fun isAllItemsSameStatus(cat: String? = null) {
val row : RowModel
var isChecked: Boolean = true
var position: Int = 0
if(cat != null){
val catRow = productList.find { it.rowType == RowType.CatHeader && it.category == cat }
catRow?.let {
val subList = productList.filter { it.category == it.category && it.rowType == RowType.ProductRow }
isChecked = subList.filter { it.isChecked }.size == subList.size
position = productList.indexOf(catRow)
}
if(catRow == null)
return
else
row = catRow
}
else{
row = productList[0]
isChecked = productList.filter { it.rowType != RowType.TopHeader && it.isChecked }.size == productList.size - 1
position = 0
}
updateHeader(row, isChecked, position)
}
private fun updateHeader(item: RowModel, isChecked: Boolean, position: Int) {
if (item.isChecked != isChecked) // no need to update if no change
{
item.isChecked = isChecked
notifyItemChanged(position)
}
}