从Fragment设置自定义ActionBar标题

时间:2013-03-22 00:54:42

标签: android android-fragments android-actionbar android-fragmentactivity

在我的主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>

22 个答案:

答案 0 :(得分:146)

你所做的是正确的。 Fragments无法访问ActionBar API,因此您必须致电getActivity。除非您的Fragment是静态内部类,否则您应该为父级创建WeakReference并从那里调用Activity。getActionBar

要设置ActionBar的标题,在使用自定义布局时,在Fragment中,您需要致电getActivity().setTitle(YOUR_TITLE)

您拨打setTitle的原因是因为您将getTitle称为ActionBar的标题。 getTitle会返回Activity的标题。

如果您不想接听电话getTitle,则需要创建一个公共方法,设置TextView中承载Activity的{​​{1}}的文字{1}}。

在您的活动中

Fragment

在您的片段中

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

<强>文档:

Activity.getTitle

Activity.setTitle

此外,您无需在提供的代码中致电((MainFragmentActivity) getActivity()).setActionBarTitle(YOUR_TITLE); ,只需提示。

答案 1 :(得分:71)

在您的活动中:

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

}

=== 2015年4月10日更新===

您应该使用监听器来更新操作栏标题

片段:

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

答案 2 :(得分:25)

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

答案 3 :(得分:7)

Fragment设置Fragment的标题会增加责任级别。 Activity包含Activity,因此这是Fragment,例如,应根据interface TopLevelFragment { String getTitle(); } 的类型设置自己的标题。

假设您有一个界面:

Fragment

可以影响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始终控制着要使用的标题,即使合并了多个sonar.jacoco.reportMissing.force.zero=true,这在平板电脑上也是如此。

答案 4 :(得分:5)

在Fragment中我们可以像这样使用,它对我来说很好。

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

答案 5 :(得分:4)

如果您遇到代码问题,请尝试将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");
 }

答案 6 :(得分:2)

使用以下内容:

getActivity().setTitle("YOUR_TITLE");

答案 7 :(得分:2)

我不认为接受的答案是一个完美的答案。由于所有使用

的活动
  

工具栏

使用

进行扩展
  

AppCompatActivity

,从中调用的片段可以使用下面提到的代码来更改标题。

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

答案 8 :(得分:1)

在String []对象中保存你的答案,并在MainActivity中将其设置为OnTabChange(),如下面的

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

答案 9 :(得分:1)

这是我使用NavigationDrawer时从片段设置ActionBar标题的解决方案。 此解决方案使用接口,因此片段不需要直接引用父活动:

1)创建一个接口:

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

2)在Fragment的 onAttach 中,将活动强制转换为Interface类型并调用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; 
}

答案 10 :(得分:1)

你的投射方式的缺点如此

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

是您的片段不再可以在MainActivityFragment之外重复使用。如果您不打算在该活动之外使用它,那么没有问题。更好的方法是根据活动有条件地设置标题。所以在你的片段中,你会写:

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

答案 11 :(得分:1)

如果您有一个包含许多片段的主要活动,通常使用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();

现在,你在onCreate上加载了navMenuTitles

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

array xml是strings.xml上的数组类型字符串资源

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

答案 12 :(得分:1)

如果你使用google提供的android studio 1.4稳定模板而不是简单你必须在%方法中编写以下代码 其中你的相关片段调用if条件。

onNavigationItemSelected

答案 13 :(得分:1)

  

我得到了一个非常简单的解决方案,可以在任一位置设置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");

答案 14 :(得分:0)

基于 Ashish 答案的 Java 解决方案

private void setUI(){
    mainToolbar = findViewById(R.id.mainToolbar);
    setSupportActionBar(mainToolbar);
    DrawerLayout drawer = findViewById(R.id.drawer_layout);
    NavigationView navigationView = findViewById(R.id.nav_view);
    mAppBarConfiguration = new AppBarConfiguration.Builder(
            R.id.nav_home, R.id.nav_messaging, R.id.nav_me)
            .setDrawerLayout(drawer)
            .build();

    navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    navController.addOnDestinationChangedListener(navDestinationChange);
    NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
    NavigationUI.setupWithNavController(navigationView, navController);
}

private NavController.OnDestinationChangedListener navDestinationChange = new NavController.OnDestinationChangedListener(){
    @Override
    public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
        if(R.id.nav_home==destination.getId()){
            destination.setLabel("News");
        }
    }
};

答案 15 :(得分:0)

一个简单的Kotlin示例

假设这些gradle部门在您的项目中匹配或更高版本:

kotlin_version = '1.3.41'
nav_version_ktx = '2.0.0'

使其适应您的片段类:

    /**
     * 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!"
    }


    }

答案 16 :(得分:0)

在您的MainActivity中,onCreate:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

onResume下的片段活动中:

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

可选:-如果它们显示空引用警告

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


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

答案 17 :(得分:0)

更改标题的最佳活动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);
}

答案 18 :(得分:0)

如果你正在使用ViewPager(就像我的情况一样),你可以使用:

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

onPageSelected

VIEW_PAGER.addOnPageChangeListener方法

答案 19 :(得分:0)

至少对我来说,在运行时更改标签标题有一个简单的答案(经过多次挖掘):

TabLayout tabLayout =(TabLayout)findViewById(R.id.tabs); tabLayout.getTabAt(MyTabPos).setText(“我的新文本”);

答案 20 :(得分:0)

如上所述,有许多方法。您也可以在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);
    }
}

答案 21 :(得分:0)

只是要添加到所选答案,您可能还想在主要活动中添加第二种方法。因此,您最终会在主要活动中使用以下方法:

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

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

这将允许您从strings变量以及来自strings.xml文件的资源ID(例如R.id.this_is_a_string)设置标题。这也可以更像getSupportActionBar().setTitle()的工作方式,因为它允许您传入资源ID。