28

एक्शनबैरशेल पर एडाप्टर व्यू पर बहु ​​चयन को कैसे कार्यान्वित किया जाना चाहिए, क्योंकि यह मल्टीचॉइसमोड लिस्टनर प्रदान नहीं करता है?आप ActionBarSherlock में बहु-चयन और प्रासंगिक क्रिया मोड को कैसे कार्यान्वित कर सकते हैं?

यह वही है

Contextual Action Mode

तरह लग रहा है आप यह कैसे कर सकते है?

+0

रहा हूँ यह recyclerview के लिए कृपया मुझे मदद करने के लिए – Harsha

उत्तर

41

तो यहां मैंने जो किया है।

संपादित करें: एक वर्ष के बाद से मुझे पता चला पिछले जवाब बेकार कोड (ओह) और सीएबी बात बहुत कम प्रयास और एक क्लीनर कोड के साथ प्राप्त किया जा सकता है की बहुत कुछ था, इसलिए मैं कुछ समय ले लिया गया और अद्यतन से अधिक यह

LibraryFragment ListView विकल्प मोड "कोई नहीं"

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

सूची आइटम आदेश स्वचालित रूप से list.setItemChecked पर प्रकाश डाला अर्द्धपारदर्शी ओवरले आकर्षित करने के लिए में एक? attr/activatedBackgroundIndicator अग्रभूमि होना चाहिए के साथ परिभाषित किया जाना चाहिए (स्थिति , सच)

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 आप राज्य को कैसे पुनर्स्थापित करते हैं? सुनिश्चित करें कि आप एडाप्टर पर 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 केवल एपीआई स्तर 11 से शुरू होता है। यदि आप एपीआई 11 का उपयोग करते हैं तो एक्शनबैरशेलॉक की कोई आवश्यकता नहीं है और मेरा समाधान खराब है क्योंकि इस शुरुआती एपीआई 11 को करने का बहुत आसान तरीका है। Http://developer.android.com/ गाइड/विषय/ui/menus.html # सीएबी –

+0

मेरी परियोजना एक न्यूनतम API8 सेट है, इसलिए मुझे दोनों का उपयोग करना होगा। मैं ऊपर भी अपने सुझाव को संशोधित करूंगा। धन्यवाद। – triston

संबंधित मुद्दे

 संबंधित मुद्दे