10

好的我有一個多選ListView,工作正常。我選中聯繫人的方框(保存在String []中),並可以返回正確的值。由於有些人有一堆聯繫人,我想創建一個搜索欄,類似於Android電話簿中的一個。我創建了一個EditText並將其對齊到我的列表上方。我在StackOverflow中找到了過濾代碼,它的功能非常好。Multiple Choice Searchable ListView

我的問題:

當篩選某人的名字了,和你選擇的名字,當你無論是從EditText上空格鍵或繼續打字,你選擇的名稱的正確位置不會被保存。例如,如果我開始輸入「Adam」並選擇「Ada」並選擇它,如果我退格鍵入「Carol」,則選擇「Ada」所處的任何位置。它通過點擊(比方說2)收集「亞當」所處的位置,並且當列表恢復時,檢查該位置(2),即使亞當不在那裏。我需要一種方法來收集名稱..然後當列表恢復或搜索時,名稱亞當被檢查,而不是位置亞當以前在。除了創建大量數組之外,我絕對沒有想法,並且可以真正使用一些幫助。以下是我正在使用的一些代碼:

@Override 
     public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.contacts_list); 


     myListView = (ListView)findViewById(android.R.id.list); 
     search_EditText = (EditText) findViewById(R.id.search_EditText); 
     search_EditText.addTextChangedListener(filterTextWatcher); 

     adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, ContactsList); 
     setListAdapter(adapter); 

     myListView.setItemsCanFocus(false); 
     getListView().setChoiceMode(2); 
     myListView.setTextFilterEnabled(true); 
     myListView.setFastScrollEnabled(true); 
     myListView.invalidate(); 
} 

    private TextWatcher filterTextWatcher = new TextWatcher() { 
     public void afterTextChanged(Editable s) { 

     } 

     public void beforeTextChanged(CharSequence s, int start, int count, 
       int after) { 

     } 

     public void onTextChanged(CharSequence s, int start, int before, 
       int count) { 

      adapter.getFilter().filter(s); 

     } 

    }; 
+0

你有沒有管理,以保持檢查的項目狀態過濾器? – 2012-09-12 19:06:37

+0

@JonasAlves我發佈了我粗略的解決方案。它可能無法滿足您的需求,它最初是爲SDK 7編寫的(我很早以前就寫過它),但您可能會發現它很有用 – burmat 2012-09-13 00:53:25

回答

8

我從來沒有找到比我將在下面列出的方法更好的方法。我不再使用這些代碼了,如果有更好的解決方案,我希望有人將它發佈到某處。

我最終做的是創建一個ArrayList來保存選定的名稱。如果選擇名稱,名稱將被推入ArrayList,並且如果未選中該名稱,則會從列表中彈出該名稱。當選擇afterTextChanged時,將迭代列表,並檢查名稱是否當前列在適配器中。當您完成選擇過程並想繼續時,我清除EditText以清除過濾器,因此在ListView中填充完整列表,並將所有聯繫人設置爲選中(如果它們存在於ArrayList中)。

請注意,我用一個自定義適配器聯繫人,只有列表中的名稱列表,因此,如果您使用其它類型的數據,該解決方案可能會更加混亂了,我看這個方法被攻擊的解決方案:

/** Used for filter **/ 
private TextWatcher filterTextWatcher = new TextWatcher() { 

    public void beforeTextChanged(CharSequence s, int start, int count, int after) { 

     ListView listview = getListView(); 

     SparseBooleanArray checked = listview.getCheckedItemPositions(); 
     for (int i = 0; i < ContactsList.length; i++) { 
      if (checked.get(i) == true) { 
       Object o = getListAdapter().getItem(i); 
       String name = o.toString(); 
       // if the arraylist does not contain the name, add it 
       if (selected.contains(name)){ 
        // Do Nothing 
       } else { 
        selected.add(name); 
       } 
      } 
     }   
    } //<-- End of beforeTextChanged 

    public void onTextChanged(CharSequence s, int start, int before, int count) {   
     adapter.getFilter().filter(s);    
    } //<-- End of onTextChanged 

    public void afterTextChanged(Editable s) { 
     ListView listview = getListView(); 
     // Uncheck everything: 
     for (int i = 0; i < listview.getCount(); i++){ 
      listview.setItemChecked(i, false);     
     } 

     adapter.getFilter().filter(s, new Filter.FilterListener() { 
      public void onFilterComplete(int count) { 
       adapter.notifyDataSetChanged(); 
       ListView listview = getListView(); 
       for (int i = 0; i < adapter.getCount(); i ++) { 
        // if the current (filtered) 
        // listview you are viewing has the name included in the list, 
        // check the box 
        Object o = getListAdapter().getItem(i); 
        String name = o.toString(); 
        if (selected.contains(name)) { 
         listview.setItemChecked(i, true); 
        } else { 
         listview.setItemChecked(i, false); 
        } 
       } 

      } 
     });   
    } //<-- End of afterTextChanged 

}; //<-- End of TextWatcher 

您不希望在使用過濾器時使用索引,因爲索引1可能是一個ListView中的某個東西,並且在更改過濾器時可能是另一個ListView項目。

3

您可以創建Android項目,並添加這些文件:

RES /佈局 - > list_row.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:background="#3c3c3c" 
    android:orientation="horizontal" 
    android:padding="8dp" > 
    <ImageView 
     android:id="@+id/contactimage" 
     android:layout_width="48dp" 
     android:layout_height="48dp" 
     android:layout_marginRight="8dp" 
     android:background="@drawable/ic_launcher" 
     android:contentDescription="@string/app_name" 
     android:scaleType="centerInside" /> 
    <RelativeLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_centerInParent="true" 
     android:layout_toLeftOf="@+id/contactcheck" 
     android:layout_toRightOf="@+id/contactimage" > 
     <TextView 
      android:id="@+id/contactname" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:singleLine="true" 
      android:text="Contact Name" 
      android:textColor="#000" 
      android:textIsSelectable="false" 
      android:textSize="18dp" 
      android:textStyle="bold" /> 
     <TextView 
      android:id="@+id/contactno" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_below="@+id/contactname" 
      android:singleLine="true" 
      android:text="" 
      android:textColor="#2689e0" 
      android:textIsSelectable="false" 
      android:textSize="14dp" /> 
    </RelativeLayout> 
    <CheckBox 
     android:id="@+id/contactcheck" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentRight="true" 
     android:layout_centerInParent="true" 
     android:layout_marginLeft="8dp" /> 
</RelativeLayout> 

RES /佈局 - > activity_main.xml中

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 
    <EditText 
     android:id="@+id/input_search" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:layout_alignParentTop="true" 
     android:layout_centerInParent="true" 
     android:hint="Search Contacts" 
     android:textSize="18dp" /> 
    <LinearLayout 
     android:id="@+id/data_container" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_above="@+id/ok_button" 
     android:layout_below="@+id/input_search" 
     android:gravity="center|top" 
     android:orientation="vertical" /> 
    <Button 
     android:id="@+id/ok_button" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_centerInParent="true" 
     android:text=" OK " 
     android:textSize="18dp" /> 
    <RelativeLayout 
     android:id="@+id/pbcontainer" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:background="#55000000" 
     android:clickable="true" 
     android:visibility="gone" > 
     <ProgressBar 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_centerInParent="true" /> 
    </RelativeLayout> 
</RelativeLayout> 

ContactObject。 java

package com.multiselectlistexample; 
public class ContactObject { 

    private String contactName; 
    private String contactNo; 
    private String image; 
    private boolean selected; 
    public String getName() { 
     return contactName; 
    } 
    public void setName(String contactName) { 
     this.contactName = contactName; 
    } 
    public String getNumber() { 
     return contactNo; 
    } 
    public void setNumber(String contactNo) { 
     this.contactNo = contactNo; 
    } 
    public String getImage() { 
     return image; 
    } 
    public void setImage(String image) { 
     this.image = image; 
    } 
    public boolean isSelected() { 
     return selected; 
    } 
    public void setSelected(boolean selected) { 
     this.selected = selected; 
    } 
} 

ContactsListClass.java

package com.multiselectlistexample; 
import java.util.ArrayList; 
public class ContactsListClass { 
    public static final ArrayList<ContactObject> phoneList = new ArrayList<ContactObject>(); 
} 

ContactsAdapter.java

package com.multiselectlistexample; 
import java.io.ByteArrayInputStream; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Locale; 
import android.content.ContentUris; 
import android.content.Context; 
import android.database.Cursor; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.net.Uri; 
import android.provider.ContactsContract.Contacts; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.BaseAdapter; 
import android.widget.CheckBox; 
import android.widget.CompoundButton; 
import android.widget.ImageView; 
import android.widget.TextView; 
public class ContactsAdapter extends BaseAdapter { 
    Context mContext; 
    LayoutInflater inflater; 
    private List<ContactObject> mainDataList = null; 
    private ArrayList<ContactObject> arraylist; 
    public ContactsAdapter(Context context, List<ContactObject> mainDataList) { 

     mContext = context; 
     this.mainDataList = mainDataList; 
     inflater = LayoutInflater.from(mContext); 
     this.arraylist = new ArrayList<ContactObject>(); 
     this.arraylist.addAll(mainDataList); 


    } 
    static class ViewHolder { 
     protected TextView name; 
     protected TextView number; 
     protected CheckBox check; 
     protected ImageView image; 
    } 
    @Override 
    public int getCount() { 
     return mainDataList.size(); 
    } 
    @Override 
    public ContactObject getItem(int position) { 
     return mainDataList.get(position); 
    } 
    @Override 
    public long getItemId(int position) { 
     return position; 
    } 
    public View getView(final int position, View view, ViewGroup parent) { 
     final ViewHolder holder; 
     if (view == null) { 
      holder = new ViewHolder(); 
      view = inflater.inflate(R.layout.list_row, null); 
      holder.name = (TextView) view.findViewById(R.id.contactname); 
      holder.number = (TextView) view.findViewById(R.id.contactno); 
      holder.check = (CheckBox) view.findViewById(R.id.contactcheck); 
      holder.image = (ImageView) view.findViewById(R.id.contactimage); 
      view.setTag(holder); 
      view.setTag(R.id.contactname, holder.name); 
      view.setTag(R.id.contactno, holder.number); 
      view.setTag(R.id.contactcheck, holder.check); 
      holder.check 
        .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
         @Override 
         public void onCheckedChanged(CompoundButton vw, 
           boolean isChecked) { 
          int getPosition = (Integer) vw.getTag(); 
          mainDataList.get(getPosition).setSelected(
            vw.isChecked()); 
         } 
        }); 
     } else { 
      holder = (ViewHolder) view.getTag(); 
     } 
     holder.check.setTag(position); 

     holder.name.setText(mainDataList.get(position).getName()); 
     holder.number.setText(mainDataList.get(position).getNumber()); 

     if(getByteContactPhoto(mainDataList.get(position).getImage())==null){ 
      holder.image.setImageResource(R.drawable.ic_launcher); 
     }else{ 
      holder.image.setImageBitmap(getByteContactPhoto(mainDataList.get(position).getImage())); 
     } 



     holder.check.setChecked(mainDataList.get(position).isSelected()); 
     return view; 
    } 
    public void filter(String charText) { 
     charText = charText.toLowerCase(Locale.getDefault()); 
     mainDataList.clear(); 
     if (charText.length() == 0) { 
      mainDataList.addAll(arraylist); 
     } else { 
      for (ContactObject wp : arraylist) { 
       if (wp.getName().toLowerCase(Locale.getDefault()) 
         .contains(charText)) { 
        mainDataList.add(wp); 
       } 
      } 
     } 
     notifyDataSetChanged(); 
    } 
    public Bitmap getByteContactPhoto(String contactId) { 
     Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(contactId)); 
     Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY); 
     Cursor cursor = mContext.getContentResolver().query(photoUri, 
         new String[] {Contacts.Photo.DATA15}, null, null, null); 
     if (cursor == null) { 
      return null; 
     } 
     try { 
      if (cursor.moveToFirst()) { 
       byte[] data = cursor.getBlob(0); 
       if (data != null) { 
        return BitmapFactory.decodeStream(new ByteArrayInputStream(data)); 
       } 
      } 
     } finally { 
      cursor.close(); 
     } 
     return null; 
     } 

} 

MainActivity。java的

package com.multiselectlistexample; 
import java.util.Collections; 
import java.util.Comparator; 
import java.util.Locale; 
import android.app.Activity; 
import android.content.Context; 
import android.database.Cursor; 
import android.os.Bundle; 
import android.provider.ContactsContract; 
import android.text.Editable; 
import android.text.TextUtils; 
import android.text.TextWatcher; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemClickListener; 
import android.widget.Button; 
import android.widget.CheckBox; 
import android.widget.EditText; 
import android.widget.LinearLayout; 
import android.widget.LinearLayout.LayoutParams; 
import android.widget.ListView; 
import android.widget.RelativeLayout; 
import android.widget.Toast; 
public class MainActivity extends Activity { 
    Context context = null; 
    ContactsAdapter objAdapter; 
    ListView lv = null; 
    EditText edtSearch = null; 
    LinearLayout llContainer = null; 
    Button btnOK = null; 
    RelativeLayout rlPBContainer = null; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     context = this; 
     setContentView(R.layout.activity_main); 
     rlPBContainer = (RelativeLayout) findViewById(R.id.pbcontainer); 
     edtSearch = (EditText) findViewById(R.id.input_search); 
     llContainer = (LinearLayout) findViewById(R.id.data_container); 
     btnOK = (Button) findViewById(R.id.ok_button); 
     btnOK.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View arg0) { 
       // TODO Auto-generated method stub 
       getSelectedContacts(); 
      } 
     }); 
     edtSearch.addTextChangedListener(new TextWatcher() { 
      @Override 
      public void onTextChanged(CharSequence cs, int arg1, int arg2, 
        int arg3) { 
       // When user changed the Text 
       String text = edtSearch.getText().toString() 
         .toLowerCase(Locale.getDefault()); 
       objAdapter.filter(text); 
      } 
      @Override 
      public void beforeTextChanged(CharSequence arg0, int arg1, 
        int arg2, int arg3) { 
       // TODO Auto-generated method stub 
      } 
      @Override 
      public void afterTextChanged(Editable arg0) { 
       // TODO Auto-generated method stub 
      } 
     }); 
     addContactsInList(); 
    } 
    private void getSelectedContacts() { 
     // TODO Auto-generated method stub 
     StringBuffer sb = new StringBuffer(); 
     for (ContactObject bean : ContactsListClass.phoneList) { 
      if (bean.isSelected()) { 
       sb.append(bean.getName()); 
       sb.append(","); 
      } 
     } 
     String s = sb.toString().trim(); 
     if (TextUtils.isEmpty(s)) { 
      Toast.makeText(context, "Select atleast one Contact", 
        Toast.LENGTH_SHORT).show(); 
     } else { 
      s = s.substring(0, s.length() - 1); 
      Toast.makeText(context, "Selected Contacts : " + s, 
        Toast.LENGTH_SHORT).show(); 
     } 
    } 
    private void addContactsInList() { 
     // TODO Auto-generated method stub 
     Thread thread = new Thread() { 
      @Override 
      public void run() { 
       showPB(); 
       try { 
        Cursor phones = getContentResolver().query(
          ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
          null, null, null, null); 
        try { 
         ContactsListClass.phoneList.clear(); 
        } catch (Exception e) { 
        } 
        while (phones.moveToNext()) { 
         String phoneName = phones 
           .getString(phones 
             .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); 
         String phoneNumber = phones 
           .getString(phones 
             .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 
         String phoneImage = phones 
           .getString(phones 
             .getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)); 

         ContactObject cp = new ContactObject(); 


         cp.setName(phoneName); 
         cp.setNumber(phoneNumber); 
         cp.setImage(phoneImage); 
         ContactsListClass.phoneList.add(cp); 
        } 
        phones.close(); 
        lv = new ListView(context); 
        lv.setLayoutParams(new LayoutParams(
          LayoutParams.MATCH_PARENT, 
          LayoutParams.MATCH_PARENT)); 
        runOnUiThread(new Runnable() { 
         @Override 
         public void run() { 
          // TODO Auto-generated method stub 
          llContainer.addView(lv); 
         } 
        }); 
        Collections.sort(ContactsListClass.phoneList, 
          new Comparator<ContactObject>() { 
           @Override 
           public int compare(ContactObject lhs, 
             ContactObject rhs) { 
            return lhs.getName().compareTo(
              rhs.getName()); 
           } 
          }); 
        objAdapter = new ContactsAdapter(MainActivity.this, 
          ContactsListClass.phoneList); 
        lv.setAdapter(objAdapter); 
        lv.setOnItemClickListener(new OnItemClickListener() { 
         @Override 
         public void onItemClick(AdapterView<?> parent, 
           View view, int position, long id) { 
          CheckBox chk = (CheckBox) view 
            .findViewById(R.id.contactcheck); 
          ContactObject bean = ContactsListClass.phoneList 
            .get(position); 
          if (bean.isSelected()) { 
           bean.setSelected(false); 
           chk.setChecked(false); 
          } else { 
           bean.setSelected(true); 
           chk.setChecked(true); 
          } 
         } 
        }); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
       hidePB(); 
      } 
     }; 
     thread.start(); 
    } 
    void showPB() { 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       // TODO Auto-generated method stub 
       rlPBContainer.setVisibility(View.VISIBLE); 
       edtSearch.setVisibility(View.GONE); 
       btnOK.setVisibility(View.GONE); 
      } 
     }); 
    } 
    void hidePB() { 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       // TODO Auto-generated method stub 
       rlPBContainer.setVisibility(View.GONE); 
       edtSearch.setVisibility(View.VISIBLE); 
       btnOK.setVisibility(View.VISIBLE); 
      } 
     }); 
    } 
} 

AndroidManifest.xml中

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.multiselectlistexample" 
    android:versionCode="1" 
    android:versionName="1.0" > 
    <uses-sdk 
     android:minSdkVersion="8" 
     android:targetSdkVersion="17" /> 
    <uses-permission android:name="android.permission.READ_CONTACTS" /> 

    <application 
     android:allowBackup="true" 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <activity 
      android:name=".MainActivity" 
      android:label="@string/app_name" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 
</manifest>