getSupportActionBar từ bên trong Fragment ActionBarCompat


102

Tôi đang bắt đầu một dự án mới sử dụng thư viện hỗ trợ AppCompat/ActionBarCompattrong v7. Tôi đang cố gắng tìm ra cách sử dụng getSupportActionBartừ bên trong một mảnh. Hoạt động lưu trữ phân mảnh của tôi mở rộng ActionBarActivity, nhưng tôi không thấy lớp hỗ trợ tương tự cho Phân mảnh.

Từ trong mảnh vỡ của tôi

    public class CrimeFragment extends Fragment {
          //...

          getActivity().getSupportActionBar().setSubtitle(R.string.subtitle); // getSupportActionBar is not defined in the v4 version of Fragment

          //...
    }

Trang google để sử dụng nó ( http://android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html ) cho biết sẽ không có thay đổi nào đối với v4phân đoạn. Tôi có cần chuyển tất cả các getActivity()cuộc gọi của mình tới một ActionBarActivitykhông? Điều đó có vẻ như thiết kế kém.

Câu trả lời:


287

Sau Fragment.onActivityCreate (...), bạn sẽ có một hoạt động hợp lệ có thể truy cập thông qua getActivity ().

Bạn sẽ cần truyền nó đến một ActionBarActivity, sau đó thực hiện cuộc gọi tới getSupportActionBar ().

((AppCompatActivity)getActivity()).getSupportActionBar().setSubtitle(R.string.subtitle);

Bạn cần diễn viên. Nó không phải là thiết kế kém, mà là khả năng tương thích ngược.


3
Cảm ơn. Tôi đã hy vọng đây sẽ không phải là câu trả lời. Tôi đã hy vọng có thể getActionBar () sẽ trả về một ActionBar v7 mà tôi sẽ truyền đến nếu tôi cần thêm chức năng. Bây giờ Những mảnh vỡ của tôi phải được nhận thức về những gì loại Hoạt động chúng được lưu trữ trong.
Paul

Không, không phải vì getActionBar () là một API hoạt động không tồn tại trên các phiên bản SDK cũ hơn (pre-honeycomb). Đây là lý do tại sao chúng tôi cần các lớp hỗ trợ phản ánh chức năng của các lớp và API mới và cải tiến trong các SDK gần đây hơn.
Pierre-Antoine LaFayette

@ Pierre-AntoineLaFayette Tại sao điều này phải được thực hiện trong onAttach ()? Nó sẽ tốt hơn trong onActivityCreate ()?
IgorGanapolsky

Có vì lệnh gọi getSupportActionBar () đầu tiên sẽ khởi tạo ActionBar bằng cách tra cứu các dạng xem trong hoạt động, nên có lẽ tốt hơn là cuộc gọi này được thực hiện trong onActivityCreate (). Tôi chỉ cố gắng chỉ ra rằng bạn cần đợi cho đến khi phân đoạn có hoạt động. Tôi sẽ cập nhật câu trả lời.
Pierre-Antoine LaFayette,

2
Sử dụng AppCompatActivity thay vì ActionBarActivity
Aparajita Sinha

37

Mặc dù câu hỏi này đã có câu trả lời được chấp nhận, nhưng tôi phải chỉ ra rằng nó không hoàn toàn chính xác: việc gọi getSupportActionBar()từ Fragment.onAttach()sẽ gây ra NullPointerExceptionkhi hoạt động được xoay vòng.

Câu trả lời ngắn:

Sử dụng ((ActionBarActivity)getActivity()).getSupportActionBar()tại onActivityCreated()(hoặc bất kỳ điểm nào sau đó trong vòng đời của nó) thay vì onAttach().

Câu trả lời dài:

Lý do là nếu an ActionBarActivityđược tạo lại sau một vòng quay, nó sẽ khôi phục tất cả các Fragment trước khi thực sự tạo ActionBarđối tượng.

Mã nguồn ActionBarActivitytrong support-v7thư viện:

@Override
protected void onCreate(Bundle savedInstanceState) {
    mImpl = ActionBarActivityDelegate.createDelegate(this);
    super.onCreate(savedInstanceState);
    mImpl.onCreate(savedInstanceState);
}
  • ActionBarActivityDelegate.createDelegate()tạo mImplđối tượng tùy thuộc vào phiên bản Android.
  • super.onCreate()FragmentActivity.onCreate(), khôi phục bất kỳ đoạn nào trước đó sau một vòng quay ( FragmentManagerImpl.dispatchCreate()& c).
  • mImpl.onCreate(savedInstanceState)ActionBarActivityDelegate.onCreate(), đọc mHasActionBarbiến từ kiểu cửa sổ.
  • Trước khi mHasActionBarlà sự thật, getSupportActionBar()sẽ luôn luôn trở lại null.

Nguồn cho ActionBarActivityDelegate.getSupportActionBar():

final ActionBar getSupportActionBar() {
    // The Action Bar should be lazily created as mHasActionBar or mOverlayActionBar
    // could change after onCreate
    if (mHasActionBar || mOverlayActionBar) {
        if (mActionBar == null) {
            ... creates the action bar ...
        }
    } else {
        // If we're not set to have a Action Bar, null it just in case it's been set
        mActionBar = null;
    }
    return mActionBar;
}

2
ActionBarActivitykhông được dùng nữa. Sử dụng AppCompatActivitythay thế
Saman Sattari

29

Nếu ai đó sử dụng com.android.support:appcompat-v7: và AppCompatActivity làm hoạt động thì điều này sẽ hoạt động

((AppCompatActivity)getActivity()).getSupportActionBar().setSubtitle(R.string.subtitle);

5

trong thẻ fragment.xmlthêm của bạn Toolbartừ thư viện hỗ trợ

 <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

Bây giờ chúng ta có thể kiểm soát nó từ MyFragment lớp học? hãy xem nào

onCreateViewchức năng bên trong thêm phần sau

mToolbar = (Toolbar) view.findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(mToolbar);

//add this line if you want to provide Up Navigation but don't forget to to 
//identify parent activity in manifest file
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);

và nếu bạn muốn thêm itemsvào thanh công cụ bên trong, MyFragment bạn hãy mustthêm dòng này vào bên trong onCreateViewhàm

        setHasOptionsMenu(true);

dòng này rất quan trọng, nếu bạn quên nó, android sẽ không điền các Mục trong menu của bạn.

giả sử chúng tôi xác định họ trong menu/fragment_menu.xml

sau đó ghi đè các chức năng sau

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.fragment_menu, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    switch (id) {
        case R.id.action_1:
            // do stuff
            return true;

        case R.id.action_2:
            // do more stuff
            return true;
    }

    return false;
}

hi vọng điêu nay co ich


5

Như một câu trả lời cập nhật cho câu trả lời của Pierre-Antoine LaFayette

ActionBarActivity không được dùng nữa; sử dụng AppCompatActivitythay thế

((AppCompatActivity)getActivity()).getSupportActionBar();

3

Đối với những người sử dụng kotlin,

(activity as AppCompatActivity).supportActionBar.setSubtitle(R.string.subtitle)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.