从Fragment设置自定义ActionBar标题

The*_*ter 83 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);
Run Code Online (Sandbox Code Playgroud)

这很完美.但是,一旦我打开其他Fragments,我希望标题改变.我不知道如何访问Main Activity来做到这一点?在过去,我这样做了:

((MainFragmentActivity) getActivity()).getSupportActionBar().setTitle(
            catTitle);
Run Code Online (Sandbox Code Playgroud)

有人可以就正确的方法提出建议吗?

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>
Run Code Online (Sandbox Code Playgroud)

adn*_*eal 146

你正在做的是正确的.Fragments无权访问ActionBarAPI,因此您必须致电getActivity.除非你Fragment是一个静态的内部类,否则你应该创建一个WeakReference父类并调用Activity.getActionBar从那里.

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

你打电话的原因setTitle是因为你打电话给你getTitle的头衔ActionBar.getTitle返回该标题Activity.

如果你不想让通话getTitle,那么你就需要创建一个设置你的文字的公共方法TextViewActivity承载Fragment.

在您的活动中:

public void setActionBarTitle(String title){
    YOUR_CUSTOM_ACTION_BAR_TITLE.setText(title);
}
Run Code Online (Sandbox Code Playgroud)

在你的片段中:

((MainFragmentActivity) getActivity()).setActionBarTitle(YOUR_TITLE);
Run Code Online (Sandbox Code Playgroud)

文档:

Activity.getTitle

Activity.setTitle

此外,您不需要调用this.whatever您提供的代码,只需提示.


Fra*_*yen 81

在您的活动中:

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
    })
} }
Run Code Online (Sandbox Code Playgroud)

在你的片段中:

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")
} }
Run Code Online (Sandbox Code Playgroud)

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

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

分段:

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

}

和活动:

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);
}
Run Code Online (Sandbox Code Playgroud)

}

在此处阅读更多内容:https://developer.android.com/training/basics/fragments/communicating.html

  • 顺便说一句:此答案中使用的onAttach(Activity)方法此时已弃用.检查`onAttach(Context)`方法内部传递的主机活动是否实现了所需的接口(通过`context.getActivity()`检索主机活动). (3认同)
  • 多年后,我将其更改为已接受的答案,因为众所周知,接口是片段和活动需要进行通信的方式。 (2认同)

Kal*_*ade 25

谷歌的例子倾向于在片段中使用它.

private ActionBar getActionBar() {
    return ((ActionBarActivity) getActivity()).getSupportActionBar();
}
Run Code Online (Sandbox Code Playgroud)

该片段将属于ActionBarActivity,这是对操作栏的引用.这是更清晰的,因为片段不需要确切地知道它是什么活动,它只需要属于实现ActionBarActivity的活动.这使得片段更加灵活,可以像往常一样添加到多个活动中.

现在,你需要在片段中做的就是.

getActionBar().setTitle("Your Title");
Run Code Online (Sandbox Code Playgroud)

如果您有一个片段继承而不是正常片段类的基本片段,这种方法很有效.

public abstract class BaseFragment extends Fragment {
    public ActionBar getActionBar() {
        return ((ActionBarActivity) getActivity()).getSupportActionBar();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的片段中.

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


Ale*_* N. 7

ActivityFragment混乱的责任层面设置标题.Fragment包含在一个中Activity,所以这就是Activity,应该根据Fragment例如的类型设置自己的标题.

假设你有一个界面:

interface TopLevelFragment
{
    String getTitle();
}
Run Code Online (Sandbox Code Playgroud)

Fragment能够影响的S 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());
}
Run Code Online (Sandbox Code Playgroud)

以这种方式Activity始终控制使用什么标题,即使TopLevelFragment组合了多个标题,这在平板电脑上是非常可能的.


Man*_*ath 7

我不认为接受的答案是它的完美答案。由于所有使用的活动

工具栏

扩展使用

应用兼容活动

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

((AppCompatActivity) context).getSupportActionBar().setTitle("Your Title");
Run Code Online (Sandbox Code Playgroud)


las*_*203 7

一个简单的 Kotlin 示例

将此适应您的片段类:

    /**
     * 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() {

        override fun onResume() {
            super.onResume()
            (requireActivity() as MyMainActivity).supportActionBar?.title = "My Fragment!"
        }


    }
Run Code Online (Sandbox Code Playgroud)


Nag*_*ddy 5

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

getActivity().getActionBar().setTitle("YOUR TITLE");
Run Code Online (Sandbox Code Playgroud)