Настройка пользовательского заголовка панели действий из фрагмента


внутри FragmentActivity, я настраиваю свой пользовательский ActionBar заголовок такой:

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

это работает идеально. Однако, как только я открою другие Fragments, Я хочу, чтобы название изменилось. Я не уверен, как получить доступ к главной Activity для этого? В прошлом, я сделал это:

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

может ли кто-нибудь посоветовать правильный метод?

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>
19 72

19 ответов:

В вашей деятельности:

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

и в вашем фрагменте:

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

    // Set title bar
    ((MainFragmentActivity) getActivity())
            .setActionBarTitle("Your title");

}

===Обновление 10 Апреля 2015 Года===

вы должны использовать listener для обновления заголовка панели действий

фрагмент:

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

}

И Действия:

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

}

Подробнее читайте здесь:https://developer.android.com/training/basics/fragments/communicating.html

то, что вы делаете, правильно. Fragments не имеют доступа к ActionBar API, так что вы должны позвонить getActivity. Если только ваш Fragment является статическим внутренним классом, в этом случае вы должны создать WeakReference к родительской и вызов активности.getActionBar оттуда.

чтобы установить название для вашего ActionBar, при использовании пользовательского макета, в вашем Fragment нужно позвонить getActivity().setTitle(YOUR_TITLE).

причина позвонить setTitle - это потому, что ты называешь getTitle как название ваш ActionBar. getTitle возвращает название для этого Activity.

если вы не хотите, чтобы получить вызов getTitle, то вам нужно будет создать открытый метод, который устанавливает текст вашего TextView на Activity что хозяева Fragment.

в работе:

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

в вашей Фрагмент:

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

документы:

Activity.getTitle

Activity.setTitle

кроме того, вам не нужно звонить this.whatever в коде, который вы предоставили, просто подсказка.

примеры Google, как правило, используют это в фрагментах.

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

фрагмент будет принадлежать ActionBarActivity, и именно там находится ссылка на actionbar. Это чище, потому что фрагмент не должен точно знать, что это за действие, он должен принадлежать только к действию, которое реализует ActionBarActivity. Это делает фрагмент более гибким и может быть добавлен к нескольким действиям, как они предназначены.

теперь все, что вам нужно сделать во фрагменте есть.

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

это хорошо работает, если у вас есть базовый фрагмент, который ваши фрагменты наследуют вместо обычного класса фрагмента.

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

тогда в вашем фрагменте.

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

задание Activity ' s title from a Fragment портит уровень ответственности. Fragment содержится в Activity, это Activity, который должен установить свой собственный заголовок в соответствии с типом Fragment например.

Предположим, у вас есть интерфейс:

interface TopLevelFragment
{
    String getTitle();
}

The Fragment s, которые могут влиять на Activity’s название затем реализовать этот интерфейс. В то время как в активности хостинга вы пишете:

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

таким образом Activity is всегда контролируйте, какое название использовать, даже если несколько TopLevelFragments комбинируются, что вполне возможно на планшете.

в фрагменте, который мы можем использовать, как это, он отлично работает для меня.

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

на всякий случай, если у вас возникли проблемы с кодом, попробуйте поставить getSupportActionBar().setTitle(title) внутри onResume() вашего фрагмента вместо onCreateView(...) Я.е

на MainActivity.java:

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

Фрагмент:

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

использовать следующий:

getActivity().setTitle("YOUR_TITLE");

Я не думаю, что принятый ответ является идеальным ответом для него. Так как все действия, которые используют

панели инструментов

продлены с помощью

AppCompatActivity

, фрагменты, вызванные из него, могут использовать приведенный ниже код для изменения заголовка.

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

если у вас есть основная деятельность со многими фрагментами, которые вы вставляете, обычно используя navigationDrawer. И у вас есть массив заголовков для ваших фрагментов, когда вы нажимаете назад, чтобы они изменились, поместите это в основное действие, которое удерживает фрагменты

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

}

это предполагает, что для каждого фрагмента вы даете ему тег, обычно где-то, когда вы добавляете фрагменты в список navigationDrawer, в соответствии с позицией, нажатой в списке. Так что эта позиция-то, что я захватываю тег:

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

теперь navmenutles-это то, что вы загружаете на onCreate

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

массив xml является строковым ресурсом типа массива в строках.xml

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

сохраните ответ ur в String [] object и установите его OnTabChange () в MainActivity как Belowwww

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

вот мое решение для установки заголовка ActionBar из фрагментов, при использовании NavigationDrawer. Это решение использует интерфейс, поэтому фрагменты не должны ссылаться на родительскую активность напрямую:

1) создать интерфейс:

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

2) в фрагменте onAttach, приведите действие к типу интерфейса и вызовите метод SetActivityTitle:

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

3) в деятельности, осуществите ActionBarTitleSetter интерфейс:

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

обратная сторона вашего подхода к кастингу, как так

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

заключается в том, что ваш фрагмент больше не используется повторно за пределами MainActivityFragment. Если вы не планируете использовать его вне этой деятельности, то нет никаких проблем. Лучшим подходом было бы условно установить название в зависимости от вида деятельности. Поэтому внутри вашего фрагмента вы напишете:

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

Если вы используете Android studio 1.4 стабильный шаблон, предоставленный google, чем просто вы должны были написать следующий код в onNavigationItemSelected methode в котором ваш связанный фрагмент вызывает условие if.

 setTitle("YOUR FRAGMENT TITLE");

Я получаю очень простое решение для установки заголовка ActionBar в любом из них фрагмент или любая деятельность без головной боли.

просто измените xml, где определена панель инструментов, как показано ниже:

<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) Если вы хотите установить панель действий в фрагменте, то :

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

для использования его из любого места, вы можете определить метод в activity

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

назвать это метод в деятельности, просто вызовите его.

setActionBarTitle("Your Title")

чтобы вызвать этот метод из фрагмента действия, просто вызовите его.

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

просто чтобы добавить к выбранному ответу, вы также можете добавить второй метод к своей основной деятельности. Таким образом, вы получите следующие методы в своей основной деятельности:

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

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

Это позволит вам установить заголовок как из строковой переменной, так и из идентификатора ресурса, такого как R.id.this_is_a_string от ваших строк.XML-файл. Это также будет работать немного больше, как getSupportActionBar().setTitle() работает, так как он позволяет передавать идентификатор ресурса.

есть много способов, как описано выше. Вы также можете сделать это в onNavigationDrawerSelected()в своем DrawerActivity

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

по крайней мере, для меня был простой ответ (после долгого копания) на изменение названия вкладки во время выполнения:

TabLayout tabLayout = (TabLayout) findViewById(R. id. tabs); tabLayout.getTabAt(MyTabPos).setText ("мой новый текст");

если вы используете ViewPager (как и в моем случае) вы можете использовать:

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

на onPageSelected метод VIEW_PAGER.addOnPageChangeListener

Лучшее событие для изменения названия 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);
}