Solution 1:

What you're doing is correct. Fragments don't have access to the ActionBar APIs, so you have to call getActivity. Unless your Fragment is a static inner class, in which case you should create a WeakReference to the parent and call Activity.getActionBar from there.

To set the title for your ActionBar, while using a custom layout, in your Fragment you'll need to call getActivity().setTitle(YOUR_TITLE).

The reason you call setTitle is because you're calling getTitle as the title of your ActionBar. getTitle returns the title for that Activity.

If you don't want to get call getTitle, then you'll need to create a public method that sets the text of your TextView in the Activity that hosts the Fragment.

In your Activity:

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

In your Fragment:

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

Docs:

Activity.getTitle

Activity.setTitle

Also, you don't need to call this.whatever in the code you provided, just a tip.

Solution 2:

===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

Solution 3:

Google examples tend to use this within the fragments.

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

The fragment will belong to an ActionBarActivity and that is where the reference to the actionbar is. This is cleaner because the fragment doesn't need to know exactly what activity it is, it only needs to belong to an activity that implements ActionBarActivity. This makes the fragment more flexible and can be added to multiple activities like they are meant to.

Now, all you need to do in the fragment is.

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

This works well if you have a base fragment that your fragments inherit from instead of the normal fragment class.

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

Then in your fragment.

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

Solution 4:

Setting Activity’s title from a Fragment messes up responsibility levels. Fragment is contained within an Activity, so this is the Activity, which should set its own title according to the type of the Fragment for example.

Suppose you have an interface:

interface TopLevelFragment
{
    String getTitle();
}

The Fragments which can influence the Activity’s title then implement this interface. While in the hosting activity you write:

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

In this manner Activity is always in control what title to use, even if several TopLevelFragments are combined, which is quite possible on a tablet.

Solution 5:

I don't think that the accepted answer is a perfect answer for it. Since all the activities that use

Toolbar

are extended using

AppCompatActivity

, the fragments called from it can use the below mentioned code for changing the title.

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