Menetapkan Judul ActionBar Kustom dari Fragmen


90

Di Utama saya FragmentActivity, saya menyiapkan ActionBarjudul khusus saya seperti ini:

    LayoutInflater inflator = (LayoutInflater) this
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v = inflator.inflate(R.layout.custom_titlebar, null);

    TextView tv = (TextView) v.findViewById(R.id.title);
    Typeface tf = Typeface.createFromAsset(this.getAssets(),
            "fonts/capsuula.ttf");
    tv.setTypeface(tf);
    tv.setText(this.getTitle());

    actionBar.setCustomView(v);

Ini bekerja dengan sempurna. Namun, begitu saya membuka yang lain Fragments, saya ingin judulnya berubah. Saya tidak yakin bagaimana mengakses Main Activityuntuk melakukan ini? Di masa lalu, saya melakukan ini:

((MainFragmentActivity) getActivity()).getSupportActionBar().setTitle(
            catTitle);

Adakah yang bisa memberi nasihat tentang metode yang tepat?

XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent" >

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="5dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:text=""
        android:textColor="#fff"
        android:textSize="25sp" />

</RelativeLayout>

stackoverflow.com/a/28279341/1651286 harus menjadi jawaban yang diterima karena skalabilitasnya. karena semua pendekatan lain membuat fragmen terkait dengan aktivitas tertentu, yang bukan merupakan desain yang skalabel, bagaimana jika fragmen yang sama harus digunakan dengan banyak aktivitas, hal ini juga yang direkomendasikan oleh framework android.
Akhil Dad

Jawaban:


98

=== Update 30 Oktober 2019 ===

Karena kita memiliki komponen baru seperti ViewModel dan LiveData , kita dapat memiliki cara lain / lebih mudah untuk memperbarui Judul Aktivitas dari Fragment dengan menggunakan ViewModel dan Live Data

Aktivitas

class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_activity)
    if (savedInstanceState == null) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.container, MainFragment.newInstance())
            .commitNow()
    }
    viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
    viewModel.title.observe(this, Observer {
        supportActionBar?.title = it
    })
} }

MainFragment

class MainFragment : Fragment() {
companion object {
    fun newInstance() = MainFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View {
    return inflater.inflate(R.layout.main_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    activity?.run {
        viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
    } ?: throw Throwable("invalid activity")
    viewModel.updateActionBarTitle("Custom Title From Fragment")
} }

Dan MainModelView:

class MainViewModel : ViewModel() {
private val _title = MutableLiveData<String>()
val title: LiveData<String>
get() = _title
fun updateActionBarTitle(title: String) = _title.postValue(title) }

Dan kemudian Anda dapat memperbarui judul Aktivitas dari Fragmen menggunakan viewModel.updateActionBarTitle("Custom Title From Fragment")

=== Update 10 April 2015 ===

Anda harus menggunakan pendengar untuk memperbarui judul bilah tindakan Anda

Pecahan:

public class UpdateActionBarTitleFragment extends Fragment {
    private OnFragmentInteractionListener mListener;

    public UpdateActionBarTitleFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (mListener != null) {
            mListener.onFragmentInteraction("Custom Title");
        }
        return inflater.inflate(R.layout.fragment_update_action_bar_title2, container, false);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {
        public void onFragmentInteraction(String title);
    }
}

Dan Aktivitas:

public class UpdateActionBarTitleActivity extends ActionBarActivity implements UpdateActionBarTitleFragment.OnFragmentInteractionListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_update_action_bar_title);
    }

    @Override
    public void onFragmentInteraction(String title) {
        getSupportActionBar().setTitle(title);
    }
}

Baca selengkapnya di sini: https://developer.android.com/training/basics/fragments/communicating.html


1
Itu berhasil untuk saya! Saya baru saja menggunakan getActionBar (). SetTitle (judul) sebagai gantinya dalam aktivitas. Terima kasih
luckyreed76

1
Persis apa yang saya cari- bekerja lebih baik untuk saya daripada jawaban yang dipilih. Terima kasih!
dstrube

1
Ini harus menjadi jawaban yang diterima! Ini benar menunjukkan bagaimana hal itu harus dilakukan: Jika sebuah fragmen ingin berkomunikasi dengan aktivitas hostingnya, komunikasi harus selalu terjadi melalui antarmuka. Fragmen menyediakan antarmuka dan aktivitas mengimplementasikannya! Jika beberapa fragmen harus berkomunikasi dengan cara yang sama dengan suatu aktivitas, tulis fragmen abstrak yang menyediakan antarmuka, lalu biarkan setiap fragmen mewarisi dari "fragmen dasar" ini.
winklerrr

3
Ngomong-ngomong: Metode onAttach (Aktivitas) yang digunakan dalam jawaban ini sudah tidak digunakan lagi saat ini. Periksa di dalam onAttach(Context)metode apakah aktivitas host yang diteruskan mengimplementasikan antarmuka yang diperlukan (mengambil aktivitas host melalui context.getActivity()).
winklerrr

2
Setelah bertahun-tahun saya mengubahnya menjadi jawaban yang diterima karena seperti yang kita ketahui, antarmuka adalah cara fragmen dan aktivitas perlu berkomunikasi.
TheLettuceMaster

150

Apa yang Anda lakukan benar. Fragmentstidak memiliki akses ke ActionBarAPI, jadi Anda harus menelepon getActivity. Kecuali Anda Fragmentadalah kelas dalam statis, dalam hal ini Anda harus membuat WeakReferenceke induk dan memanggil Activity. getActionBardari sana.

Untuk menyetel judul untuk Anda ActionBar, saat menggunakan tata letak khusus, FragmentAnda harus menelepon getActivity().setTitle(YOUR_TITLE).

Alasan Anda menelepon setTitleadalah karena Anda menelepon getTitlesebagai judul Anda ActionBar. getTitlemengembalikan judul untuk itu Activity.

Jika Anda tidak ingin menerima panggilan getTitle, maka Anda harus membuat metode publik yang menyetel teks Anda TextViewdi Activityyang menghosting Fragment.

Dalam Aktivitas Anda :

public void setActionBarTitle(String title){
    YOUR_CUSTOM_ACTION_BAR_TITLE.setText(title);
}

Di Fragmen Anda :

((MainFragmentActivity) getActivity()).setActionBarTitle(YOUR_TITLE);

Dokumen:

Activity.getTitle

Activity.setTitle

Selain itu, Anda tidak perlu memanggil this.whateverkode yang Anda berikan, cukup tip.


Saya mencoba dan saya tidak bisa membuatnya bekerja. Untuk apa nilainya, saya memposting saya XMLdan juga menghapus "ini". Tidak ada perubahan ... Dan tidak, ini bukan statickelas batin.
TheLettuceMaster

Tunggu, apa yang tidak berhasil? Dalam OP Anda, Anda tidak menyebutkan apa pun yang tidak berfungsi, Anda hanya menyebutkan ingin tahu metode yang "tepat" untuk menyetel judul di ActionBardari a Fragment. Juga, saya tidak menawarkan penghapusan this.whateversebagai solusi untuk apa pun, itu hanya tip pemformatan kode.
adneal

Saya rasa saya mengerti apa yang Anda alami dan mengedit jawaban saya yang sesuai.
adneal

Thankx jawaban sempurna
Ammar ali

@KickingLettuce, saya kesulitan dengan jawaban ini untuk sementara waktu sampai saya membuatnya berhasil (itulah mengapa saya menaikkan suara, serta pertanyaan Anda): dalam aktivitas utama menu_actpanel navigasi saya ( ) saya membuat "mTitle" global, dan, dalam fragmen, pertama saya menetapkan judul untuk "mTitle" ( ( (menu_act) getActivity() ).mTitle = "new_title"), dan segera saya lakukan ( (menu_act) getActivity() ).restoreActionBar();. Di dalam "restoreActionBar ()" Saya memiliki "actionBar.setTitle (mTitle);".
Jose Manuel Abarca Rodríguez

29

Contoh Google cenderung menggunakan ini di dalam fragmen.

private ActionBar getActionBar() {
    return ((ActionBarActivity) getActivity()).getSupportActionBar();
}

Fragmen akan menjadi milik ActionBarActivity dan di sanalah referensi ke bilah tindakan berada. Ini lebih rapi karena fragmen tidak perlu tahu persis apa aktivitasnya, ia hanya perlu dimiliki oleh aktivitas yang mengimplementasikan ActionBarActivity. Ini membuat fragmen lebih fleksibel dan dapat ditambahkan ke beberapa aktivitas seperti yang dimaksudkan.

Sekarang, yang perlu Anda lakukan di fragmen adalah.

getActionBar().setTitle("Your Title");

Ini berfungsi dengan baik jika Anda memiliki fragmen dasar yang mewarisi fragmen Anda, bukan kelas fragmen normal.

public abstract class BaseFragment extends Fragment {
    public ActionBar getActionBar() {
        return ((ActionBarActivity) getActivity()).getSupportActionBar();
    }
}

Kemudian di fragmen Anda.

public class YourFragment extends BaseFragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getActionBar().setTitle("Your Title");
    }
}

Terima kasih. solusi yang sangat bagus, dengan cara ini Anda juga dapat meneruskan tampilan kustom ke bilah tindakan Anda.
Amir

Dengan update terbaru pada Android SDK, sebagai ganti ActionBarActivity, Anda mungkin ingin downcast ke AppCompatActivity jika Anda menggunakan pustaka kompatibilitas mundur v7 (yang mungkin harus Anda lakukan).
fr4gus

8

Pengaturan Activityjudul dari Fragmenttingkat tanggung jawab yang kacau. Fragmentterkandung di dalam Activity, jadi ini adalah Activity, yang harus menetapkan judulnya sendiri sesuai dengan jenis Fragmentmisalnya.

Misalkan Anda memiliki antarmuka:

interface TopLevelFragment
{
    String getTitle();
}

Yang Fragmentdapat mempengaruhi Activityjudul kemudian mengimplementasikan antarmuka ini. Saat dalam aktivitas hosting Anda menulis:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FragmentManager fm = getFragmentManager();
    fm.beginTransaction().add(0, new LoginFragment(), "login").commit();
}

@Override
public void onAttachFragment(Fragment fragment)
{
    super.onAttachFragment(fragment);

    if (fragment instanceof TopLevelFragment)
        setTitle(((TopLevelFragment) fragment).getTitle());
}

Dengan cara Activityini selalu mengontrol judul apa yang akan digunakan, bahkan jika beberapa TopLevelFragmentdigabungkan, yang sangat mungkin dilakukan di tablet.


6

Saya tidak berpikir bahwa jawaban yang diterima adalah jawaban yang sempurna untuk itu. Karena semua kegiatan itu memanfaatkan

Toolbar

diperpanjang menggunakan

AppCompatActivity

, fragmen yang dipanggil darinya dapat menggunakan kode yang disebutkan di bawah ini untuk mengubah judul.

((AppCompatActivity) context).getSupportActionBar().setTitle("Your Title");

5

Di Fragmen yang bisa kita gunakan seperti ini, Ini berfungsi dengan baik untuk saya.

getActivity().getActionBar().setTitle("YOUR TITLE");

Ini tidak berfungsi saat Toolbar aktivitas kita memiliki TextView yang memiliki peran judul
Simon

4

Untuk berjaga-jaga jika Anda mengalami masalah dengan kode, coba masukkan ke getSupportActionBar().setTitle(title)dalam onResume()fragmen Anda alih-alih onCreateView(...)ie

Di MainActivity.java :

public void setActionBarTitle(String title) {
    getSupportActionBar().setTitle(title);
}

Dalam Fragmen:

 @Override
 public void onResume(){
     super.onResume();
     ((MainActivity) getActivity()).setActionBarTitle("Your Title");
 }

Ini adalah masalah saya - di mana saya menetapkan judul. Namun, sudah ((MainActivity) getActivity()).setTitle("title")cukup. Di Kotlin, fragmen saya melakukannya activity!!.title = "title.
Joe Lapp


2

Berikut adalah solusi saya untuk menyetel judul ActionBar dari fragmen, saat menggunakan NavigationDrawer. Solusi ini menggunakan Antarmuka sehingga fragmen tidak perlu merujuk Aktivitas induk secara langsung:

1) Buat Antarmuka:

public interface ActionBarTitleSetter {
    public void setTitle(String title); 
}

2) Dalam Fragment's onAttach , transmisikan aktivitas ke tipe Interface dan panggil metode SetActivityTitle:

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity);
    ((ActionBarTitleSetter) activity).setTitle(getString(R.string.title_bubbles_map)); 
}

3) Dalam aktivitas, terapkan antarmuka ActionBarTitleSetter :

@Override 
public void setTitle(String title) { 
    mTitle = title; 
}

Ini harus menjadi jawaban yang diterima karena semua pendekatan lain membuat fragmen terkait dengan aktivitas tertentu, yang bukan merupakan desain yang dapat diskalakan, juga inilah yang juga direkomendasikan oleh framework android
Akhil Dad

2

Acara terbaik untuk mengubah judul onCreateOptionsMenu

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.general, container,  
    setHasOptionsMenu(true); // <-Add this line
    return view;
}

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

    // If use specific menu
    menu.clear();
    inflater.inflate(R.menu.path_list_menu, menu);
    // If use specific menu

    ((AppCompatActivity) getActivity()).getSupportActionBar().setTitle("Your Fragment");
    super.onCreateOptionsMenu(menu, inflater);
}

2

Contoh Kotlin sederhana

Dengan asumsi deps gradle ini cocok atau versi yang lebih tinggi dalam proyek Anda:

kotlin_version = '1.3.41'
nav_version_ktx = '2.0.0'

Sesuaikan ini dengan kelas fragmen Anda:

    /**
     * A simple [Fragment] subclass.
     *
     * Updates the action bar title when onResume() is called on the fragment,
     * which is called every time you navigate to the fragment
     *
     */

    class MyFragment : Fragment() {
    private lateinit var mainActivity: MainActivity

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

       //[...]

        mainActivity = this.activity as MainActivity

       //[...]
    }

    override fun onResume() {
        super.onResume()
        mainActivity.supportActionBar?.title = "My Fragment!"
    }


    }

1

Jika Anda memiliki aktivitas utama dengan banyak fragmen yang Anda masukkan, biasanya menggunakan navigationDrawer. Dan Anda memiliki serangkaian judul untuk fragmen Anda, ketika Anda menekan kembali, agar mereka berubah, letakkan ini di tindakan utama yang menahan fragmen

@Override
     public void onBackPressed() {

    int T=getSupportFragmentManager().getBackStackEntryCount();
    if(T==1) { finish();}

    if(T>1) {
        int tr = Integer.parseInt(getSupportFragmentManager().getBackStackEntryAt(T-2).getName());
        setTitle(navMenuTitles[tr]);  super.onBackPressed();
      }

}

Ini mengasumsikan bahwa untuk setiap fragmen Anda memberinya tag, biasanya di suatu tempat saat Anda menambahkan fragmen ke daftar navigationDrawer, sesuai dengan posisi yang ditekan pada daftar. Jadi posisi itu yang saya tangkap di tag:

    fragmentManager.beginTransaction().
replace(R.id.frame_container, fragment).addToBackStack(position).commit();

Sekarang, navMenuTitles adalah sesuatu yang Anda muat di onCreate

 // load slide menu items
        navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);

Larik xml adalah sumber daya string tipe larik di strings.xml

 <!-- Nav Drawer Menu Items -->
    <string-array name="nav_drawer_items">
        <item>Title one</item>
        <item>Title Two</item>
    </string-array>

1

Simpan Jawaban Anda dalam objek String [] dan setel OnTabChange () di MainActivity seperti Di Bawahwww

String[] object = {"Fragment1","Fragment2","Fragment3"};

public void OnTabChange(String tabId)
{
int pos =mTabHost.getCurrentTab();     //To get tab position
 actionbar.setTitle(object.get(pos));
}


//Setting in View Pager
public void onPageSelected(int arg0) {
    mTabHost.setCurrentTab(arg0);
actionbar.setTitle(object.get(pos));
}

1

Sisi negatif dari pendekatan casting Anda seperti itu

((MainFragmentActivity) getActivity()).getSupportActionBar().setTitle(
        catTitle);

adalah fragmen Anda tidak lagi dapat digunakan kembali di luar MainActivityFragment. Jika Anda tidak berencana menggunakannya di luar aktivitas itu, maka tidak ada masalah. Pendekatan yang lebih baik adalah menetapkan judul secara kondisional tergantung pada aktivitas. Jadi di dalam fragmen Anda, Anda akan menulis:

if (getActivity() instanceof ActionBarActivity) {
    ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle("Some Title");
}

1

Jika Anda menggunakan template stabil android studio 1.4 yang disediakan oleh Google daripada yang sederhana Anda harus menulis kode berikut dalam onNavigationItemSelectedmetode di mana fragmen terkait Anda memanggil jika kondisi.

 setTitle("YOUR FRAGMENT TITLE");

itu bagus jika Anda memiliki akses ke judul langsung dari aktivitas ... tetapi jika judul adalah string yang disetel secara dinamis dalam fragmen, perlu ada komunikasi antara fragmen dan aktivitas
me_

1

Saya mendapatkan solusi yang sangat sederhana untuk mengatur Judul ActionBar baik dalam fragmen atau aktivitas apa pun tanpa sakit kepala.

Ubah saja xml di mana Toolbar didefinisikan seperti di bawah ini:

<android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimaryDark"
            app:popupTheme="@style/AppTheme.PopupOverlay" >

            <TextView
                style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
                android:id="@+id/toolbar_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/app_name"
                />
            </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout> 

1) Jika Anda ingin mengatur bilah tindakan dalam sebuah fragmen, maka:

Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);

Untuk menggunakannya dari mana saja, Anda bisa menentukan metode dalam aktivitas

public void setActionBarTitle(String title) {
        toolbarTitle.setText(title);
    }

Untuk memanggil metode ini dalam aktivitas, panggil saja.

setActionBarTitle("Your Title")

Untuk memanggil metode ini dari fragmen aktivitas, panggil saja.

((MyActivity)getActivity()).setActionBarTitle("Your Title");

Luar biasa! Menggunakan toolbar_title mengganti judul fragmen jika menggunakan Android Navigation Components.
Paixols

0

Hanya untuk menambahkan jawaban yang dipilih, Anda mungkin juga ingin menambahkan metode kedua ke aktivitas utama Anda. Jadi, Anda akan mendapatkan metode berikut dalam aktivitas utama Anda:

public void setActionBarTitle(String title) {
    getSupportActionBar().setTitle(title);
}

public void setActionBarTitle(int resourceId) {
    setActionBarTitle(getResources().getString(resourceId);
}

Ini akan memungkinkan Anda menyetel judul dari variabel String serta ID sumber daya seperti R.id.this_is_a_stringdari file strings.xml Anda. Ini juga akan bekerja lebih seperti cara getSupportActionBar().setTitle()kerjanya karena memungkinkan Anda meneruskan ID sumber daya.


0

Ada banyak cara seperti yang diuraikan di atas. Anda juga dapat melakukan ini di onNavigationDrawerSelected()dalam AndaDrawerActivity

public void setTitle(final String title){
    ((TextView)findViewById(R.id.toolbar_title)).setText(title);
}

@Override
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by replacing fragments
    fragment = null;
    String title = null;
    switch(position){

    case 0:
        fragment = new HomeFragment();
        title = "Home";
        break;
    case 1:
        fragment = new ProfileFragment();
        title = ("Find Work");
        break;
    ...
    }
    if (fragment != null){

        FragmentManager fragmentManager = getFragmentManager();
        fragmentManager
        .beginTransaction()
        .replace(R.id.container,
                fragment).commit();

        //The key is this line
        if (title != null && findViewById(R.id.toolbar_title)!= null ) setTitle(title);
    }
}

0

Setidaknya bagi saya, ada jawaban yang mudah (setelah banyak menggali) untuk mengubah judul tab saat runtime:

TabLayout tabLayout = (TabLayout) findViewById (R.id.tabs); tabLayout.getTabAt (MyTabPos) .setText ("Teks Baru Saya");


0

Jika Anda menggunakan ViewPager(seperti kasus saya), Anda dapat menggunakan:

getSupportActionBar().setTitle(YOURE_TAB_BAR.getTabAt(position).getText());

dalam onPageSelectedmetode AndaVIEW_PAGER.addOnPageChangeListener


0

Dalam MainActivity Anda, di bawah onCreate:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

Dan dalam aktivitas fragmen Anda di bawah onResume:

getActivity().setTitle(R.string.app_name_science);

Opsional: - jika mereka menunjukkan peringatan referensi null

Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);


Objects.requireNonNull(getActivity()).setTitle(R.string.app_name_science);
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.