編輯:Android開發實例
在使用ListView時,一般為了性能的提升,都會使用ViewHolder,也就是Item的View實現復用。
現在的問題是,當在ListView的Item中包含CheckBox,並且CheckBox的事件處理監聽器是holder.checkbox.setOnCheckedChangeListener()時,會出現第一項開始未選中,當第二項選中時第一項也跟著選中,這顯然不是我們想要的結果。
出現這個問題的原因是第一項和第二項用的是同一個Item,當第二項選中時,CheckBox的當前狀態為選中,這時setOnCheckedChangeListener裡面會改變第一項關聯的實體對象的屬性(引用類型,變量A、B都引用同一個對象AA,當A把AA的某個屬性值修改了,B再次訪問時,AA對象的那個屬性的值為A引用改後的值),代碼如下:
- holder.checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- driver.setSelected(isChecked);
- }
- });
解決辦法:
1、在ListViewAdapter初始化時,將對象中有關CheckBox是否選中的屬性存儲起來。
- selectedMap = new HashMap<Integer, Boolean>();
- int size = mPersons.size();
- for (int i = 0; i < size; i++) {
- selectedMap.put(i, mPersons.get(i).isSelected());
- }
2、去掉CheckBox的holder.checkbox.setOnCheckedChangeListener(){}事件監聽器
3、在Adapter裡的 public View getView(final int position, View convertView, ViewGroup parent){}方法體裡面,當前的CheckBox是否選中狀態,由之前初始化時保存的對象屬性值控制,代碼如下:
- boolean selected = selectedMap.get(position);
- holder.checkbox.setChecked(selected);
3、用戶點擊ListView的Item時,改變CheckBox的狀態,代碼如下:
- convertView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- checkbox.toggle();
- selectedMap.put(position, checkbox.isChecked());
- driver.setSelected(checkbox.isChecked());
- }
- });
數據適配器ListViewAdapter的完整代碼:
- package com.easipass.cloud.ccp.adapter;
- import java.util.ArrayList;
- import java.util.HashMap;
- 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.Filter;
- import android.widget.Filterable;
- import android.widget.ImageView;
- import android.widget.TextView;
- import com.easipass.R;
- import com.easipass.cloud.ccp.entity.UserInfo;
- /**
- * 用戶列表數據適配器
- *
- * @author android_ls
- */
- public final class UserListViewAdapter extends BaseAdapter implements Filterable {
- private LayoutInflater inflater;
- private MyFilter myFilter;
- private final Object mLock = new Object();
- private ArrayList<UserInfo> mPersons;
- private ArrayList<UserInfo> mCheckValues;
- public HashMap<Integer, Boolean> selectedMap;
- public UserListViewAdapter(Context context, ArrayList<UserInfo> cms) {
- inflater = LayoutInflater.from(context);
- mPersons = cms;
- selectedMap = new HashMap<Integer, Boolean>();
- int size = mPersons.size();
- for (int i = 0; i < size; i++) {
- selectedMap.put(i, mPersons.get(i).isSelected());
- }
- }
- @Override
- public int getCount() {
- return mPersons.size();
- }
- @Override
- public Object getItem(int arg0) {
- return mPersons.get(arg0);
- }
- @Override
- public long getItemId(int position) {
- return position;
- }
- @Override
- public View getView(final int position, View convertView, ViewGroup parent) {
- ViewHolder holder = null;
- if (convertView == null) {
- convertView = inflater.inflate(R.layout.ccp_carmanager_lv_item, null);
- holder = new ViewHolder();
- holder.text1 = (TextView) convertView.findViewById(R.id.tv_name);
- holder.text2 = (TextView) convertView.findViewById(R.id.tv_phnoe);
- holder.checkbox = (CheckBox) convertView.findViewById(R.id.checkbox);
- holder.imageView = (ImageView) convertView.findViewById(R.id.iv_icon);
- convertView.setTag(holder);
- } else {
- holder = (ViewHolder) convertView.getTag();
- }
- final UserInfo driver = mPersons.get(position);
- holder.text1.setText(driver.getName());
- holder.text2.setText(driver.getPhoneNumber());
- // TODO 測試
- holder.imageView.setBackgroundResource(Integer.valueOf(driver.getIconUrl()));
- holder.checkbox.setVisibility(View.VISIBLE);
- boolean selected = selectedMap.get(position);
- holder.checkbox.setChecked(selected);
- final CheckBox checkbox = holder.checkbox;
- convertView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- checkbox.toggle();
- selectedMap.put(position, checkbox.isChecked());
- driver.setSelected(checkbox.isChecked());
- }
- });
- if (selected) {
- convertView.setClickable(false);
- }
- return convertView;
- }
- @Override
- public Filter getFilter() {
- if (myFilter == null) {
- myFilter = new MyFilter();
- }
- return myFilter;
- }
- class MyFilter extends Filter {
- @Override
- protected FilterResults performFiltering(CharSequence prefix) {
- FilterResults results = new FilterResults();
- if (mCheckValues == null) {
- synchronized (mLock) {
- mCheckValues = new ArrayList<UserInfo>(mPersons);
- }
- }
- if (prefix == null || prefix.length() == 0) {
- synchronized (mLock) {
- ArrayList<UserInfo> list = new ArrayList<UserInfo>(mCheckValues);
- results.values = list;
- results.count = list.size();
- }
- } else {
- String prefixString = prefix.toString().toLowerCase();
- final ArrayList<UserInfo> values = mCheckValues;
- final int count = values.size();
- final ArrayList<UserInfo> newValues = new ArrayList<UserInfo>(count);
- for (int i = 0; i < count; i++) {
- final UserInfo value = (UserInfo) values.get(i);
- if (value.getName().contains(prefixString)) {
- newValues.add(value);
- }
- }
- results.values = newValues;
- results.count = newValues.size();
- }
- return results;
- }
- @SuppressWarnings("unchecked")
- @Override
- protected void publishResults(CharSequence constraint, FilterResults results) {
- mPersons = (ArrayList<UserInfo>) results.values;
- if (results.count > 0) {
- notifyDataSetChanged();
- } else {
- notifyDataSetInvalidated();
- }
- }
- }
- static class ViewHolder {
- public TextView text1;
- public TextView text2;
- public ImageView imageView;
- public CheckBox checkbox;
- }
- }
Activity中onCreate()裡的寫法:
- mSearchToolbar = (SearchToolbar) this.findViewById(R.id.top_search_toolbar);
- mListView = (ListView) this.findViewById(R.id.listview);
- mDriverListAdapter = new UserListViewAdapter(this, driverList);
- mListView.setAdapter(mDriverListAdapter);
- mSearchToolbar.setFilter(mDriverListAdapter.getFilter());
SearchToolbar類的代碼:
- package com.easipass.custom.view;
- import android.content.Context;
- import android.text.Editable;
- import android.text.TextWatcher;
- import android.util.AttributeSet;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.widget.AutoCompleteTextView;
- import android.widget.FrameLayout;
- import android.widget.ImageView;
- import android.widget.RelativeLayout;
- import com.easipass.R;
- /**
- * 功能描述:自定義搜索框組件
- * @author android_ls
- */
- public class SearchToolbar extends FrameLayout {
- private RelativeLayout topSearchToolbar;
- /**
- * 頂部自動補全文本輸入框
- */
- private AutoCompleteTextView autoSearch;
- /**
- * 清除搜索結果按鈕
- */
- private ImageView btnClearSearch;
- public SearchToolbar(Context context) {
- super(context);
- setupViews();
- }
- public SearchToolbar(Context context, AttributeSet attrs) {
- super(context, attrs);
- setupViews();
- }
- private void setupViews() {
- final LayoutInflater mLayoutInflater = LayoutInflater.from(getContext());
- topSearchToolbar = (RelativeLayout) mLayoutInflater.inflate(R.layout.top_search_toolbar, null);
- addView(topSearchToolbar);
- btnClearSearch = (ImageView) topSearchToolbar.findViewById(R.id.iv_search_clear);
- autoSearch = (AutoCompleteTextView) topSearchToolbar.findViewById(R.id.auto_search);
- }
- public void setFilter(final android.widget.Filter filter) {
- autoSearch.addTextChangedListener(new TextWatcher() {
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- String filterWord = autoSearch.getText().toString().trim();
- filter.filter(filterWord);
- }
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- // TODO Auto-generated method stub
- }
- @Override
- public void afterTextChanged(Editable s) {
- // TODO Auto-generated method stub
- }
- });
- btnClearSearch.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- autoSearch.setText(null);
- }
- });
- }
- }
top_search_toolbar.xml文件:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/top_search_bar"
- android:layout_width="match_parent"
- android:layout_height="45dip"
- android:background="@drawable/search_bar_bg"
- android:visibility="visible" >
- <AutoCompleteTextView
- android:id="@+id/auto_search"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_marginLeft="5dip"
- android:layout_marginRight="5dip"
- android:background="@drawable/search_bar_edit_normal"
- android:completionThreshold="1"
- android:drawableLeft="@drawable/search_bar_icon_normal"
- android:dropDownHorizontalOffset="30dip"
- android:dropDownVerticalOffset="9dip"
- android:dropDownWidth="210dip"
- android:singleLine="true"
- android:textSize="15sp" />
- <ImageView
- android:id="@+id/iv_search_clear"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:layout_marginRight="12dip"
- android:layout_marginTop="-1dip"
- android:background="@drawable/btn_search_clear_selector" />
- </RelativeLayout>
轉自:http://blog.csdn.net/android_ls/article/details/8644247
Android作為一個偉大的系統,自然提供了設置默認打開程序的實現.在這篇文章中,我會介紹如何在Android系統中設置默認的程序. 在設置默認程序之前,無非有兩
JSON代表JavaScript對象符號。它是一個獨立的數據交換格式,是XML的最佳替代品。本章介紹了如何解析JSON文件,並從中提取所需的信息。Android提供了四個
點九圖片的拉伸區域不難理解,顯示內容區域是怎樣的?.9 ,是andriod平台的應用軟件開發裡的一種特殊的圖片形式,文件擴展名為:.9.png智能手機中有自動橫屏
做了個Android項目,需要接入新浪微博,實現時也順帶著研究了下騰訊微博和人