조각에서 사용자 지정 ActionBar 제목 설정


90

내 Main 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이 작업을 수행하기 위해 Main 에 액세스하는 방법을 잘 모르겠 습니까? 과거에는 이렇게했습니다.

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

답변:


98

=== 2019 년 10 월 30 일 업데이트 ===

ViewModelLiveData 와 같은 새로운 구성 요소 가 있으므로 ViewModel 및 Live Data를 사용하여 Fragment에서 Activity Title을 업데이트하는 다른 / 쉬운 방법을 가질 수 있습니다.

활동

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

그런 다음 다음을 사용하여 Fragment에서 활동 제목을 업데이트 할 수 있습니다. 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-08-02

1
내가 찾던 바로 그 답이 선택한 답보다 나에게 더 효과적이었습니다. 감사!
dstrube 2016 년

1
이것은 받아 들여진 대답이어야합니다! 어떻게해야하는지 정확하게 보여줍니다. 프래그먼트가 호스팅 활동과 통신하려면 항상 인터페이스를 통해 통신해야합니다. 조각은 인터페이스를 제공하고 활동은이를 구현합니다! 여러 조각이 활동과 동일한 방식으로 통신해야하는 경우 인터페이스를 제공하는 추상 조각을 작성한 다음 모든 조각이이 "기본 조각"에서 상속되도록합니다.
winklerrr

3
그건 그렇고 :이 답변에 사용 된 onAttach (Activity) 메서드는 이번에는 더 이상 사용되지 않습니다. onAttach(Context)전달 된 호스트 활동이 필요한 인터페이스를 구현하는지 메서드 내부를 확인 합니다 (을 통해 호스트 활동 검색 context.getActivity()).
winklerrr

2
수년 후 나는 이것을 받아 들여진 대답으로 변경했습니다. 우리가 알고 있듯이 인터페이스는 조각과 활동이 통신하는 데 필요한 방법이기 때문입니다.
TheLettuceMaster

150

당신이하는 일은 옳습니다. API에 Fragments대한 액세스 권한이 없으므로 . 당신이하지 않는 정적 내부 클래스이며,이 경우 당신은을 만들어야 부모와 통화 활동에. 거기에서.ActionBargetActivityFragmentWeakReferencegetActionBar

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제공 한 코드 를 호출 할 필요없이 팁만 있으면됩니다.


나는 노력하고 그것을 작동시킬 수 없습니다. 그것의 가치를 위해, 나는 나의 게시 XML하고 또한 "this"를 제거했다. 변경 사항 없음 ... 그리고 아니, static내부 클래스 가 아닙니다 .
TheLettuceMaster 2013 년

잠깐, 작동하지 않는 것은 무엇입니까? 당신의 영업 이익에서 당신은 아무것도 언급하지 않을 수 없습니다 , 당신은 단지에있는 제목을 설정하기 위해 "적절한"방법을 알고 싶은 말할 것도 작업 ActionBarA로부터를 Fragment. 또한 나는 this.whatever어떤 것에 대한 해결책으로 제거 를 제안하지 않았 으며 코드 서식 지정 팁일뿐이었습니다.
adneal

나는 당신이 어려움을 겪고있는 것을 이해하고 그에 따라 내 대답을 편집했다고 생각합니다.
adneal

Thankx 완벽한 답변
Ammar ali

@KickingLettuce, 나는 그것이 작동 할 때까지 menu_act잠시이 대답으로 고생한다. 조각, 먼저 제목을 "mTitle"( ( (menu_act) getActivity() ).mTitle = "new_title")에 할당 하고 즉시 ( (menu_act) getActivity() ).restoreActionBar();. "restoreActionBar ()"안에 "actionBar.setTitle (mTitle);"이 있습니다.
Jose Manuel Abarca Rodríguez

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

감사. 이 방법으로 사용자 정의보기를 작업 표시 줄에 전달할 수도 있습니다.
Amir

Android SDK의 최신 업데이트를 통해 ActionBarActivity 대신 v7 하위 호환성 라이브러리를 사용하는 경우 AppCompatActivity로 다운 캐스트 할 수 있습니다.
fr4gus

8

Activity의 제목을 설정하면 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몇 개의 TopLevelFragments가 결합 되더라도 어떤 타이틀을 사용할지 항상 제어 할 수 있습니다. 이는 태블릿에서 가능합니다.


6

나는 받아 들여진 대답이 그것에 대한 완벽한 대답이라고 생각하지 않는다. 사용하는 모든 활동이

툴바

사용하여 확장됩니다

AppCompatActivity

, 그것에서 호출 된 조각은 제목을 변경하기 위해 아래 언급 된 코드를 사용할 수 있습니다.

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

5

Fragment에서 우리는 이렇게 사용할 수 있습니다. 그것은 저에게 잘 작동합니다.

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.
Joe Lapp


2

NavigationDrawer를 사용할 때 조각에서 ActionBar 제목을 설정하는 솔루션은 다음과 같습니다. 이 솔루션은 인터페이스를 사용하므로 조각이 부모 활동을 직접 참조 할 필요가 없습니다.

1) 인터페이스 생성 :

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

2) Fragment의 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; 
}

다른 모든 접근 방식이 확장 가능한 디자인이 아닌 특정 활동에 연결된 조각을 만들고 있기 때문에 이것은 허용되는 대답이어야합니다. 이것은 또한 안드로이드 프레임 워크가 권장하는 것입니다
Akhil Dad

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 예제

이러한 gradle deps가 프로젝트에서 일치하거나 더 높은 버전이라고 가정합니다.

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 [] 개체에 ur Answer를 저장하고 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

구글에서 제공하는 안드로이드 스튜디오 1.4 안정적인 템플릿을 단순하게 사용하고 onNavigationItemSelected있다면 관련 프래그먼트가 if 조건을 호출하는 방법으로 다음 코드를 작성해야했습니다 .

 setTitle("YOUR FRAGMENT TITLE");

활동에서 직접 제목에 액세스 할 수 있다면 훌륭합니다 ... 그러나 제목이 조각에서 동적으로 설정된 문자열 인 경우 조각과 활동간에 통신이 필요합니다
me_

1

두통없이 단편 또는 모든 활동에서 ActionBar Title을 설정하는 매우 간단한 솔루션을 얻고 있습니다.

아래와 같이 Toolbar가 정의 된 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

0

선택한 답변에 추가하기 위해 주 활동에 두 번째 방법을 추가 할 수도 있습니다. 따라서 주요 활동에서 다음 방법을 사용하게됩니다.

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

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

이렇게하면 R.id.this_is_a_stringstrings.xml 파일 과 같은 리소스 ID뿐 아니라 String 변수에서 제목을 설정할 수 있습니다 . 이것은 또한 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.