2012-01-12 89 views
18

我試圖重新創建Google在Gmail應用中使用ListView所做的事情。特別是,我希望每個列表項都包含一個CheckBox和兩個TextView(一個在另一個之上)。我需要監聽器來檢查複選框(或單擊)和何時單擊列表項上的其他位置。最後,我希望ActionBar能夠反映選擇的項目並提供諸如全選,無選擇等選項(請參閱this screenshot)。帶有複選框的Gmail類ListView(並使用ActionBar)

enter image description here

到目前爲止,這是我想出了佈局。

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="horizontal" > 

    <CheckBox android:id="@+id/checkBox" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center_vertical|center_horizontal" /> 

    <LinearLayout android:id="@+id/linearLayout1" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="vertical" 
     android:padding="6dp" 
     android:focusable="true" 
     android:clickable="true" > 

     <TextView android:id="@+id/titleTextView" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:textSize="16sp" /> 

     <TextView android:id="@+id/dateTextView" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:textSize="12sp" /> 

    </LinearLayout> 

</LinearLayout> 

這可以正確地顯示一切,但我需要如何設置偵聽器的兩個視圖(@ + ID /複選框@ + ID/linearLayout1)指針。我看了一下List16 API demo,但他們使用的是simple_list_item_activated_1佈局,我不確定它的XML是什麼樣的。正如他們的代碼所暗示的,我創建了一個ModeCallback類,該類實現了ListView.MultiChoiceModeListener並且我將ListView的選擇模式設置爲CHOICE_MODE_MULTIPLE_MODAL,但我不知道如何讓我的佈局中的CheckBox使用它。

是否有人成功複製了Gmail應用程序的ListView行爲?我已經搜索了很多東西,不能提出任何東西(儘管其他幾個人也提出了類似的問題,like this one - 大多數答案只是指向這個相同的API演示)。

另外,對於上下文,我從SQLite數據庫加載數據到列表中,並且我創建了自己的Cursor適配器(工作正常)。我有一種感覺,我需要在newView()和bindView()方法的這個類中設置監聽器,但是我嘗試過的所有內容都無法工作。

任何想法?

+0

我需要更好地解釋我的問題,還是我只是要求太多? :/ – mturco 2012-01-14 22:41:26

回答

7

圖中的模式稱爲動作模式。如果您正在使用自定義行視圖和自定義適配器,則不必使用CHOICE_MODE_MULTIPLE_MODAL啓動操作模式。我嘗試過一次並失敗,我懷疑它用於內置適配器。

爲了在代碼中自己調用動作模式,請在任何視圖的任何偵聽器方法中調用startActionMode方法,讓它成爲複選框,textview或類似的東西。然後您將ModeCallback作爲參數傳遞給它,並在ModeCallback類中執行您想要執行的任何操作。

我不認爲這個可以在3.0以前的Android上工作。

這裏是一個簡單的例子。我有一個擴展列表活動,想調出動作模式菜單當用戶選中/取消選中該複選框,並在這裏是我的getChildView方法在我的自定義適配器類:

public View getChildView(int groupPosition, int childPosition, 
      boolean isLastChild, View convertView, ViewGroup parent) { 

     if (convertView == null) { 
      LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      convertView = inflater.inflate(R.layout.childrow, null); 
     } 
     CheckBox cb = (CheckBox)convertView.findViewById(R.id.row_check); 
     cb.setChecked(false); // Initialize 
     cb.setTag(groupPosition + "," + childPosition); 
     cb.setFocusable(false); // To make the whole row selectable 
     cb.setOnCheckedChangeListener(new OnCheckedChangeListener() { 
      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
       String tag = (String)buttonView.getTag(); 
       String[] pos = tag.split(","); 
       if (isChecked) { 
        if (mActionMode == null) mActionMode = startActionMode(mMultipleCallback);      
       } 
       else { 
        if (mActionMode != null) { // Only operate when mActionMode is available 

         mActionMode.finish(); 
         mActionMode = null; 
        } 
       } 
      } 
     }); 

     TextView tvTop = (TextView)convertView.findViewById(R.id.row_text_top); 
     TextView tvBottom = (TextView)convertView.findViewById(R.id.row_text_bottom); 
     tvTop.setText(mChildren.get(groupPosition).get(childPosition)); 
     tvBottom.setText(mChildrenSize.get(groupPosition).get(childPosition)); 
     return convertView; 
    } 
+0

謝謝!我今晚會嘗試這個,看看我能否得到它的工作。標記爲此之前的答案。 – mturco 2012-02-06 23:19:42

2

此外tocnbuff410的答案使用下面的代碼更新檢查的項目數

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
if (isChecked) { 
    ++checkBoxCount; 
} else { 
    --checkBoxCount; 
} 
... 

if (mActionMode != null) { 
    mActionMode.setSubtitle(checkBoxCount + " item(s) selected."); 
} 

我可以確認下面的代碼不會在自定義列表視圖的複選框上工作。然而,長按仍然會工作:

listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); 
listView.setMultiChoiceModeListener(new ModeCallback()); 

選擇自定義ListView上的複選框將不會觸發actionmode。只有內置的ListViews,例如擴展ListActivity會自動做到這一點。

+0

也非常有幫助。謝謝! – mturco 2012-02-09 05:29:27

11

這將在SDK 7(android 2.1)及更高版本中工作。 (與SherlockActionBar一起)

Totaly模仿gmail列表框體驗。

我重寫onTouchEvent,所以按下左側角將激活選擇模式; mutch更好,然後嘗試點擊微小的cheackbox。

我重寫了performItemClick,所以按不在左邊將作爲一個常規的按下操作。

我重寫setItemChecked,以便根據需要更新mActionMode。

public class SelectListView extends ListView { 

    private SherlockFragmentActivity mActivity; 
    ActionMode mActionMode; 

     public SelectListView(Context context) { 
    this(context, null, 0); 
} 

public SelectListView(Context context, AttributeSet attrs) { 
    this(context, attrs, 0); 
} 


public SelectListView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 
    mActivity = (SherlockFragmentActivity) context; 
} 

    @Override 
    public boolean performItemClick(View view, int position, long id) { 
     OnItemClickListener mOnItemClickListener = getOnItemClickListener(); 
     if (mOnItemClickListener != null) { 
      playSoundEffect(SoundEffectConstants.CLICK); 
      if (view != null) 
       view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); 
      mOnItemClickListener.onItemClick(this, view, position, id); 
      return true; 
     } 
     return false; 
    } 

    boolean mSelectionMode = false; 
    int mStartPosition; 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 

     final int action = ev.getAction(); 
     final int x = (int) ev.getX(); 
     final int y = (int) ev.getY(); 

     if (action == MotionEvent.ACTION_DOWN && x < getWidth()/7) { 
      mSelectionMode = true; 
      mStartPosition = pointToPosition(x, y); 
     } 
     if (!mSelectionMode) 
      return super.onTouchEvent(ev); 
     switch (action) { 
     case MotionEvent.ACTION_DOWN: 
      break; 
     case MotionEvent.ACTION_MOVE: 
      if (pointToPosition(x, y) != mStartPosition) 
       mSelectionMode = false; 
      break; 
     case MotionEvent.ACTION_CANCEL: 
     case MotionEvent.ACTION_UP: 
     default: 
      mSelectionMode = false; 
      int mItemPosition = pointToPosition(x, y); 
      if (mStartPosition != ListView.INVALID_POSITION) 
       setItemChecked(mItemPosition, !isItemChecked(mItemPosition)); 
     } 

     return true; 
    } 

    @Override 
    public void setItemChecked(int position, boolean value) { 
     super.setItemChecked(position, value); 
     // boolean r = getAdapter().hasStableIds(); 
     int checkedCount = getCheckItemIds().length; 

     if (checkedCount == 0) { 
      if (mActionMode != null) 
       mActionMode.finish(); 
      return; 
     } 
     if (mActionMode == null) 
      mActionMode = mActivity.startActionMode(new ModeCallback()); 

     mActionMode.setTitle(checkedCount + " selected"); 

    } 

    class ModeCallback implements ActionMode.Callback { 

     @Override 
     public boolean onCreateActionMode(ActionMode mode, Menu menu) { 

      menu.add(getResources().getString(R.string.aBar_remove)).setIcon(R.drawable.ic_action_trash) 
        .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); 

      return true; 
     } 

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

     @Override 
     public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 
      Toast.makeText(mActivity, "Delted items", Toast.LENGTH_SHORT).show(); 
      mode.finish(); 
      return true; 
     } 

     @Override 
     public void onDestroyActionMode(ActionMode mode) { 
      mActionMode = null; 
      clearChecked(); 
     } 

    } 

    public void clearChecked() { 
     SparseBooleanArray CItem = getCheckedItemPositions(); 
     for (int i = 0; i < CItem.size(); i++) 
      if (CItem.valueAt(i)) 
       super.setItemChecked(CItem.keyAt(i), false); 
    } 

} 

您可以使用任何您需要的列表框適配器。

,如果你對你的list_item_layout土特產品需要程度適配器這樣一個複選框:

ArrayAdapter<String> mAdapter = new ArrayAdapter<String>(this, R.layout.simple_list_item_multiple_choice, 
      R.id.text1, Cheeses.sCheeseStrings) { 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
      View v = super.getView(position, convertView, parent); 
      CheckBox checkBox = (CheckBox) v.findViewById(R.id.CheckBox); 
      checkBox.setChecked(((ListView)parent).isItemChecked(position)); 
      return v; 
     } 

    }; 

不要忘了使用Android:您list_item_layout.xml

背景=「ATTR/activatedBackgroundIndicator?」
+0

我實現上下文行動欄與複選框時,我滾動列表視圖,然後不維護操作欄上設置的複選框計數。任何幫助? – 2014-05-28 12:18:09

+0

就像一個魅力。 :d – Uzair 2016-07-01 04:15:20