フラグメントからのカスタムActionBarタイトルの設定


90

メインでは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>

stackoverflow.com/a/28279341/1651286は、そのスケーラビリティのために受け入れられる答えであるはずです。他のすべてのアプローチでは、スケーラブルな設計ではない特定のアクティビティにフラグメントを関連付けるため、同じフラグメントを複数のアクティビティで使用する必要がある場合は、これもAndroidフレームワークで推奨されます。
Akhil Dad 2016

回答:


98

=== 2019年10月30日更新===

ViewModelLiveDataなどの新しいコンポーネントがあるため、ViewModelとLive Dataを使用して、フラグメントからアクティビティタイトルを更新する別の/簡単な方法を使用できます。

アクティビティ

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

そしてMainModelView:

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

次に、を使用してフラグメントからアクティビティタイトルを更新できます。 viewModel.updateActionBarTitle("Custom Title From Fragment")

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


1
それは私のために働いた!代わりに、アクティビティでgetActionBar()。setTitle(title)を使用しました。ありがとう
Luckyreed76 2013

1
まさに私が探していたものは、選択した答えよりもうまく機能しました。ありがとう!
dstrube 2016年

1
これは受け入れられた答えでなければなりません!それはそれがどのように行われるべきかを正しく示しています:フラグメントがそのホスティング活動と通信したい場合、通信は常にインターフェースを介して行われるべきです。フラグメントはインターフェースを提供し、アクティビティはそれを実装します!複数のフラグメントがアクティビティと同じ方法で通信する必要がある場合は、インターフェイスを提供する抽象フラグメントを記述してから、すべてのフラグメントがこの「ベースフラグメント」から継承するようにします。
winklerrr 2017

3
ちなみに、この回答で使用されているonAttach(Activity)メソッドは、この時点で非推奨になっています。onAttach(Context)渡されたホストアクティビティが必要なインターフェイスを実装しているかどうかをメソッド内で確認します(を介してホストアクティビティを取得しますcontext.getActivity())。
winklerrr 2017

2
何年も経った後、私はこれを受け入れられた答えに変更しました。なぜなら、私たちが知っているように、インターフェースはフラグメントとアクティビティが通信する必要がある方法だからです。
TheLettuceMaster 2018年

150

あなたがしていることは正しいです。APIにFragmentsアクセスできないActionBarため、を呼び出す必要がありますgetActivityFragmentが静的内部クラスでない限り、その場合WeakReferenceは親に対してを作成し、Activityを呼び出す必要があります。getActionBarそこから。

ActionBarカスタムレイアウトを使用しているときに、のタイトルを設定するには、Fragmentを呼び出す必要がありますgetActivity().setTitle(YOUR_TITLE)

あなたが呼ぶ理由はあなたがあなたのタイトルとして呼んでsetTitleいるからです。そのタイトルを返します。getTitleActionBargetTitleActivity

呼び出しを取得したくない場合は、をホストgetTitleするTextViewにのテキストを設定するパブリックメソッドを作成する必要があります。ActivityFragment

あなたの活動では

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

あなたのフラグメントで

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

ドキュメント:

Activity.getTitle

Activity.setTitle

また、this.whatever提供したコードを呼び出す必要はありません。ヒントだけです。


試してみましたが、うまくいきません。その価値のために、私は自分を投稿し、XML「これ」も削除しました。変更はありません...そして、いいえ、それはstatic内部クラスではありません。
TheLettuceMaster 2013年

待って、何がうまくいかないのですか?OPでは、機能しないことについては何も言及していませんActionBarからにタイトルを設定するための「適切な」方法を知りたいことだけを述べていFragmentます。また、私はthis.whatever何かの解決策として削除を提供していませんでした。それはコードフォーマットのヒントにすぎませんでした。
アドニール2013年

私はあなたが問題を抱えていることを理解し、それに応じて私の答えを編集したと思います。
アドニール2013年

ありがとう完璧な答え
Ammar ali

@KickingLettuce、私はそれが機能するまでしばらくの間この答えに苦労します(それが私がそれを賛成した理由とあなたの質問です):私のナビゲーションドロワーのメインアクティビティで(menu_act)私はグローバルな「mTitle」を作りました、そして、フラグメント、最初に「mTitle」(( (menu_act) getActivity() ).mTitle = "new_title")にタイトルを割り当て、すぐに( (menu_act) getActivity() ).restoreActionBar();。を割り当てます。「restoreActionBar()」の中に「actionBar.setTitle(mTitle);」があります。
ホセマヌエルアバルカロドリゲス

29

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

ありがとう。非常に優れたソリューションです。この方法で、カスタムビューをアクションバーに渡すこともできます。
アミール

Android SDKの最近の更新では、v7の下位互換性ライブラリを使用している場合に備えて、ActionBarActivityではなくAppCompatActivityにダウンキャストすることをお勧めします(おそらくそうすべきです)。
fr4gus 2017

8

混乱Activityからのタイトルの設定は、Fragment責任レベルを台無しにします。FragmentActivity、内に含まれているため、これは、Activityなどのタイプに応じて独自のタイトルを設定する必要がありFragmentます。

インターフェースがあるとします。

interface TopLevelFragment
{
    String getTitle();
}

Fragment影響を与えることができ、SActivityのタイトルは、このインターフェイスを実装します。あなたが書くホスティング活動中に:

@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のが組み合わされている場合でも、使用するタイトルを常に制御できます。これは、タブレットでは非常に可能です。


6

受け入れられた答えはそれに対する完璧な答えではないと思います。を使用するすべての活動以来

ツールバー

を使用して拡張されます

AppCompatActivity

、そこから呼び出されたフラグメントは、タイトルを変更するために以下のコードを使用できます。

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

5

このように使用できるフラグメントでは、正常に機能しています。

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

これは、アクティビティのツールバーにタイトルの役割を持つTextViewがある場合は機能しません
Simon

4

コードに問題がある場合に備えて、ieの代わりにフラグメントの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");
 }

これが私の問題でした-私がタイトルを設定していたところです。ただし、((MainActivity) getActivity()).setTitle("title")十分です。Kotlinでは、私のフラグメントはそうしactivity!!.title = "titleます。
ジョーラップ


2

これは、NavigationDrawerを使用するときに、フラグメントからActionBarタイトルを設定するための私のソリューションです。このソリューションはインターフェースを使用するため、フラグメントは親アクティビティを直接参照する必要はありません。

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

他のすべてのアプローチは、スケーラブルな設計ではない特定のアクティビティにフラグメントを関連付けているため、これは受け入れられる答えです。これは、Androidフレームワークも推奨するものです
Akhil Dad 2016

2

タイトル変更に最適なイベント 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);
}

2

簡単なKotlinの例

これらのgradledepsがプロジェクト内で一致するか、より高いバージョンであると想定します。

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


    }

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

これで、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

回答をString []オブジェクトに保存し、MainActivityのOnTabChange()に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));
}

1

そのようなキャスティングのアプローチの欠点

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

これは、フラグメントがMainActivityFragmentの外部で再利用できなくなったことです。そのアクティビティ以外で使用する予定がない場合は、問題ありません。より良いアプローチは、アクティビティに応じて条件付きでタイトルを設定することです。したがって、フラグメント内に次のように記述します。

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

1

単純なものよりもグーグルが提供するonNavigationItemSelectedandroidstudio 1.4の安定したテンプレートを使用している場合は、関連するフラグメントがif条件を呼び出すmethodeに次のコードを記述する必要がありました。

 setTitle("YOUR FRAGMENT TITLE");

アクティビティから直接タイトルにアクセスできるのであれば、それは素晴らしいことです...しかし、タイトルがフラグメント内で動的に設定された文字列である場合、フラグメントとアクティビティの間の通信が必要です
me_

1

ActionBar Titleをフラグメントまたはアクティビティに設定するための非常に簡単なソリューションを、頭痛の種なしに取得しています。

ツールバーが定義されている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");

優秀な!Androidナビゲーションコンポーネントを使用している場合、toolbar_titleを使用すると、フラグメントのタイトルが上書きされます。
Paixols 2018

0

選択した回答に追加するために、メインアクティビティに2番目のメソッドを追加することもできます。したがって、メインアクティビティで次のメソッドを使用することになります。

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ファイルなどのリソースIDの両方からタイトルを設定できます。これはgetSupportActionBar().setTitle()、リソースIDを渡すことができるため、動作方法と少し似ています。


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

0

少なくとも私にとっては、実行時にタブのタイトルを変更することに対する簡単な答えがありました(よく調べた後)。

TabLayout tabLayout =(TabLayout)findViewById(R.id.tabs); tabLayout.getTabAt(MyTabPos).setText( "My New Text");


0

あなたが使用している場合ViewPager(私の場合のように)あなたが使用することができます。

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

onPageSelectedあなたの方法VIEW_PAGER.addOnPageChangeListener


0

MainActivityで、 onCreate:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

そして、以下のフラグメントアクティビティでonResume

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

オプション:-null参照の警告が表示される場合

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


Objects.requireNonNull(getActivity()).setTitle(R.string.app_name_science);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.