it-swarm.com.ru

Установка пользовательского заголовка ActionBar из фрагмента

В моем главном 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, я хочу изменить заголовок. Я не уверен, как получить доступ к Main 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>
74
KickingLettuce

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

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

Вы должны использовать слушатель, чтобы обновить заголовок панели действий

Фрагмент:

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

64
Frank Nguyen

То, что вы делаете, правильно. Fragments не имеет доступа к API ActionBar, поэтому вы должны вызвать getActivity. Если ваш Fragment не является статическим внутренним классом, в этом случае вы должны создать WeakReference для родителя и вызвать там Activity .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 в коде, который вы предоставили, просто совет.

146
adneal

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

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

Фрагмент будет принадлежать ActionBarActivity, и именно там находится ссылка на панель действий. Это чище, потому что фрагменту не нужно точно знать, что это за действие, ему нужно только принадлежать действию, которое реализует 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");
    }
}
25
Kalel Wade

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

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

interface TopLevelFragment
{
    String getTitle();
}

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

@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 всегда контролирует, какой заголовок использовать, даже если несколько TopLevelFragment объединены, что вполне возможно на планшете.

7
Aleks N.

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

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

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

В MainActivity.Java :

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

Во фрагменте:

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

Используйте следующее:

getActivity().setTitle("YOUR_TITLE");
2
Anisetti Nagendra

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

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

расширяются с помощью 

AppCompatActivity

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

((AppCompatActivity) context).getSupportActionBar().setTitle("Your Title");
2
Manoj Perumarath

Сохраните ваш ответ в объекте String [] и установите его OnTabChange () в MainActivity, как показано ниже.

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
Narendra Kumar

Если у вас есть основной вид деятельности с множеством вставленных фрагментов, обычно с помощью 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();

Теперь navMenuTitles - это то, что вы загружаете в onCreate.

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

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

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

Вот мое решение для установки заголовка 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; 
}
1
Assaf S.

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

 setTitle("YOUR FRAGMENT TITLE");
1
Manan Patel

Я получаю очень простое решение для установки заголовка 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);

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

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

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

setActionBarTitle("Your Title")

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

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

Недостаток вашего подхода к кастингу вот так

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

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

if (getActivity() instanceof ActionBarActivity) {
    ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle("Some Title");
}
1
Mieczysław Daniel Dyba

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

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

0
Mark

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

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

в onPageSelected методе вашего VIEW_PAGER.addOnPageChangeListener

0
Reza

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

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

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

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

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

0
CodyEngel

Есть много способов, как указано выше. Вы также можете сделать это в 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);
    }
}
0
tricknology