2010-02-28 24 views
47

Mở rộngListView có phương thức setOnChildClickListener nhưng thiếu phương thức setOnChild Dài ClickListener.Android: dài nhấp vào các chế độ xem con của ExpandableListView?

Khi tôi thêm setOnLongClickListener() vào chế độ xem con trong getChildView(), toàn bộ danh sách phụ trở nên hoàn toàn không thể nhấp (mặc dù parentView.setOnChildClickListener() hiện tại và hoạt động trước đó).

Làm cách nào để bật các nhấp chuột dài trên chế độ xem con?

+0

Xem câu trả lời chi tiết ở đây ... http://stackoverflow.com/question/23646098/android-can-i-use-setonlongclicklistener-and-setonclicklistener-cho-same-butto/23646241 # 23646241 – Nepster

Trả lời

40

Tôi tìm thấy một câu trả lời về Steve Oliver blog ở đây: http://steveoliverc.wordpress.com/2009/10/16/context-menus-for-expandable-lists/

Bạn nên sử dụng onCreateContextMenu() thay vì tìm kiếm setOnChildLongClickListener(). Đây là thông tin của Steve:

Danh sách có thể mở rộng hỗ trợ menu ngữ cảnh theo cách tương tự như danh sách chuẩn: thêm người nghe cho menu ngữ cảnh (khi người dùng nhấn lâu vào mục danh sách). Tuy nhiên, không giống như chế độ xem danh sách chuẩn, bạn có thể muốn biết liệu người dùng đã chọn một nhóm (mục có thể mở rộng) hay một mục danh sách con (mục phụ).

Ngoài ra, bạn có thể không muốn làm bất cứ điều gì nếu người dùng cố gắng hiển thị menu ngữ cảnh trên một mục nhóm. Có thể có trường hợp bạn muốn làm điều gì đó cho tất cả trẻ em dưới một nhóm, nhưng trong ứng dụng Librarium của tôi, tôi muốn bỏ qua các mục nhóm và trình bày menu ngữ cảnh chỉ dành cho trẻ em.

Trước tiên, bạn cần phải biết khi nào trình đơn ngữ cảnh sẽ được tạo để bạn có thể xác định liệu người dùng đã nhấn vào một nhóm hay một đứa trẻ. Nếu họ nhấn vào một nhóm, sau đó hủy menu ngữ cảnh. Điều này cũng cho chúng ta cơ hội nhận được văn bản của mục con, để chúng ta có thể đặt nó vào phần đầu của menu ngữ cảnh.

public void onCreateContextMenu(ContextMenu menu, View v, 
           ContextMenuInfo menuInfo)    
{ 
    super.onCreateContextMenu(menu, v, menuInfo); 

    ExpandableListView.ExpandableListContextMenuInfo info = 
    (ExpandableListView.ExpandableListContextMenuInfo) menuInfo; 

    int type = 
    ExpandableListView.getPackedPositionType(info.packedPosition); 

    int group = 
    ExpandableListView.getPackedPositionGroup(info.packedPosition); 

    int child = 
    ExpandableListView.getPackedPositionChild(info.packedPosition); 

    // Only create a context menu for child items 
    if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) 
    { 
    // Array created earlier when we built the expandable list 
    String page =mListStringArray[group][child]; 

    menu.setHeaderTitle(page); 
    menu.add(0, MENU_READ, 0, “Read page”); 
    menu.add(0, MENU_EDIT, 0, “Edit page”); 
    menu.add(0, MENU_FAVORITE, 0, “Add page to favorites”); 
    menu.add(0, MENU_EXPORT, 0, “Export page to file”); 
    menu.add(0, MENU_DELETE, 1, “Delete page”); 
    } 
} 

Thứ hai, tạo ra các menu ngữ cảnh:

public boolean onContextItemSelected(MenuItem menuItem) 
{ 
    ExpandableListContextMenuInfo info = 
    (ExpandableListContextMenuInfo) menuItem.getMenuInfo(); 

    int groupPos = 0, childPos = 0; 

    int type = ExpandableListView.getPackedPositionType(info.packedPosition); 
    if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) 
    { 
    groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition); 
    childPos = ExpandableListView.getPackedPositionChild(info.packedPosition); 
    } 

    // Pull values from the array we built when we created the list 
    String author = mListStringArray[groupPos][0]; 
    String page = mListStringArray[groupPos][childPos * 3 + 1]; 
    rowId = Integer.parseInt(mListStringArray[groupPos][childPos * 3 + 3]); 

    switch (menuItem.getItemId()) 
    { 
    case MENU_READ: 
     readNote(rowId); 
     return true; 

    case MENU_EDIT: 
     editNote(rowId); 
     return true; 

    // etc.. 

    default: 
     return super.onContextItemSelected(menuItem); 
    } 
} 

Vậy là xong. Giờ đây, người dùng có thể nhấn và giữ một mục trong danh sách có thể mở rộng và nhận menu ngữ cảnh nếu đó là mục con.

+12

Như một lưu ý phụ, đừng quên cuộc gọi registerForContextMenu trong phương thức onCreate. Nếu bạn (như tôi) quên điều đó, thế thì chẳng cái gì có hiệu quả cả. –

+0

Đồng thời, đừng quên ghi đè isChildSelectable để trả về true trong việc triển khai BaseExpandableListAdapter của bạn. Nếu không có điều này, chế độ xem trẻ em sẽ không phản hồi lại các nhấp chuột dài. –

83

tôi quản lý để có được nhấp chuột dài làm việc trên một mục con ExpandableListView, sử dụng như sau:

getExpandableListView().setOnItemLongClickListener(new OnItemLongClickListener() { 
    @Override 
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { 
     if (ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_CHILD) { 
      int groupPosition = ExpandableListView.getPackedPositionGroup(id); 
      int childPosition = ExpandableListView.getPackedPositionChild(id); 

      // You now have everything that you would as if this was an OnChildClickListener() 
      // Add your logic here. 

      // Return true as we are handling the event. 
      return true; 
     } 

     return false; 
    } 
}); 

Phải mất rất lâu để tìm ra rằng đối số id trong onItemLongClick là packedPosition đối số bắt buộc bởi getPackedPosition * phương pháp , chắc chắn không rõ ràng từ tài liệu.

Lưu ý: Đối với giải pháp này để làm việc bạn cần phải ghi đè các phương pháp getGroupIdgetChildId() trong adapter của bạn

@Override 
    public long getGroupId(int groupPosition) { 
     return groupPosition; 
    } 

    @Override 
    public long getChildId(int groupPosition, int childPosition) { 
     return childPosition; 
    } 
+3

Một giải pháp làm việc thanh lịch. Không xung đột với OnChildClickListener. – kaay

+3

Tôi đã làm theo giải pháp này và tìm thấy vấn đề. Nó ném outOfIndexException khi tôi cố gắng lấy đối tượng từ nguồn dữ liệu của bộ điều hợp danh sách với 'childPosition' và' groupPosition'. Tôi tìm thấy câu trả lời khác tại đây: http://stackoverflow.com/questions/5806100/identifying-the-group-that-has-been-clicked-in-an-expandablelistview giải thích tại sao tôi không thể sử dụng id cho điều này tình hình. Cuối cùng, tôi đã giải quyết được vấn đề của tôi với câu trả lời (bạn có thể tìm thấy trong câu trả lời của tôi ở dưới/trên). – toantran

+0

Điều này không hiệu quả đối với tôi, ChildPosition luôn là 0, vì vậy tôi đã sử dụng câu trả lời của autobot_101. – Brandon

1

tôi xử lý vấn đề ur.chỉ cần đặt mục thẻ ur và sử dụng nó, như sau:

adapter = new ExpandableListAdapter() { 


     private String[] groups = { "Biceps", "Deltoids", "Hamstrings", "Lower Back","Quadriceps","Triceps","Wrist" }; 
     private String[][] children = { 
       { "Konsantra Dumbell curl", "Hammer curl", "Barbell Biceps Curl", "Prone Curl" }, 
       { "Arnold Press", "Lateral Raise", "Dumbell Upright row", "Bar Military Press" }, 
       { "Dead Lift", "Hack Squat","Zercher Squat","Seated Leg Flexion" }, 
       { "Back Raise", "Superman" }, 
       { "Back Squat", "Bulgarian Split Squat","Dumbell Lunge" }, 
       { "Bench Dip", "French Press","Triceps Extension" }, 
       { "Dumbell Wrist Curl "," Reverse Writst Curl"} 
     }; 
     public void unregisterDataSetObserver(DataSetObserver observer) { 
      // TODO Auto-generated method stub 

     } 

     public void registerDataSetObserver(DataSetObserver observer) { 
      // TODO Auto-generated method stub 

     } 

     public void onGroupExpanded(int groupPosition) { 
      // TODO Auto-generated method stub 

     } 

     public void onGroupCollapsed(int groupPosition) { 
      // TODO Auto-generated method stub 

     } 

     public boolean isEmpty() { 
      // TODO Auto-generated method stub 
      return false; 
     } 

     public boolean isChildSelectable(int groupPosition, int childPosition) { 
      // TODO Auto-generated method stub 
      return true; 
     } 

     public boolean hasStableIds() { 
      // TODO Auto-generated method stub 
      return true; 
     } 

     public View getGroupView(int groupPosition, boolean isExpanded, 
       View convertView, ViewGroup parent) { 
      TextView textView = getGenericView(); 
       textView.setText(getGroup(groupPosition).toString()); 
       textView.setTag((Object)getGroup(groupPosition).toString()+"G"); 
       return textView; 
     } 

     public long getGroupId(int groupPosition) { 
      // TODO Auto-generated method stub 
      return groupPosition; 
     } 

     public int getGroupCount() { 
      // TODO Auto-generated method stub 
      return groups.length; 
     } 

     public Object getGroup(int groupPosition) { 
      // TODO Auto-generated method stub 
      return groups[groupPosition]; 
     } 

     public long getCombinedGroupId(long groupId) { 
      // TODO Auto-generated method stub 
      return 0; 
     } 

     public long getCombinedChildId(long groupId, long childId) { 
      // TODO Auto-generated method stub 
      return 0; 
     } 

     public int getChildrenCount(int groupPosition) { 
      // TODO Auto-generated method stub 
      return children[groupPosition].length; 
     } 

     public View getChildView(int groupPosition, int childPosition, 
       boolean isLastChild, View convertView, ViewGroup parent) { 
      TextView textView = getGenericView(); 
       textView.setText(getChild(groupPosition, childPosition).toString()); 
       textView.setTag((Object)getChild(groupPosition, childPosition).toString()+"C"); 
       return textView; 
     } 

     public long getChildId(int groupPosition, int childPosition) { 
      // TODO Auto-generated method stub 
      return childPosition; 
     } 

     public Object getChild(int groupPosition, int childPosition) { 
      // TODO Auto-generated method stub 
      return children[groupPosition][childPosition]; 
     } 

     public boolean areAllItemsEnabled() { 
      // TODO Auto-generated method stub 
      return false; 
     } 

     public TextView getGenericView() { 
      // Layout parameters for the ExpandableListView 
      AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
        ViewGroup.LayoutParams.FILL_PARENT, 64); 

      TextView textView = new TextView(expandXml.this); 
      textView.setLayoutParams(lp); 
      // Center the text vertically 
      textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); 
      // Set the text starting position 
      textView.setPadding(36, 0, 0, 0); 

      return textView; 
     } 

    }; 

Và sau đó setOnItemLongClickListener cho danh sách mở rộng.

listView.setOnItemLongClickListener(new OnItemLongClickListener() { 

     public boolean onItemLongClick(AdapterView<?> arg0, View arg1, 
       int arg2, long arg3) { 
      // TODO Auto-generated method stub 
      String s=null; 

       int childPosition =ExpandableListView.getPackedPositionChild(arg3); 
       if(arg1.getTag()!=null){ 
       Object o= arg1.getTag(); 

       s = o.toString(); 
       } 
       Toast.makeText(expandXml.this ,s , Toast.LENGTH_SHORT).show(); 

      return false; 
     } 
    }); 

Đây rồi.

+0

Nó hoạt động. và tiết kiệm thời gian của tôi. – riseres

30

Tôi biết câu trả lời này có thể không cần thiết, nhưng tôi có tình huống tương tự và không có câu trả lời nào giải quyết được vấn đề của tôi. Vì vậy, tôi đăng bài của tôi trong trường hợp ai đó có thể cần nó. Mong mọi người đừng bận tâm.

@Override 
       public boolean onItemLongClick(AdapterView<?> parent, View childView, int flatPos, long id) { 
        if (ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_CHILD) { 
          final ExpandableListAdapter adapter = ((ExpandableListView) parent).getExpandableListAdapter(); 
          long packedPos = ((ExpandableListView) parent).getExpandableListPosition(flatPos); 
          int groupPosition = ExpandableListView.getPackedPositionGroup(packedPos); 
          int childPosition = ExpandableListView.getPackedPositionChild(packedPos); 

         // do whatever you want with groupPos and childPos here - I used these to get my object from list adapter. 
        return false; 
       } 

Sửa Giải pháp này cho listview đã lâu lắm rồi. Tôi khuyên bạn nên chuyển sang RecyclerView ngay bây giờ.

+2

+1. Đây là giải pháp __ đúng. Bạn cần vị trí phẳng (thô) đầu tiên, không chỉ là id của đối tượng ở vị trí đó. –

+2

wow !!!! Đồng ý! Không thể lấy te childPosition từ các ví dụ trước đó. Nó luôn giống với ZERO - nhưng bây giờ, khi tôi triển khai mã này, nó dường như hoạt động hoàn hảo !. Tôi sẽ bỏ phiếu. –

+2

autobot_101: Phiếu bầu của tôi được chuyển đến câu trả lời của bạn. Câu trả lời này sẽ nhận được số phiếu tối đa. – MobiDev

12

Tôi đã tìm kiếm câu trả lời này, nhưng ở đây không có kết quả chính xác.

Câu trả lời được đánh dấu từ tomash đề xuất cách hoàn toàn khác. Câu trả lời từ Nicholas là một phần chính xác, nhưng việc sử dụng 'id' không chính xác.

Đúng, làm việc, trả lời là: chuyển đổi thông số position thành packedPosition và THEN! sử dụng giá trị packedPosition mới này để nhận ID nhóm và ID con. Kiểm tra mã dưới đây

getExpandableListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 

     @Override 
     public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { 
      long packedPosition = getExpandableListView().getExpandableListPosition(position); 
      if (ExpandableListView.getPackedPositionType(packedPosition) == 
        ExpandableListView.PACKED_POSITION_TYPE_CHILD) { 
       // get item ID's 
       int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition); 
       int childPosition = ExpandableListView.getPackedPositionChild(packedPosition); 

       // handle data 
       ... 

       // return true as we are handling the event. 
       return true; 
      } 
      return false; 
     } 
    }); 

EDIT: bây giờ tôi thấy rằng autobot có giải pháp gần đúng, trừ thử nghiệm getPackedPositionType trên id và không phải trên packetPosition

+0

exListView là gì trong câu trả lời của bạn? –

+0

xin lỗi, tôi đã cải thiện mã ở trên. 'exListView' là đối tượng' ExpandableListView'. Tương tự như cái mà bạn đặt người nghe này là –

+0

Thumbs up cho cái này. Sử dụng vị trí tốt hơn sử dụng id để có được đóng góiPosition. –

Các vấn đề liên quan