(Không được chấp nhận) Phân mảnh onOptionsItemSelected không được gọi


82

CHỈNH SỬA: Câu hỏi này dành cho thanh tác vụ sherlock không dùng nữa. Thư viện hỗ trợ Android sẽ được sử dụng thay thế ngay bây giờ

Tôi đã thêm một tùy chọn menu thanh tác vụ được gọi là chia sẻ cho của tôi fragment, tùy chọn này xuất hiện nhưng sự kiện lựa chọn không được bắt

Tôi đang thêm nó như thế này

@Override
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {
    MenuItem item = menu.add(0, 7,0, R.string.share);
    item.setIcon(R.drawable.social_share).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}

Đang cố gắng để nắm bắt nó trong cả hai fragmentfragment activitynhư

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case 7:
            Intent share = new Intent(Intent.ACTION_SEND);
            share.setType("text/plain");
            share.putExtra(Intent.EXTRA_TEXT, "I'm being sent!!");
            startActivity(Intent.createChooser(share, "Share Text"));
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

và tôi có setHasOptionsMenu(true);trong onCreate().

Câu trả lời:


145

Các vấn đề tương tự đã xảy ra với tôi:

onMenuItemSelected các sự kiện không được gọi trong Fragment

Đã tìm kiếm trên google không thể tìm ra giải pháp và thêm phương thức onMenuItemSelected trong FragmentActivity không giải quyết được vấn đề đó.

Cuối cùng giải quyết nó bằng cách theo tham khảo http://developer.android.com/guide/topics/ui/actionbar.html

Lưu ý: Nếu bạn đã thêm mục menu từ một phân đoạn, thông qua lệnh gọi lại onCreateOptionsMenu của lớp Fragment, thì hệ thống sẽ gọi phương thức onOptionsItemSelected () tương ứng cho phân đoạn đó khi người dùng chọn một trong các mục của phân đoạn. Tuy nhiên, hoạt động có cơ hội xử lý sự kiện trước, vì vậy hệ thống gọi onOptionsItemSelected () trên hoạt động trước khi gọi cùng một lệnh gọi lại cho phân đoạn.

Điều đó có nghĩa là chỉ khi bạn không có trình xử lý mục menu đó trong onOptionsItemSelected () trên hoạt động, thì onOptionsItemSelected () trên phân đoạn sẽ được gọi.

Mã như sau ----- Xóa trình xử lý cho R.action.add trên FragmentActivity):

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case android.R.id.home:
            popBackStack();             
            return true;        
        case R.id.action_search:
            searchAction();
            return true;
        case R.id.action_logout:
            userLogout();
            return true;
        //case R.id.action_add:
            //return true;    
        default:
            return super.onOptionsItemSelected(item);
    }   
}

Và trình xử lý cho R.action.add trên Fragment trông như thế này:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    Log.d("onOptionsItemSelected","yes");
    switch (item.getItemId()) {
        case R.id.action_add:
            add();
            return true;    
        default:
            return super.onOptionsItemSelected(item);
    }
}

Cuối cùng, hãy nhớ thêm

    setHasOptionsMenu(true);

trong phương thức onCreate của bạn trong Fragment


12
Đối với tôi, để chặn việc nhấp vào menu trên phân đoạn, tôi phải trả về "false" trên onOptionsItemSelected của FragmentActivity và trên onOptionsItemSelected của phân đoạn, hãy thực hiện hành vi mong muốn.
Edison Santos

1
phân mảnh với setHasOptionsMenu (true); trong onCreate và public boolean onOptionsItemSelected (MenuItem item) {} phương pháp đã làm điều kỳ diệu
Moisés

@Felixqk Tôi đang gặp sự cố như thế này với Fragment. Tôi có hai mảnh vỡ. Nhưng OnOptionsSelectedItem của phân đoạn 2 không được gọi. Phân đoạn 2 đang hiển thị tùy chọn menu của phân đoạn 1.
Roon13

@ Roon13 Xóa super.onCreateOptionsMenu; từ onCreateOptionsMenu của phân mảnh. + setHasOptionsMenu (true); đã làm việc cho tôi mà không xóa Activity onOptionsItemSelected.
ahmadalibaloch

129

Tôi đã gặp vấn đề tương tự, nhưng tôi nghĩ tốt hơn nên tóm tắt và giới thiệu bước cuối cùng để nó hoạt động:

  1. Thêm setHasOptionsMenu(true)phương thức trong phương thức Fragment của bạn onCreate(Bundle savedInstanceState).

  2. Ghi đè onCreateOptionsMenu(Menu menu, MenuInflater inflater)(nếu bạn muốn làm điều gì đó khác biệt trong menu của Fragment) và onOptionsItemSelected(MenuItem item)các phương thức trong Fragment của bạn.

  3. Bên trong onOptionsItemSelected(MenuItem item)phương thức Activity của bạn , hãy đảm bảo rằng bạn quay lại falsekhi hành động của mục menu sẽ được triển khai trong onOptionsItemSelected(MenuItem item)phương thức của Fragment .

Một ví dụ:

Hoạt động

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.activity_menu_item:
        // Do Activity menu item stuff here
        return true;
    case R.id.fragment_menu_item:
        // Not implemented here
        return false;
    default:
        break;
    }

    return false;
}

Miếng

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
    ....
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // Do something that differs the Activity's menu here
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.activity_menu_item:
        // Not implemented here
        return false;
    case R.id.fragment_menu_item:
        // Do Fragment menu item stuff here
        return true;
    default:
        break;
    }

    return false;
}

6
return falsetrên Activity's onOptionItemSelectedlà chìa khóa. chỉ cần thay thếreturn super.onOptionItemSelected(item);
Youngjae

1
Hoạt động hoàn hảo. Cảm ơn Marco.
Rajeev Sahu

2
Câu trả lời chính xác. Bạn nên thay đổi onCreateOptionsMenu (Menu menu) để onCreateOptionsMenu (Menu menu, MenuInflater inflater) khi nó trong một mảnh
Chris Sprague

1
Đó là giải pháp tuyệt vời. Thnakx Marco HC
Darsh Patel

1
Giải pháp tuyệt vời bạn của tôi! Cảm ơn!
Han Tran

5

Tôi nhận thấy rằng giải pháp mọi người đưa ra cho bạn là triển khai mã cho mục trình đơn của bạn trong hoạt động thay vì phân đoạn. Tôi nghĩ rằng nó sẽ trông đẹp hơn nhiều nếu bạn đã triển khai mã trong phân đoạn thay vì sau đó hoạt động 'vì theo ý kiến ​​của tôi, nó trông tốt hơn. Để làm như vậy, hãy làm như sau:

Hoạt động

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.menu, menu);      
        return true;
    }

 @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {            
        switch (item.getItemId())
        {
            case R.id.SomeIDInTheMenueOfTheActivity:
            {
               //something();
                break;
            }
            default:
             //do something default and add the code under : 
             return super.onOptionsItemSelected(item);
        }
        return true;
    }

Miếng

 @Override
    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);  
            setHasOptionsMenu(true);      
        }

  @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
    {           
        super.onCreateOptionsMenu(menu, inflater);
    }

     @Override
        public boolean onOptionsItemSelected(MenuItem item)
        {
            switch (item.getItemId())
            {           
                case R.id.SomeIDInFragmentMenue:
                {             
                    break;
                }

                default:
                    return super.onOptionsItemSelected(item);
            }

            return true;
        }

Bây giờ là các dòng (và các dòng thích): "return super.onOptionsItemSelected (item);" trong hoạt động và phân đoạn là cực kỳ quan trọng, vì như thể bạn làm theo mã khi gỡ lỗi, bạn sẽ thấy rằng các hàm sự kiện menue sẽ được gọi đầu tiên trên Hoạt động và nếu mục không khớp với id trong chuyển đổi của hoạt động- trường hợp, dòng degault: "super.onOptionsItemSelected (item);" sẽ gọi hàm onOptionsItemSelected trên phân mảnh, như chúng ta muốn. (nếu bạn có nhiều đoạn, hãy đảm bảo có dòng đó trong chúng, vì cấu trúc gọi có thể hơi phức tạp).


2

Tôi đang sử dụng actionbarsherlock. Điều này đã làm việc cho tôi:

1) Tạo menu dummy_menu.xml

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="fill_parent" >
<item
      android:title=""
      android:showAsAction="never"
      android:id="@+id/dummyMenu"
        />

2) Trong hoạt động thổi phồng menu như thế này:

@Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
    com.actionbarsherlock.view.MenuInflater inflater = getSupportMenuInflater();
   inflater.inflate(R.menu.dummy_menu,menu);
   return super.onCreateOptionsMenu(menu);
}

3) Trong các phân đoạn, onCreateView gọi setHasOptionsMenu (true) và ghi đè onCreateOptionsMenu và onOptionsItemSelected cũng ẩn dummyMenu như thế này (trong phân mảnh)

    @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.fragment_actions, menu);
    MenuItem item = menu.findItem(R.id.dummyMenu);
    item.setVisible(false);
    super.onCreateOptionsMenu(menu, inflater);
}

Hy vọng nó sẽ giúp một ai đó.


2

Chỉnh sửa để sử dụng thanh tác vụ

Tôi đã phải sử dụng

public boolean onMenuItemSelected(int featureId, MenuItem item) {

trong hoạt động chính để nắm bắt mục menu


Cùng một vấn đề và nó đã được khắc phục cho tôi, cảm ơn. Bạn có thể cho biết tại sao onOptionItemSelected không hoạt động không?
nadeem gc

Nguyên nhân thanh hành động sherlock không sử dụng phương pháp này
user1634451

Thay đổi onMenuItemSelected để gọi onOptionItemSelected để mã của bạn sẽ hoạt động khi chuyển từ ABS sang appcompatlib
slott

1
@nadeemgc lý do nó không hoạt động là vì Android biết về hai loại menu: Menu tùy chọn và Menu ngữ cảnh. Actionbar Sherlock sử dụng Menu ngữ cảnh, onContextItemSelectedthay vì gọi onOptionsItemSelected. Chỉ onMenuItemSelectedđơn giản là chuyển tiếp nhấp chuột đến đúng phương pháp, đó là lý do tại sao nó hoạt động tốt hơn.
Amru E.

@AmruE. Cảm ơn bạn, nó sẽ hữu ích trong tương lai.
nadeem gc

2

thật đơn giản, bạn có thể thực hiện điều đó trong phân đoạn của mình để đảm bảo rằng hành động của bạn sẽ nghe đúng:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

0

Tôi đã có vấn đề này. Đó là vì tôi đã đánh giá sai phương pháp

onOptionsItemSelected (com.actionbarsherlock.view.MenuItem item) là những gì tôi đã sử dụng.

Hãy chắc chắn rằng bạn đang sử dụng đúng!


0

Bạn không chuỗi vào lớp cha trong các phương thức hoạt động. Vui lòng có onCreateOptionsMenu () trả về super.onCreateOptionsMenu (menu) và có onOptionsItemSelected () trả về super.onOptionsItemSelected (mục) (ngoại trừ mục mà bạn đang xử lý, sẽ trả về true để cho biết rằng bạn đã xử lý sự kiện)


0

bạn phải thêm mã này toolbar.bringToFront();vào thanh công cụ đặt tiếp theo trong hoạt động của mình

 public class MainActivity extends AppCompatActivity {
     protected void onCreate(Bundle savedInstanceState) {
        ...

        Toolbar toolbar = findViewById(R.id.toolbar);
        toolbar.setTitle("Yazd");
        setSupportActionBar(toolbar);
        toolbar.bringToFront(); // <<= add here
         ...
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.