回答

41

所以這就是我所做的。

編輯: 超過一年,因爲我發現了以前的答案了無用的代碼(woops)和CAB東西可以用少得多的努力和更乾淨的代碼實現了很多,所以我花了一些時間過去了,更新它

的LibraryFragment的ListView應該選擇模式「無」

<ListView 
    android:id="@android:id/list" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:choiceMode="none"/> 

列表項應該有一個?ATTR/activatedBackgroundIndicator前景,以自動吸取list.setItemChecked高亮半透明疊加來定義(POS ,真)

list_item_library.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:foreground="?attr/activatedBackgroundIndicator" 
    android:paddingBottom="5dp" 
    android:paddingTop="5dp" > 

.... 

的ListFragment

import android.support.v4.app.DialogFragment; 
import com.actionbarsherlock.app.SherlockListFragment; 
import com.actionbarsherlock.view.ActionMode; 
import com.actionbarsherlock.view.Menu; 

public final class LibraryFragment 
     extends SherlockListFragment 
{ 

    private MyListAdapter adapter; 
    private ListView list; 

    // if ActoinMode is null - assume we are in normal mode 
    private ActionMode actionMode; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) 
    { 
     View v = inflater.inflate(R.layout.fragment_library, null); 
     this.list = (ListView) v.findViewById(android.R.id.list); 
     this.initListView(); 
     return v; 
    } 

    @Override 
    public void onPause() 
    { 
     super.onPause(); 
     if (this.actionMode != null) { 
      this.actionMode.finish(); 
     } 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     updateData(); 
    } 

    // update ListView 
    protected void updateData() 
    { 
     if (adapter == null) { 
      return; 
     } 
     adapter.clear(); 
     // my kinda stuff :) 
     File[] items = scan(); 
     if (items != null) { 
      adapter.updateData(items); 
      if (actionMode != null) { 
       actionMode.invalidate(); 
      } 
     } 
     // if empty - finish action mode. 
     if (actionMode != null && (files == null || files.length == 0)) { 
      actionMode.finish(); 
     } 
    } 

    private void initListView() 
    { 
     this.adapter = new MyAdapter(getActivity()); 
     this.list.setAdapter(adapter); 
     this.list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() 
     { 

      @Override 
      public boolean onItemLongClick(AdapterView<?> arg0, 
        View arg1, int arg2, long arg3) 
      { 
       if (actionMode != null) { 
        // if already in action mode - do nothing 
        return false; 
       } 
       // set checked selected item and enter multi selection mode 
       list.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); 
       list.setItemChecked(arg2, true); 

       getSherlockActivity().startActionMode(
         new ActionModeCallback()); 
       return true; 
      } 
     }); 
     this.list.setOnItemClickListener(new AdapterView.OnItemClickListener() 
     { 
      @Override 
      public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, 
        long arg3) 
      { 
       if (actionMode != null) { 
        // the items are auomatically "checked" becaise we've set AbsListView.CHOICE_MODE_MULTIPLE before 
        // starting action mode, so the only thing we have to care about is invalidating the actionmode 
        actionMode.invalidate(); //invalidate title and menus. 
       } else { 
        // do whatever you should on item click 
       } 
      } 
     }); 
    } 


    // all our ActionMode stuff here :) 
    private final class ActionModeCallback 
      implements ActionMode.Callback 
    { 

     // " selected" string resource to update ActionBar text 
     private String selected = getActivity().getString(
       R.string.library_selected); 

     @Override 
     public boolean onCreateActionMode(ActionMode mode, Menu menu) 
     { 
      actionMode = mode; 
      return true; 
     } 

     @Override 
     public boolean onPrepareActionMode(ActionMode mode, Menu menu) 
     { 
      // remove previous items 
      menu.clear(); 
      final int checked = list.getCheckedItemCount(); 
      // update title with number of checked items 
      mode.setTitle(checked + this.selected); 
      switch (checked) { 
      case 0: 
       // if nothing checked - exit action mode 
       mode.finish(); 
       return true; 
      case 1: 
       // all items - rename + delete 
       getSherlockActivity().getSupportMenuInflater().inflate(
         R.menu.library_context, menu); 
       return true; 
      default: 
       getSherlockActivity().getSupportMenuInflater().inflate(
         R.menu.library_context, menu); 
       // remove rename option - because we have more than one selected 
       menu.removeItem(R.id.library_context_rename); 
       return true; 
      } 
     } 

     @Override 
     public boolean onActionItemClicked(ActionMode mode, 
       com.actionbarsherlock.view.MenuItem item) 
     { 
      SparseBooleanArray checked; 
      switch (item.getItemId()) { 
      case R.id.library_context_rename: 
       // the rename action is present only when only one item is selected. 
       // so when the first checked item found, show the dialog and break 
       checked = list.getCheckedItemPositions(); 
       for (int i = 0; i < checked.size(); i++) { 
        final int index = checked.keyAt(i); 
        if (checked.get(index)) { 
         final DialogFragment d = RenameDialog.instantiate(adapter.getItem(index).getFile(), LibraryFragment.this); 
         d.show(getActivity().getSupportFragmentManager(), "dialog"); 
         break; 
        } 
       } 
       return true; 

      case R.id.library_context_delete: 
       // delete every checked item 
       checked = list.getCheckedItemPositions(); 
       for (int i = 0; i < checked.size(); i++) { 
        final int index = checked.keyAt(i); 
        if (checked.get(index)) { 
         adapter.getItem(index).getFile().delete(); 
        } 
       } 
       updateData(); 
       return true; 
      default: 
       return false; 
      } 
     } 

     @Override 
     public void onDestroyActionMode(ActionMode mode) 
     { 
      list.clearChoices(); 

      //workaround for some items not being unchecked. 
      //see http://stackoverflow.com/a/10542628/1366471 
      for (int i = 0; i < list.getChildCount(); i++) { 
       (list.getChildAt(i).getBackground()).setState(new int[] { 0 }); 
      } 

      list.setChoiceMode(AbsListView.CHOICE_MODE_NONE); 
      actionMode = null; 
     } 

    } 
+0

感謝分享。我正在尋找這個! – h4ck3d

+0

感謝這個偉大的職位,但我有一個方向變化的問題。 比方說,我選擇了動作模式上的幾個項目,然後旋轉設備,我可以恢復操作欄並設置選定的項目。但突出顯示,直到我從屏幕上滾動列表,然後回來,突出顯示。 有什麼想法? – triston

+0

@triston你如何恢復狀態?確保你在Adapter上調用setChecked()。在這種情況下,它應該工作。但是,如果這就是你所做的,並且它不工作,恐怕我無法幫助你,因爲我沒有足夠的空閒時間來測試這些東西。 –

0

您的解決方案是該線程的最佳和最簡單的解決方案。但是getView()中存在一個小問題 - 請參考上面的註釋。

int version = android.os.Build.VERSION.SDK_INT;  
if(version < 11){ 
    if (checkedItems.contains(Integer.valueOf(position))) { 
     convertView.getBackground().setState(
       new int[] { android.R.attr.state_checked }); 
    } else { 
     convertView.getBackground().setState(
       new int[] { -android.R.attr.state_checked }); 
    } 
}else{ 

    if (checkedItems.contains(Integer.valueOf(position))) { 
     convertView.setActivated(true); 
    } else { 
     convertView.setActivated(false);   
    } 
} 

這會給你從API8全力支持API18

+0

setActivated僅從API級別11開始纔可用。如果您使用API​​ 11,則不需要ActionBarSherlock,而且我的解決方案很糟糕,因爲有更簡單的方法來執行此開始API 11. http://developer.android.com/ guide/topics/ui/menus.html#CAB –

+0

我的項目設置了最低的API8,所以我必須同時使用這兩個。我也會修改我的建議。謝謝。 – triston

相關問題