OnCreateOptionsMenu () không được gọi trong Fragment


107

Tôi có một ứng dụng có một hoạt động với 2 mảnh được đặt theo chiều ngang.

Trong hoạt động của mình, tôi đã tăng menu bằng onCreateOptionsMenu()cách sử dụng mà tôi có thể hiển thị menu tùy chọn thanh tác vụ. Nhưng khi tôi cố gắng cập nhật các mục menu của thanh tác vụ từ một trong các phân đoạn của tôi, phân đoạn onCreateoptionsmenu()không được gọi. Vì vậy, tôi không thể cập nhật menu tùy chọn thanh tác vụ.

Mã trong hoạt động của tôi như sau:

myActivity.java

package com.andr.androidtablelist;

import java.io.IOException;

import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;

import com.andr.fragments.ListLeftFragment;
import com.andr.utils.DBHelper;

      public class TabletActivity extends Activity {
    ActionBar actionBar = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DBHelper dbhelper;
        dbhelper = new DBHelper(this);
        try {
            dbhelper.createDatabase();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        setContentView(R.layout.activity_tablet);
        actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(false);
        getFragmentManager().beginTransaction()
                .replace(R.id.master, ListLeftFragment.newInstance()).commit();
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            Toast.makeText(
                    getApplicationContext(),
                    "Back Stack Count::"
                            + getFragmentManager().getBackStackEntryCount(),
                    Toast.LENGTH_LONG).show();
            if (getFragmentManager().getBackStackEntryCount() == 1) {
                actionBar.setDisplayHomeAsUpEnabled(false);
            }
            if (getFragmentManager().getBackStackEntryCount() > 1) {
                getFragmentManager().popBackStack();

            }
            return true;

        }
        return super.onOptionsItemSelected(item);
    }

}
      // http://www.vogella.com/articles/AndroidListView/article.html

myFragment.java

      package com.andr.fragments;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.TextView;

import com.andr.androidtablelist.R;
import com.andr.helper.LazyHelper;

   public class ListLeftFragment extends Fragment{
    private static ListLeftFragment listFragment = null;

    public static ListLeftFragment newInstance(){
        listFragment = new ListLeftFragment();      
        return listFragment;
    }

     @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);


    }

     @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
         View v =  inflater.inflate(R.layout.fragment_listlayout, container,false);
         getActivity().invalidateOptionsMenu();
         ListView lv = (ListView)v.findViewById(R.id.lview);
         String[] values = new String[] { "Android", "iPhone", "WindowsMobile",
                    "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X",
                    "Linux", "OS/2", "Ubuntu", "Windows7", "Max OS X", "Linux",
                    "OS/2", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2",
                    "Android", "iPhone", "WindowsMobile" };
         getActivity().getActionBar().setTitle("LeftList");

          ArrayList<String> list = new ArrayList<String>();
         LazyHelper lHelper = new LazyHelper(getActivity());
         list = lHelper.getLazyDetials();

           /* for (int i = 0; i < values.length; ++i) {
              list.add(values[i]);
            }
            final StableArrayAdapter adapter = new StableArrayAdapter(getActivity(),
                android.R.layout.simple_list_item_1, list);*/
            LeftListAdapter lAdapter = new LeftListAdapter(getActivity(),list);
            lv.setAdapter(lAdapter);
            lv.setOnItemClickListener(new OnItemClickListener()
            {

                @Override
                public void onItemClick(AdapterView<?> arg0, View arg1,
                        int pos, long arg3) {
                    final String clickedData = (String)arg0.getItemAtPosition(pos);
                    Bundle bundle = new Bundle();
                    bundle.putString("clickedItemName", clickedData);
                    Fragment detailFragment = DetailFormRightFragment.newInstance();
                    detailFragment.setArguments(bundle);
                    getActivity().getFragmentManager().beginTransaction().replace(R.id.details, detailFragment).addToBackStack(null).commit();
                }

            }
                    );
         return v;
    }


     @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        getActivity().getMenuInflater().inflate(R.menu.search, menu);
        SearchView searchView=(SearchView)menu.findItem(R.id.search);
        searchView.setIconifiedByDefault(true);
    } 

     @Override
    public boolean onOptionsItemSelected(MenuItem item) {

         super.onOptionsItemSelected(item);
         return false;
    }


     @Override
    public void onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
        /*MenuItem item;
        menu.clear();
        getActivity().getMenuInflater().inflate(R.menu.search, menu);
        SearchView searchView=(SearchView)menu.findItem(R.id.search);
        searchView.setIconifiedByDefault(true);*/
    }

     private class StableArrayAdapter extends ArrayAdapter<String> {

            HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();

            public StableArrayAdapter(Context context, int textViewResourceId,
                List<String> objects) {
              super(context, textViewResourceId, objects);
              for (int i = 0; i < objects.size(); ++i) {
                mIdMap.put(objects.get(i), i);
              }
            }

            @Override
            public long getItemId(int position) {
              String item = getItem(position);
              return mIdMap.get(item);
            }

            @Override
            public boolean hasStableIds() {
              return true;
            }

          }

     private class LeftListAdapter extends BaseAdapter implements OnClickListener {
         private Context mcontext;
         ArrayList<String> listData;
         private  LayoutInflater inflater=null;
         public LeftListAdapter(Context context, ArrayList<String> listItems) {
              mcontext=context;
              listData=listItems;
              inflater = (LayoutInflater)mcontext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         }

        @Override
        public int getCount() {
            return listData.size();
        }

        @Override
        public Object getItem(int arg0) {
            return null;
        }

        @Override
        public long getItemId(int arg0) {
            // TODO Auto-generated method stub
            return 0;
        }

        @Override
        public View getView(int position, View view, ViewGroup arg2) {
            // create a ViewHolder reference
            View vi=view;
            if(vi==null){
                vi = inflater.inflate(R.layout.item, null);
            }
            TextView text=(TextView)vi.findViewById(R.id.text);
            text.setText(listData.get(position));
            vi.setOnClickListener(this);
            return vi;
        }

        @Override
        public void onClick(View vi) {
            TextView text=(TextView)vi.findViewById(R.id.text);
            Bundle bundle = new Bundle();
            bundle.putString("clickedItemName", text.getText().toString());
            Fragment detailFragment = DetailFormRightFragment.newInstance();
            detailFragment.setArguments(bundle);
            getActivity().getFragmentManager().beginTransaction().replace(R.id.details, detailFragment).addToBackStack(null).commit();          
        }

     }
   }

Câu trả lời:


296

Trong onCreateView()phương thức của phân đoạn , bạn cần gọi setHasOptionsMenu(true)để thông báo cho hoạt động máy chủ lưu trữ rằng phân đoạn của bạn có các tùy chọn menu mà nó muốn thêm vào.


Tôi đã thực hiện thay đổi nhưng ứng dụng gặp sự cố với 11-27 01: 55: 34.468: E / AndroidRuntime (12294): Nguyên nhân do: java.lang.ClassCastException: com.android.internal.view.menu.MenuItemImpl không thể truyền sang android .widget.SearchView
Android_programmer_office

vâng, tôi đã tìm thấy vấn đề. quên thêm getActionView () cho searchView.
Android_programmer_office

2
Ngoài ra, bạn phải sử dụng kiểu void cho onCreateOptionsMenu (menu Menu, MenuInflater inflater) kiểu Boolean sẽ không làm việc
Bahaa Hany

15
Nếu bạn đang sử dụng Toolbartrong bố cục Hoạt động của mình, hãy đảm bảo rằng bạn gọi setSupportActionBar(your_toolbar)trong Hoạt động của mình. Nếu không thì không setHasOptionsMenucó hiệu lực.
artkoenig 19/02/18

You are my love bro :)
Qadir Hussain

30

Nếu bạn đang sử dụng một chủ đềkhông hỗ trợ ActionBar, sau đó OnCreateOptionsMenu () sẽ không được gọi tự động, ngay cả khi bạn đã viết tất cả các mã Java đúng cách.

Bạn có thể mở AndroidManifest.xml, thay đổi giá trị của android: theme thành "@android: style / Theme.Holo.Light.DarkActionBar" hoặc bất kỳ chủ đề nào khác hỗ trợ ActionBar.


tôi đang sử dụng thanh công cụ từ thư viện hỗ trợ và Theme.AppCompat.Light.NoActionBar như chủ đề và tôi đang phải đối mặt với cùng một vấn đề ... không có trình đơn tùy chọn displayed..plz giúp đỡ
Dhruvam Gupta

6
tôi giải quyết nó bằng cách gọitoolbar.inflateMenu(R.menu.menu_custom);
Dhruvam Gupta

Chỉ cần gọi setSupportActionBar (mToolbar) trong hoạt động của bạn và onCreateOptionsMenu trong Fragment sẽ được gọi tự động.
Vít Kapitola

12

điều này làm việc cho tôi

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    setHasOptionsMenu(true);
    View view = inflater.inflate(R.layout.sample, null);
}

11

Ngoài ra, hãy đảm bảo rằng phiên bản Thanh công cụ bạn đang chuyển đến

setSupportActionBar(toolbar);

trong Hoạt động của bạn thì không null, bởi vì bạn sẽ không nhận được ngoại lệ nếu thực sự là như vậy nullvà bạn sẽ mất vài giờ như tôi đã làm.

Tôi đã sử dụng ButterKnife để ràng buộc các lượt xem, nhưng vô tình bị đặt setSupportActionBar(toolbar)trước khi tôi thực sự gọiButterKnife.bind()


1
Haris, bạn thật tuyệt vời. Cảm ơn vì đã chia sẻ! Tôi gặp sự cố chính xác này vì tôi đang sử dụng Kotlin và nhiều khi bạn không phải thực hiện findViewById, v.v. để có được chế độ xem bạn cần.
DWndrer

1

Đơn giản chỉ cần cho hoạt động máy chủ lưu trữ biết rằng phân đoạn của bạn có menu tùy chọn trong phương thức khởi tạo của nó.

public YourFragment () {setHasOptionsMenu (true);}

Mặc dù nó hiệu quả với tôi, nhưng nó không được khuyến khích như đã lưu ý trong nhận xét từ @aldorain

Các ứng dụng thường không nên triển khai một phương thức khởi tạo. Mã ứng dụng vị trí đầu tiên có thể chạy ở nơi mà phân đoạn sẵn sàng được sử dụng là onAttach (Hoạt động), điểm mà phân đoạn thực sự được liên kết với hoạt động của nó.

Vì vậy, hãy đặt setHasOptionsMenu (true) trong onCreateView () hoặc onAttach () để thay thế.


Bạn không nên viết các hàm tạo của riêng mình cho các phân đoạn tùy chỉnh
aldorain

1
developer.android.com/reference/android/app/Fragment.html tl; dr 'Các ứng dụng nói chung không nên triển khai hàm tạo [Fragment].'
aldorain

0

Tôi có một chủ đề không cung cấp cho bạn AppBar theo mặc định và bạn đang sử dụng chế độ xem thanh công cụ để cung cấp tính năng này thay thế, ĐỪNG QUÊN gọi setSupportActionBar (thanh công cụ) trong phương thức onCreate () của hoạt động lưu trữ của bạn mảnh vỡ.

Sau đó gọi setHasOptionsMenu (true) trong phương thức phân mảnh onCreate () của bạn.

:)


-2

Đặt setHasOptionsMenu(true)trong onCreateView()phương thức trong phân đoạn.

@Override

 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
 {
    Viewroot=inflater.inflate(R.layout.fragment_client_requestfragment,container,false);
  hideKeyboard();
    getemail = getArguments().getString("email_id");
    Log.e("email_id from activity",getemail);
    setHasOptionsMenu(true);
    return root;
}

1
Xin chào và chào mừng đến với SO. Vui lòng không chỉ đăng các câu trả lời chỉ có mã không có chú thích và có định dạng sai vì điều này không giải thích chính xác vấn đề được mô tả trong câu hỏi là gì. Kiểm tra ở đây để biết một số mẹo chung về những gì tạo nên một câu trả lời tốt.
Gero
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.