Search code examples
javaandroidandroid-fragmentsandroid-actionbarandroid-fragmentactivity

Setting Custom ActionBar Title from Fragment


In my Main FragmentActivity, I setup my custom ActionBar title like this:

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

This works perfect. However, once I open other Fragments, I want the title to change. I am not sure how to access the Main Activity to do this? In the past, I did this:

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

Can someone advise on the proper method?

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>

Solution

  • ===Update October, 30, 2019===

    Since we have new components such as ViewModel and LiveData, we can have a different/easier way to update Activity Title from Fragment by using ViewModel and Live Data

    Activity

    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")
    } }
    

    And MainModelView:

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

    And then you can update the Activity title from Fragment using viewModel.updateActionBarTitle("Custom Title From Fragment")

    ===Update April, 10, 2015===

    You should use listener to update your action bar title

    Fragment:

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

    And Activity:

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

    Read more here: https://developer.android.com/training/basics/fragments/communicating.html