2013-06-30 39 views
14

loại của Menu

Hãy để tôi bắt đầu bằng việc phác thảo sự phân biệt giữa Contextual Menus và Popup Menus (lấy từ here):Triggering một PopupMenu với các nút bên trong một mục ListView

  • Một PopupMenu là một phương thức menu được neo vào Chế độ xem

  • Trình đơn ngữ cảnh [Tôi đang nói cụ thể về menu ngữ cảnh nổi] cung cấp các tác vụ ảnh hưởng đến một mục cụ thể hoặc khung xt trong giao diện người dùng. Bạn có thể cung cấp menu ngữ cảnh cho bất kỳ chế độ xem nào nhưng chúng thường được sử dụng cho các mục trong một bộ sưu tập ListView, GridView hoặc chế độ xem khác, trong đó người dùng có thể thực hiện các tác vụ trực tiếp trên mỗi mục.

Như hướng dẫn, các tài liệu phân biệt giữa sử dụng của họ: - PopupMenu: "Cung cấp một thực đơn tràn kiểu cho hành động mà liên quan đến nội dung cụ thể (chẳng hạn như tiêu đề email của Gmail ..." - ContextualMenu : "Đối với hành động mà ảnh hưởng nội dung được lựa chọn ..."

tôi là sau khi giao diện trực quan và tương tác của các PopupMenu

M. y setup (và goal)

Tôi có một ListView trong đó mỗi mục có một nút ở bên phải.

-------------------- 
| Item 1  [ ]| 
-------------------- 
-------------------- 
| Item ...  [ ]| 
-------------------- 
-------------------- 
| Item n  [ ]| 
-------------------- 

trong khi giữ lại onItemClick cho mỗi ListItem, tôi muốn tận dụng nút để kích hoạt một PopupMenu.

Các hành động trong PopupMenu được liệt kê trong my_menu.xml, do đó, sự khác biệt duy nhất giữa mỗi trường hợp của menu là mục mà nó được nhấp vào.

Những gì tôi đã cố gắng

Tôi đã thử trọng getView() trong ListAdapter tôi thêm một OnClickListener cho mỗi nút, theo this post. Kết quả không nhất quán; không phải tất cả các nhấp chuột đều được đăng ký (có lẽ do tái chế - tôi chưa có tried this fix) nhưng nói chung cách tiếp cận có vẻ hơi khó khăn, xem xét việc dễ dàng chỉ định một menu ngữ cảnh cho một listview.

Tôi cũng đã thử thêm một menu ngữ cảnh, đã chết dễ dàng, ngoại trừ việc nó chỉ được kích hoạt khi mục danh sách được nhấn lâu.

Phương pháp getView() có phải là cách để đi hoặc có điều gì đó dễ dàng hơn không?

Trong chế độ xem danh sách của tôi, tôi có nút tràn nhỏ cho mỗi mục, tương tự như mỗi bản nhạc trong danh sách phát cho Play Âm nhạc. Họ hiển thị PopupMenu cho mỗi mục ở đó, khi bạn nhấp vào nút tràn. Nhấn và giữ không có gì.

Tôi thích điều đó nhưng không chắc chắn như thế nào? Trang menu chỉ trình bày cách bật menu bật lên cho các chế độ xem riêng lẻ.

registerForContextMenu(ListView lv) là điều duy nhất tôi thấy rằng tôi có thể áp dụng cho toàn bộ ListView, nhưng điều đó dường như chỉ hoạt động trên các lần nhấn dài toàn bộ danh sách. Có cách nào để móc sự kiện đó vào một lần nhấp vào một chế độ xem cụ thể trong một mục danh sách (trong khi vẫn duy trì mục danh sách nhấp cho phần còn lại của mục danh sách) không?

Tôi đã thử đặt onClickListener trong getView() như được mô tả ở đây nhưng nó cảm thấy ngột ngạt cho PopupMenu và không phải tất cả các lần nhấp đều được đăng ký mọi lúc (nó không nhất quán).

Update - với getView() ghi đè một lần nữa

Khi tôi tạo ra StacksCursorAdapter, tôi vượt qua một thể hiện của StackViewFragment mà được lưu giữ như một lĩnh vực (vì vậy nó có thể được giao cho quan điểm như người nghe nhấp chuột).

ViewHolder là một lớp học với public final ImageView miniOverflow

StacksCursorAdapter (mở rộng SimpleCursorAdapter):

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    View row = super.getView(position, convertView, parent); 
    ViewHolder holder = (ViewHolder) row.getTag(); 

    if (holder == null) { 
     holder = new ViewHolder(row); 
     row.setTag(holder); 
    } 
    holder.miniOverflow.setTag(R.id.tag_stack_position, position); 
    holder.miniOverflow.setOnClickListener(listener); 

    return row; 
} 

StackViewFragment (mở rộng ListFragment, thực hiện View.OnClickListener):

@Override 
public void onClick(View v) { 
    Log.d(TAG, "mini overflow clicked"); 
    Log.d(TAG, "position:::::" + v.getTag(R.id.tag_stack_position)); 

    PopupMenu popup = new PopupMenu(getActivity(), v); 
    MenuInflater inflater = popup.getMenuInflater(); 
    inflater.inflate(R.menu.menu_stackview_listitem, popup.getMenu()); 
    popup.show(); 
} 

stack_list_item.xml:

<?xml version="1.0" encoding="utf-8"?> 
<!-- a single row item for a Stacks listview --> 
<RelativeLayout 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="match_parent" 
     android:layout_height="48dp" 
     android:descendantFocusability="blocksDescendants" 
     > 

    ... 
    <other views> 
    ... 


    <ImageView 
      android:id="@+id/moreoverflow_btn" 
      android:focusable="false" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_centerVertical="true" 
      android:alpha="0.4" 
      android:scaleType="fitCenter" 
      android:src="@drawable/ic_menu_moreoverflow_black" 
      android:layout_alignParentRight="true" 
      /> 
</RelativeLayout> 

Sự cố tại ngã ba này là thỉnh thoảng tôi phải nhấp nhiều lần để nhận được nhấp chuột để đăng ký (trên nút). Điều này là không có cuộn, vì vậy nó không liên quan đến xem tái chế.

Kết (giải pháp bởi eskimoapps.com đánh dấu là đúng)

Vì vậy, không có vấn đề với nhiều lần nhấp chuột ngoại trừ mục tiêu liên lạc của tôi đã không ở nơi tôi đã mong đợi - tài sản hình ảnh tôi đã được sử dụng cho tràn nhỏ được đặt ở bên phải (sao cho ba dấu chấm gần cạnh phải của mục tiêu cảm ứng) có nghĩa là tôi chỉ bị thiếu một nửa thời gian (facepalm).

Overriding getView() như tôi đã giới thiệu ở trên dường như làm việc tốt, và trên thực tế, getView() thể được sửa đổi hơn nữa, bằng cách thiết lập OnClickListener chỉ khi nó là cần thiết (nhưng chắc chắn, cập nhật thẻ cần phải được thực hiện cho mỗi xem , không chỉ những người mới được tạo):

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    View row = super.getView(position, convertView, parent); 
    ViewHolder holder = (ViewHolder) row.getTag(); 

    if (holder == null) { 
     holder = new ViewHolder(row); 
     row.setTag(holder); 
     holder.miniOverflow.setOnClickListener(listener); 
    } 
    holder.miniOverflow.setTag(R.id.tag_stack_position, position); 

    return row; 
} 
+0

u có thể xin vui lòng mô tả cách u thêm người biết lắng nghe? đối tượng nghe là gì? holder.miniOverflow.setOnClickListener (người nghe); –

+0

@mahdi nó sẽ thuộc loại 'View.OnClickListener' – ataulm

Trả lời

3

Ghi đè quá mức sẽ làm phức tạp mọi thứ (nếu bạn đang ở chế độ xem tái chế).

Vì không có phương pháp getOnClickListener, bạn chỉ cần đặt OnClickListener mới cho chế độ xem được tái chế cũng như các chế độ xem chưa được tạo (nếu bạn không muốn tạo chế độ xem tùy chỉnh triển khai getOnClickListener).

+0

nếu một chế độ xem đã được tái chế, tôi có thể giả sử nó vẫn có OnClickListener không, vậy chỉ đặt nó cho cái mới? Điều này nghe giống như một bình luận tôi chỉ nên thử ..: P – ataulm

+0

Nó vẫn có một OnClickListener, chỉ cần không phải là một trong những quyền đó là lý do tại sao bạn cần phải thiết lập một cái mới. – eski

+0

Tôi không hiểu - tôi đang thêm ListFragment làm người nghe cho từng mục; đó là, chỉ có một. chỉnh sửa: mà nói, tôi chỉ thử nó, và nó đã không bắn cho bất kỳ mục danh sách. – ataulm

1

Nếu tôi muốn thực hiện việc này hôm nay, tôi sẽ sử dụng mẫu HolderView.

Mẫu HolderView yêu cầu chế độ xem/chế độ xem tùy chỉnh (một lớp mở rộng Chế độ xem/Chế độ xem là gốc của bố cục danh sách/mục lưới của bạn, với 3 trình tạo khung nhìn chuẩn).

Ý tưởng chung là bộ điều hợp không chịu trách nhiệm cập nhật nội dung của chế độ xem trực tiếp; thay vào đó, nó sẽ cung cấp cho các quan điểm tất cả các thông tin cần thiết để cập nhật bản thân:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    if (convertView == null) { 
     convertView = createView(parent); 
    } 

    updateView((GalleryItemView) convertView, position); 

    return convertView; 
} 

private View createView(ViewGroup parent) { 
    LayoutInflater inflater = LayoutInflater.from(parent.getContext()); 

    return inflater.inflate(R.layout.gallery_item_view, null, false); 
} 

private void updateView(GalleryItemView view, int position) { 
    GalleryElement item = getItem(position); 

    view.updateWith(position, item, listener); 
} 

Theo quan điểm của tôi:

public class GalleryItemView extends ImageView { 

    public GalleryItemView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    void updateWith(int position, final GalleryElement item, final GalleryAdapter.GalleryItemListener listener) { 
     if (position % 2 == 0) { 
      setBackgroundColor(getColor(android.R.color.holo_orange_dark)); 
     } else { 
      setBackgroundColor(getColor(android.R.color.holo_orange_light)); 
     } 

     setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       listener.onGalleryItemClicked(item.id); 
      } 
     }); 
    } 

    @ColorInt 
    private int getColor(@ColorRes int colorRes) { 
     return getResources().getColor(colorRes); 
    } 

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