Android'de Fragment'a Seçenekler Menüsü nasıl eklenir


399

Bir grup parçadan seçenekler menüsüne bir öğe eklemek çalışıyorum.

Ben yeni bir MenuFragmentsınıf oluşturduk ve bu menü öğesi eklemek istediğiniz parçalar için genişletilmiş. İşte kod:

Java:

public class MenuFragment extends Fragment {

    MenuItem fav;

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

    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        fav = menu.add("add");
        fav.setIcon(R.drawable.btn_star_big_off);
    }
}

Kotlin:

class MenuFragment : Fragment {

    lateinit var fav: MenuItem

    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        fav = menu.add("add");
        fav.setIcon(R.drawable.btn_star_big_off);
    }
}

Bazı nedenlerden dolayı onCreateOptionsMenuçalışmaz.


belki aptalca bir soru ... menü düğmesine basarsın değil mi?
Ovidiu Latcu

2
..lol ... evet menü düğmesine bastım, ayrıca ve olmadan da denedim: fav.setShowAsAction (MenuItem.SHOW_AS_ACTION_ALWAYS);
misterbassman

Merhaba, belki bu konu size yardımcı olacak veya api demosunu çalışan bir örnek için kontrol edecektir .
kameny

Yanıtlar:


604

Süper yöntemi çağırın:

Java:

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

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // TODO Add your menu entries here
        super.onCreateOptionsMenu(menu, inflater);
    }

Kotlin:

    override fun void onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        // TODO Add your menu entries here
        super.onCreateOptionsMenu(menu, inflater)
    }

Yöntemin çağrılmadığını veya menünün kodunuz tarafından değiştirilip değiştirilmediğini görmek için günlük deyimlerini koda koyun.

Ayrıca Aradığınız sağlamak setHasOptionsMenu(boolean)içinde onCreate(Bundle)bu seçenekler menüsü işleme katılması gerektiğini fragman bildirmek için.


2
Yardım için teşekkürler, süper yöntemi ekledim ve @Override'ı kaldırdığımı fark ettim, bu yüzden bu geri eklendi, tutulma bir hata attı, bu yüzden android.view.MenuInflater'ı içe aktarmak için MenuInflater'ın yerini aldım; ithalat yerine android.support.v4.view.MenuInflater; ve şimdi hepsi çalışıyor
misterbassman

183
Fragment'ın onCreate'deki setHasOptionsMenu (true)
çağrılmıyor

7
Faaliyetimi bir Fragment'e aktarıyordum ve bu sorunla karşılaştım. Yöntem imzası genel boole'den genel boşluğa değişti ve argümanlar da değişti. Bunu not ettiğinizden emin olun!
you786

14
Fragment.onCreateOptionsMenu'nun (Menu, MenuInflater) boş bir yöntem olduğunu unutmayın, bu nedenle super çağrılması hiç gerekli değildir. Buradaki tek hata, yanlış yöntem imzası ve muhtemelen eksik bir setHasOptionsMenu () onCreate ()
cmende içinde

6
Super.onCreateOptionsMenu yerine inflater.inflate (R.menu.menu_custom, menü);
Code_Worm

197

Aynı problemim vardı, ancak çalışmasını sağlamak için son adımı özetlemek ve tanıtmak daha iyi:

  1. Parçanızın yöntemine setHasOptionsMenu (true) yöntemini ekleyin onCreate(Bundle savedInstanceState).

  2. onCreateOptionsMenu(Menu menu, MenuInflater inflater)(Parçanızın menüsünde farklı bir şey yapmak istiyorsanız) ve onOptionsItemSelected(MenuItem item)Parçanızdaki yöntemleri geçersiz kılın .

  3. Senin İçinde onOptionsItemSelected(MenuItem item)etkinlik'ın yöntemi emin menü öğesi eylem uygulanacağına dair zaman return false yapmak onOptionsItemSelected(MenuItem item)Fragment yöntemi.

Bir örnek:

Aktivite

@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;
}

fragman

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;
}

2
Sadece eksikti setHasOptionsMenu(true);Teşekkürler
Chad Bingham

1
Bir görünümde Bazı cihazlarda menü, parçaya ikinci kez gittiğinizde gösterilir
Roel

3
@Marco HC kodunuz iyi çalışıyor. Ancak, Etkinlik veya Parça için menünün bazılarını gizlemek istersem ne olur? Hangi seçenek menüsünün nereye uygulanacağından bahsettiniz (Etkinlik ve parça halinde). Peki ya bazı menüleri gizlemek istersem?
Shreyash Mahajan

@iDroidExplorer sadece bu MenuItem referans tutmak ve görünmez gitti veya görünmez olarak ayarlayın. Sorunuz bu mu?
Marco HC

@IDroidExplorer Kodunu denedim ve nasıl olduğunu bilmiyorum ama diğer parçalara geçince menüyü otomatik olarak gizliyor.
Noor Ali Butt

156

Eğer bulursanız onCreateOptionsMenu(Menu menu, MenuInflater inflater)yöntemi çağrılan değil, emin olun Fragment en aşağıdaki çağrı onCreate(Bundle savedInstanceState)yöntemiyle:

setHasOptionsMenu(true)

NullPointerException
Pratik Butani

2
İyi bir nokta. Statik newInstance yönteminden setHasOptionMenu yöntemini çağırıyordum. Parçamı sadece saveInstanceState boşken eklediğim için, ekran yapılandırması değiştiğinde menü oluşturulmaz. Parçanın onCreate yöntemi, setHasOptionMenu değerini true olarak ayarlamak için doğru yerdir.
argenkiwi

1
Ben kullanıyorum Toolbarve aramak zorunda setHasOptionsMenu(true)içinde onCreateView()yerine onCreate()onu halletmek için.
CLOUGH

60

Belirli menubir webviewiçini yenilemek için a gerekiyorsa Fragmentşunları kullanabilirsiniz:

fragman :

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

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    // TODO Add your menu entries here
    inflater.inflate(R.menu.menu, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.exit:
        System.exit(1);
        break;

    case R.id.refresh:
        webView.reload();
        break;
    }
    return true;

}

menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/exit" android:title="Exit" android:icon="@drawable/ic_action_cancel" />
    <item android:id="@+id/refresh" android:title="Refresh" android:icon="@drawable/ic_action_refresh" />
</menu>

31

TL; DR

Kullanın android.support.v7.widget.Toolbarve yapın:

toolbar.inflateMenu(R.menu.my_menu)
toolbar.setOnMenuItemClickListener {
    onOptionsItemSelected(it)
}

Bağımsız Araç Çubuğu

Önerilen çözümlerin çoğu, setHasOptionsMenu(true)yalnızca üst Etkinliğin mizanpajında ​​Araç Çubuğu olduğunda ve bunu bildirdiği zaman çalışır setSupportActionBar(). Daha sonra Parçalar, bu tam ActionBar öğesinin menü popülasyonuna katılabilir :

Fragment.onCreateOptionsMenu (): Parça ana bilgisayarının standart seçenekler menüsünün içeriğini başlatın.

Belirli bir Parça için bağımsız bir araç çubuğu ve menü istiyorsanız istiyorsanız, aşağıdakileri yapabilirsiniz:

menu_custom_fragment.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_save"
        android:title="SAVE" />
</menu>

custom_fragment.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    ...

CustomFragment.kt

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(layout.custom_fragment, container, false)
    val toolbar = view.findViewById<Toolbar>(R.id.toolbar)
    toolbar.inflateMenu(R.menu.menu_custom_fragment)
    toolbar.setOnMenuItemClickListener {
        onOptionsItemSelected(it)
    }
    return view
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.menu_save -> {
            // TODO: User clicked the save button
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

Evet, bu kadar kolay. Hatta geçersiz kılmak gerekmez onCreate()ya onCreateOptionsMenu().

Not: Bu sadece android.support.v4.app.Fragmentve ile çalışır android.support.v7.widget.Toolbar(ayrıca kullandığınızdan AppCompatActivityve bir AppCompattemanız olduğundan emin olun styles.xml).


1
gerçekten bana çok yardımcı oldu
brahmy adigopula

23

İçinde menu.xml tüm menü öğelerini eklemek gerekir. Ardından, ilk yüklemede görmek istemediğiniz öğeleri gizleyebilirsiniz.

menu.xml

<item
    android:id="@+id/action_newItem"
    android:icon="@drawable/action_newItem"
    android:showAsAction="never"
    android:visible="false"
    android:title="@string/action_newItem"/>

Ekle setHasOptionsMenu(true)sizin Fragment sınıfta menü öğelerini çağırmak için onCreate () yönteminde.

FragmentClass.java

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

onCreateOptionsMenuParça sınıfınızda tekrar geçersiz kılmanız gerekmez . Menü öğeleri Parçada onPrepareOptionsMenumevcut olan geçersiz kılma yöntemi ile değiştirilebilir (Ekle / kaldır) .

@Override
public void onPrepareOptionsMenu(Menu menu) {
    menu.findItem(R.id.action_newItem).setVisible(true);
    super.onPrepareOptionsMenu(menu);

}

16

Menüleri şişirmeden önce menu.clear () yöntemini kullanmanız gerekir.

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

ve

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

1
Farklı parçalarda farklı menüler istediğinizde ve bunları değiştirmek yerine parça eklediğinizde bu doğrudur.
Akshay Mahajan

Teşekkür ederim! menu.clear (), Etkinlik menü seçeneğini kaldırmama yardımcı olur.
kimcy929

13

Benim durumumda, adımlar burada.

Aşama 1

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Here notify the fragment that it should participate in options menu handling.
    setHasOptionsMenu(true);
}

Adım 2

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // First clear current all the menu items
    menu.clear();

    // Add the new menu items
    inflater.inflate(R.menu.post_stuff, menu);

    super.onCreateOptionsMenu(menu, inflater);
}

Aşama 3

 @Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.post_stuff:
            Log.d(TAG, "Will post the photo to server");
            return true;
        case R.id.cancel_post:
            Log.d(TAG, "Will cancel post the photo");
            return true;
        default:
            break;
    }
    return super.onOptionsItemSelected(item);
}

Zaten ana faaliyet menu.clear()menüsü temizlenmiş önceki menüyü kullanarak vardı . Benim için çalıştı :)
Anbuselvan Rocky

8

Menünüzü özel eklemek istiyorsanız

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

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

sekme görünümü varsa ve her parça için farklı menüleri şişirmek istiyorsanız ne olur?
Jainam Jhaveri

7

Aynı sorunu yaşadım, parçalarım bir ViewPager sayfasıydı. Bunun nedeni, FragmentPagerAdapter örneğini başlatırken aktivite destek parçası yöneticisi yerine alt parça yöneticisi kullanmamdı.


3

Menü dosyası:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/play"
        android:titleCondensed="Speak"
        android:showAsAction="always"
        android:title="Speak"
        android:icon="@drawable/ic_play">
    </item>
    <item
        android:id="@+id/pause"
        android:titleCondensed="Stop"
        android:title="Stop"
        android:showAsAction="always"
        android:icon="@drawable/ic_pause">
    </item>
</menu>

Faaliyet kodu:

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.play:
            Toast.makeText(getApplicationContext(), "speaking....", Toast.LENGTH_LONG).show();
            return false;

        case R.id.pause:
            Toast.makeText(getApplicationContext(), "stopping....", Toast.LENGTH_LONG).show();
            return false;

        default:
            break;
    }

    return false;
}

Parça kodu:

@Override

public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.play:
            text = page.getText().toString();
            speakOut(text);

            // Do Activity menu item stuff here
            return true;

        case R.id.pause:
            speakOf();

            // Not implemented here
            return true;

        default:
            break;
    }
    return false;
}

3

Kodunuz iyi. Yöntemde sadece süper eksikti:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // TODO add your menu : 
    inflater.inflate(R.menu.my_menu, menu);
    //TODO call super
    super.onCreateOptionsMenu(menu, inflater);
}

2

Çıldırıyordum çünkü buradaki cevapların hiçbiri benim için işe yaramadı.

Menüyü göstermek için: setSupportActionBar(toolbar)

Bitti!

Not: toolbarGörünümünüz aynı etkinlik düzeninde değilse yukarıdaki çağrıyı doğrudan etkinlik sınıfınızdan kullanamazsınız, bu durumda bu etkinliği parça sınıfınızdan almanız ve ardından setSupportActionBar(toolbar). Hatırlamak: Etkinlik sınıfınız AppCompatActivity'yi genişletmelidir.

Umarım bu cevap size yardımcı olur.


1

Parça görünümünü oluşturduktan sonra seçenekler menüsünü ayarlamak benim için iyi çalıştı.

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

1

Benim sorunum biraz farklıydı. Her şeyi doğru yaptım. Ama parçayı barındıran etkinlik için yanlış sınıfı miras alıyordum.

Bu nedenle onCreateOptionsMenu(Menu menu, MenuInflater inflater), parçada geçersiz kılıyorsanız , bu parçayı barındıran etkinlik sınıfınızın devralındığından emin olun android.support.v7.app.ActionBarActivity(API düzey 11'in altında desteklemek istiyorsanız).

android.support.v4.app.FragmentActivity11'in altındaki API düzeyini desteklemek için miras alıyordum .


1

Buna ekleyeceğim bir şey ve bunun benim için çalışmamasının nedeni.

Napster'ın cevabına benzer.

  1. Emin veridiliminin barındırma aktivite uzanır olun AppCompatActivity, değil FragmentActivity!

    public class MainActivity extends AppCompatActivity {
    
    }

    FragmentActivity için Google Referans Belgeleri'nden :

    Not: Eylem çubuğu içeren bir etkinlik uygulamak istiyorsanız, bunun yerine bunun bir alt sınıfı olan ActionBarActivity sınıfını kullanmanız gerekir; böylece, API düzeyi 7 ve daha üstü üzerinde Parça API'larını kullanmanızı sağlar.

  2. Napster'in yanıtını güncellemek - ActionBarActivityşimdi kullanımdan kaldırılıyor, AppCompatActivitybunun yerine kullanın.

  3. Kullanırken AppCompatActivity, "etkinlik temasını Theme.AppCompatveya benzer bir temayı" (Google Doküman) olarak ayarladığınızdan da emin olun .

Not: android.support.v7.app.AppCompatActivitysınıfın bir alt android.support.v4.app.FragmentActivitysınıfıdır (bkz. AppCompatActivity ref doc).


1

Menü klasörünüzde bir .menu xml dosyası oluşturun ve bu xml'yi ekleyin

<item
    android:id="@+id/action_search"
    android:icon="@android:drawable/ic_menu_search"
    android:title="@string/action_search"
    app:actionViewClass="android.support.v7.widget.SearchView"
    app:showAsAction="always|collapseActionView" />

Parça sınıfınızda bu yöntemi geçersiz kılın ve

implement SearchView.OnQueryTextListener    in your fragment class



@Override
 public void onViewCreated(View view, Bundle savedInstanceState) {    
  super.onViewCreated(view, savedInstanceState);
  setHasOptionsMenu(true);

}

Şimdi menü xml dosyanızı parça sınıfında kurmanız yeterlidir

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.menu_main, menu);

    final MenuItem item = menu.findItem(R.id.action_search);
    final SearchView searchView = (SearchView)    
    MenuItemCompat.getActionView(item);


    MenuItemCompat.setOnActionExpandListener(item,
            new MenuItemCompat.OnActionExpandListener() {
                @Override
                public boolean onMenuItemActionCollapse(MenuItem item) {
                    // Do something when collapsed

                    return true; // Return true to collapse action view
                }

                @Override
                public boolean onMenuItemActionExpand(MenuItem item) {
                    // Do something when expanded
                    return true; // Return true to expand action view
                }
            });

}

0

Yukarıdakilerin hepsi işe yaramazsa, hata ayıklamanız ve onCreateOptionsMenu işlevinin çağrıldığından emin olmanız gerekir (hata ayıklama veya günlük yazma ...)

Çalışmıyorsa, belki de Android temanız işlem çubuğunu desteklemiyor olabilir. AndroidManifest.xml dosyasını açın ve android:themetema desteği işlem çubuğuyla değerini ayarlayın :

 <activity
     android:name=".MainActivity"
     android:label="@string/app_name"
     android:theme="@style/Theme.AppCompat">

0

senin üzerinde onCreate yöntem eklenti setHasOptionMenu ()

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

Sonra geçersiz senin onCreateOptionsMenu

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    menu.add("Menu item")
            .setIcon(android.R.drawable.ic_delete)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.