2012-07-14 167 views
0

我創建了一個ArrayList與定製ArrayAdater。每個ListItem包含CheckBoxTextViewAndroid:按下按鈕後,CheckBox onCheckedChange無法正常工作

TextView包含目錄的名稱,CheckBox指示是否應該掃描該目錄。

我在維護一個ArrayList,它存儲所有檢查目錄的名稱。 在ListView中有一些buttons

最初,當我選中/取消選中應用程序時,ArrayList工作正常,並添加/刪除它中的元素。

但是當我按任何按鈕的ArrayList凍結,不添加/刪除元素。

下面的代碼:(很抱歉的長度)

MainActivity類別:

public class MainActivity extends ListActivity implements OnClickListener { 

    Button done, cancel, selectAll, back; 
    ListView listView; 
    ArrayAdapter<Directory> adapter; 
    List<Directory> list; 
    ArrayList<String> checkedList; 
    private final static String ROOT = "/"; 
    private String currentDir; // Used at the time of back button press 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     try { 
      setContentView(R.layout.main); 
      checkedList = new ArrayList<String>(); 
      done = (Button) findViewById(R.id.bDone); 
      back = (Button) findViewById(R.id.bBack); 
      cancel = (Button) findViewById(R.id.bCancel); 
      selectAll = (Button) findViewById(R.id.bSelAll); 
      done.setOnClickListener(this); 
      back.setOnClickListener(this); 
      cancel.setOnClickListener(this); 

      currentDir = ROOT; 
      new AsyncHandler(this, ROOT).execute(); 
     } catch (Exception e) { 
      Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show(); 
     } 
    } 

    @Override 
    protected void onListItemClick(ListView l, View v, int position, long id) { 
     // super.onListItemClick(l, v, position, id); 
     try { 
      Directory d = list.get(position); 
      File f = d.getFile(); 
      if (f.isDirectory() && f.canRead()) { 
       // Updating View on List TextView item click 
       currentDir = f.getAbsolutePath(); 
       new AsyncHandler(this, f.getAbsolutePath()).execute(); 
      } else { 
       Toast.makeText(this, f.getName() + " NOT READABLE", 
         Toast.LENGTH_SHORT).show(); 
      } 
     } catch (Exception e) { 
      Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show(); 
     } 
    } 

    @Override 
    public void onClick(View view) { 
     switch (view.getId()) { 
     case R.id.bDone: 
      ArrayList<String> localCheckedList = checkedList; 
      checkedList = filterCheckedList(); 
      String allCkecdDirs = ""; 
      for (int i = 0; i < checkedList.size(); i++) { 
       allCkecdDirs = allCkecdDirs + "\n" + checkedList.get(i); 
      } 
      Toast.makeText(this, allCkecdDirs, Toast.LENGTH_LONG).show(); 
      break; 
     case R.id.bBack: 
      if(!currentDir.equals(ROOT)){ 
       /* 
       * here backtracking current directory one step 
       * if current die = /mnt/sdcard/music 
       * so now it will be /mnt/sdcard 
       * this is because if Back button is pressed, 
       * in ElementAdapter while rendering elements 
       * the currentDir will become /mnt/sdcard/music/music 
       */ 
       currentDir = new File(currentDir).getParent(); 
       new AsyncHandler(this, currentDir).execute(); 
      }else{ 
       Toast.makeText(this, "Listing already at Root Folder", Toast.LENGTH_LONG).show(); 
      } 
      break; 
     case R.id.bCancel: 
      this.finish(); 
      break; 
     } 
    } 

    private ArrayList<String> filterCheckedList() { 
     /* 
     * Removing duplicates 
     */ 
     HashSet hs = new HashSet(); 
     hs.addAll(checkedList); 
     checkedList.clear(); 
     checkedList.addAll(hs); 

     /* 
     * Deleting sub-folders if their parent folder has already been added in 
     * the list 
     */ 
     Collections.sort(checkedList); 
     ArrayList<String> filteredList = new ArrayList<String>(); 
     for (int i = 0; i < checkedList.size(); i++) { 
      File current = new File(checkedList.get(i)); 
      File parent = current; 
      while ((parent = parent.getParentFile()) != null) { 
       if (checkedList.contains(parent.getAbsolutePath())) { 
        current = parent; 
       } 
      } 
      if (current != null 
        && !filteredList.contains(current.getAbsolutePath())) { 
       filteredList.add(current.getAbsolutePath()); 
      } 
     } 
     checkedList = filteredList; 
     return checkedList; 
    } 

    public class AsyncHandler extends AsyncTask { 

     Context context; 
     String currentFolder; 
     private List<Directory> prevList; 

     public AsyncHandler(Context c, String currentFolder) { 
      this.context = c; 
      this.currentFolder = currentFolder; 
     } 

     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 
     } 

     @Override 
     protected Object doInBackground(Object... arg0) { 
      getList(); 
      return null; 
     } 

     @Override 
     protected void onPostExecute(Object result) { 
      /* 
      * Checking if list does not contain any directory. If it does not 
      * then the previous view's list is treated as current list and 
      * rendered again. 
      */ 
      if (list.size() == 0) { 
       Toast.makeText(context, "No Sub Directory", Toast.LENGTH_SHORT) 
         .show(); 
       list = prevList; 
      } 
      setListAdapter(new ElementAdapter(context, list, checkedList, currentDir)); 
     } 

     private void getList() { 
      prevList = list; 
      list = new ArrayList<Directory>(); 
      File root = new File(currentFolder); 
      File[] files = root.listFiles(); 
      for (File f : files) { 
       if (f.isDirectory() && !f.isHidden() && f.canRead()) { 
        list.add(new Directory(f, f.getName())); 
       } 
      } 
     } 
    } 
} 

一個ArrayAdapter類:

public class ElementAdapter extends ArrayAdapter { 
    private Context context; 
    private List<Directory> list; 
    ArrayList<String> checkedList; 
    public final String fileName = "AudioSessionFile"; 
    SharedPreferences sharedAudioPrefrences; 
    private static String currentDir; // This will be appended at the time when 
             // chcing if the checkbox is aready 
             // checked or not 

    public ElementAdapter(Context c, List<Directory> list, 
      ArrayList checkedList, String currentDir) { 
     super(c, R.layout.row, list); 
     this.context = c; 
     sharedAudioPrefrences = c.getSharedPreferences(fileName, 
       Context.MODE_PRIVATE); 
     this.list = list; 
     this.checkedList = checkedList; 
     this.currentDir = currentDir; 
    } 

    static class ViewHolder { 
     protected TextView textView; 
     protected CheckBox checkBox; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     ViewHolder viewHolder = null; 
     View view = convertView; 
     if (view == null) { 
      LayoutInflater inflator = (LayoutInflater) context 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      view = inflator.inflate(R.layout.row, null); 
      viewHolder = new ViewHolder(); 
      viewHolder.textView = (TextView) view.findViewById(R.id.tvElement); 
      viewHolder.checkBox = (CheckBox) view.findViewById(R.id.checkBox1); 
      viewHolder.checkBox 
        .setOnCheckedChangeListener(new OnCheckedChangeListener() { 

         @Override 
         public void onCheckedChanged(CompoundButton buttonView, 
           boolean isChecked) { 
          int getPosition = (Integer) buttonView.getTag(); 
          list.get(getPosition).setSelected(
            buttonView.isChecked()); 

          /* 
          * Code to check if checkbox is checked on 
          * unchecked. If checked then, the corresponding 
          * entry is made in the HashMap (which contains the 
          * state of directories to be scanned) 
          */ 
          if (isChecked 
            && !checkedList.contains(list 
              .get(getPosition).getFile() 
              .getAbsolutePath())) { 
           /* 
           * Here we can also put condition && 
           * !checkedList 
           * .contains(list.get(getPosition).getFile 
           *().getParent()) to avoid creating unnecessary 
           * entries 
           */ 
           checkedList.add(list.get(getPosition).getFile() 
             .getAbsolutePath()); 
          } else if (!isChecked 
            && checkedList.contains(list 
              .get(getPosition).getFile() 
              .getAbsolutePath())) { 
           checkedList.remove(list.get(getPosition) 
             .getFile().getAbsolutePath()); 
          } 
         } 
        }); 
      view.setTag(viewHolder); 
      view.setTag(R.id.tvElement, viewHolder.textView); 
      view.setTag(R.id.checkBox1, viewHolder.checkBox); 
     } else { 
      viewHolder = (ViewHolder) view.getTag(); 
     } 
     viewHolder.checkBox.setTag(position); 
     viewHolder.textView.setText(list.get(position).getName()); 
     viewHolder.checkBox.setChecked(list.get(position).isSelected()); 

     /* 
     * checking if the directory is already selected earlier by the user 
     */ 
     String absPath = currentDir + "/" + viewHolder.textView.getText(); 
     if (checkedList != null 
       && checkedList.contains(absPath)) { 
      viewHolder.checkBox.setChecked(true); 
     } 

     return view; 
    } 
} 

雖然代碼沒有進入onCheckedChangeListener在ElementAdapter中,但是當流i s返回到Activity類,該列表保持原樣。

回答

0

嘗試添加notifyDataSetChanged()setListAdapter(new ElementAdapter(context, list, checkedList, currentDir))聲明。

如:

ElementAdapter myAdpt = new ElementAdapter(context, list, checkedList, currentDir) 
    setListAdapter(myAdpt); 
    myAdpt.notifyDataSetChanged(); 
+0

感謝快速回復,但沒有工作...任何其他建議 – reiley 2012-07-14 18:42:06