这是我关于StackOverFlow的第一个问题,我通常总能找到自己的答案,但我真的陷入一个奇怪的问题,我将在这里解释:
我在片段活动中实现了ListView,此listview包含与从SQLLite数据库获取的当前记录相关的类别列表。
一切正常,我创建了一个SimpleCursorAdapter来从数据库中检索数据,并在ListView中正确显示类别。 这个问题与复选框的预填充有关(它是一个多选列表),取决于我如何尝试预先检查复选框,我得到2个案例:
首先,复选框已经过预先检查,但我无法通过点击它们来切换复选框。然后点击切换选中复选框,但不再预先检查它们了......
以下是我遇到问题的代码部分:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//super.onCreate(savedInstanceState);
View v = inflater.inflate(R.layout.rate_fragment, container,false);
dbCategories = "";
displayCategories = resources.getText(R.string.no_categories).toString();
/** INITIALIZATION */
mViewSwitcher = (ViewSwitcher)v.findViewById(R.id.profileSwitcher);
/** Edition view */
rateGroup = (RadioGroup)v.findViewById(R.id.rate_group);
rateOne = (RadioButton)v.findViewById(R.id.one_button);
rateOne.setTag(1);
rateTwo = (RadioButton)v.findViewById(R.id.two_button);
rateTwo.setTag(2);
rateThree = (RadioButton)v.findViewById(R.id.three_button);
rateThree.setTag(3);
rateFour = (RadioButton)v.findViewById(R.id.four_button);
rateFour.setTag(4);
rateFive = (RadioButton)v.findViewById(R.id.five_button);
rateFive.setTag(5);
descET = (EditText)v.findViewById(R.id.editdescription);
descTextSize = descET.getTextSize();
descET.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
categoriesTV_edit = (TextView)v.findViewById(R.id.edit_categories);
categoriesBT = (Button) v.findViewById(R.id.select_categories);
categoriesBT.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
View categoriesListTitle = getActivity().getLayoutInflater().inflate(R.layout.category_list_title, null);
AlertDialog.Builder alt_bld = new AlertDialog.Builder(v.getContext()).setCustomTitle(categoriesListTitle);
categories = db.getAllCategoriesByRate(currentRate);
categoriesList = new ListView(getActivity());
categoriesList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
categoriesList.setClickable(true);
String[] fromColumns = new String[] {
DatabaseHandler.CATEGORY_NAME
};
int[] toViews = new int[]{
R.id.cat_checked
};
//mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_multiple_choice, categories, fromColumns, toViews, 0);
mAdapter = new SimpleCursorAdapter(getActivity(), R.layout.category_item, categories, fromColumns, toViews, 0);
mAdapter.setViewBinder(new ViewBinder() {
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (columnIndex == 1) {
CheckedTextView categRow = (CheckedTextView) view;
String catName = cursor.getString(1);
mAdapter.setViewText((TextView) view, catName);
int catChecked = cursor.getInt(2);
//boolean checkedCat = catChecked==1;
//categoriesList.setItemChecked(cursor.getPosition(),checkedCat);
categRow.setChecked(catChecked==1);
int catID = cursor.getInt(0);
categRow.setTag(catID);
return true;
}
else {
return false;
}
}
});
categoriesList.setAdapter(mAdapter);
alt_bld.setView(categoriesList);
要拥有一个或另一个案例,全部取决于这两行:
//boolean checkedCat = catChecked==1;
//categoriesList.setItemChecked(cursor.getPosition(),checkedCat);
如果他们被评论,则不会预先选中复选框,但点击的切换功能正常。但是如果我对这些行进行评论,则切换不再起作用,但是类别是预先检查的。
我也不明白这条线不起作用:
categRow.setChecked(catChecked==1);
但是这个工作得很好(我成功检索了标签):
categRow.setTag(catID);
所以我希望有人会成功向我解释我做错了什么,我想这里有些东西我误解了......
注意:我从游标“categories”中获得3列,第一列是类别的ID,第二列是名称,第三列是状态:是否已选中(1或0)。
提前感谢您的时间。
答案 0 :(得分:0)
最后我最终创建了自己的自定义适配器,这样我至少可以更容易地理解发生的事情。
我必须创建几个多选列表,其中一些填充数据库中的数据,另一些填充来自共享首选项。
对于这个显示来自数据库的数据,我创建了以下适配器(我注释掉了关于图标的行,因为我还没有设置它们):
public class CategoriesLVAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
private List<Category> categoriesList;
// Constructor
public CategoriesLVAdapter(Context c, List<Category> categories_list){
mContext = c;
mInflater = LayoutInflater.from(c);
categoriesList = categories_list;
}
public List<Category> getCategoriesList(){
return categoriesList;
}
@Override
public int getCount() {
return categoriesList.size();
}
@Override
public Object getItem(int position) {
return categoriesList.get(position);
}
@Override
public long getItemId(int position) {
return categoriesList.get(position).getID();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.categories_list_row, null);
//convertView.setLayoutParams(new ListView.LayoutParams(200, 90));
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.categories_list_row_tv);
//holder.icon = (ImageView) convertView.findViewById(R.id.categories_list_row_iv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//holder.icon.setImageResource(categoriesList.get(position).getDrawableID());
//holder.icon.setAdjustViewBounds(true);
//holder.icon.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.title.setText(categoriesList.get(position).getName());
return convertView;
}
static class ViewHolder {
TextView title;
//ImageView icon;
}
}
在我的活动中,当调用AlertDialog来填充ListView时,我使用此适配器,然后使用共享首选项中保存的最后一个类别预先选择类别:
private void categoriesFilter(){
AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
alt_bld.setTitle(resources.getText(R.string.select_categories).toString());
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.categories_list,(ViewGroup) findViewById(R.id.categories_layout_root));
categoriesLV = (ListView) layout.findViewById(R.id.categories_list);
alt_bld.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String selectedCategoriesString = getSelectedValues(categoriesLV);
//Update the shared preferences
prefs.edit().putString(RateDayApplication.PREF_KEY_CATEGORIES, selectedCategoriesString).commit();
updateFilterDisplay(resources.getText(R.string.cat_title).toString(), selectedCategoriesString, searchedCategoriesTV, "Category");
}
});
alt_bld.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
String selectedCategoriesString = prefs.getString(RateDayApplication.PREF_KEY_CATEGORIES, new String());
categoriesLV.setAdapter(new CategoriesLVAdapter(this, categoriesList));
String[] selectedCategoriesArray = selectedCategoriesString.split(",");
int categoriesLVLength = categoriesLV.getCount();
for(int i = 0; i < categoriesLVLength; i++){
int categoryID = ((Category) categoriesLV.getItemAtPosition(i)).getID();
if(Arrays.asList(selectedCategoriesArray).contains(String.valueOf(categoryID))){
categoriesLV.setItemChecked(i, true);
}
}
alt_bld.setView(layout);
AlertDialog alert = alt_bld.create();
alert.show();
}
最后,这是我从数据库处理程序调用的函数,以获取catagories列表:
// Getting All Categories By ID desc
public List<Category> getCategoriesList() {
String selectQuery = "SELECT " + CATEGORY_ID + ", " + CATEGORY_NAME + " FROM " + CATEGORY_TABLE + " ORDER BY " + CATEGORY_ID + " ASC";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
List<Category> categoriesList = new ArrayList<Category>();//String[] categoriesList = {};
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Category category = new Category(cursor.getInt(0), cursor.getString(1), false);
categoriesList.add(category);
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return categoriesList;
}
我认为我之前遇到的问题是因为函数“setItemChecked”有点误导,因为它并不意味着必须检查任何内容。 当您使用“setItemChecked”函数时,列表视图中的项目将被选中,带或不带复选框(我的行只包含文本视图)。
我列表中选择的行以不同的颜色显示,在我看来,这对于一个简单的多选列表来说已经足够了。
我使用的布局非常简单,“categories_list”包含LinearLayout中的ListView,“categories_list_row”包含LinearLayout中的TextView。
希望它可以引导某人!