82

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

Từ bên 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 

      //... 
    } 

Các google trang để sử dụng nó (http://android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html) nói không nên có những thay đổi cho v4 mảnh. Tôi có cần chuyển tất cả các cuộc gọi getActivity() của mình sang số ActionBarActivity không? Điều đó có vẻ như thiết kế kém.

+0

Có thể giải thích cách bạn giải quyết vấn đề này? –

Trả lời

229

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

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

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

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

+3

Cảm ơn. Tôi đã hy vọng điều nà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ẽ cast nếu tôi cần thêm chức năng. Bây giờ mảnh vỡ của tôi phải nhận thức được loại hoạt động mà chúng được lưu trữ trong. – Paul

+0

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 cũ hơn của SDK (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. –

+0

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

33

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

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

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

Long trả lời:

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

Mã nguồn cho ActionBarActivity trong thư viện support-v7:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    mImpl = ActionBarActivityDelegate.createDelegate(this); 
    super.onCreate(savedInstanceState); 
    mImpl.onCreate(savedInstanceState); 
} 
  • ActionBarActivityDelegate.createDelegate() tạo ra các đối tượng mImpl tùy theo phiên bản Android.
  • super.onCreate()FragmentActivity.onCreate(), khôi phục mọi đoạn trước đó sau khi xoay vòng (FragmentManagerImpl.dispatchCreate(), & c).
  • mImpl.onCreate(savedInstanceState)ActionBarActivityDelegate.onCreate(), đọc biến số mHasActionBar từ kiểu cửa sổ.
  • Trước khi mHasActionBar là đúng, getSupportActionBar() sẽ luôn trả lại null.

Nguồn 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; 
} 
25

Nếu ai đó sử dụng com.android.support:appcompat-v7: và AppCompatActivity như hoạt động thì đây sẽ làm việc

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

trong bạn fragment.xml thêm Toolbar Gắn thẻ từ 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ó như thế nào từ lớp MyFragment? chúng ta hãy xem

bên onCreateView chức năng thêm như 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 items vào thanh công cụ trong MyFragment bạn must thêm dòng này bên onCreateView chức năng

 setHasOptionsMenu(true); 

dòng này là quan trọng, nếu bạn quên nó, android sẽ không cư các mục menu của bạn.

giả sử chúng ta xác định chúng trong menu/fragment_menu.xml

sau đó ghi đè lên 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; 
} 

hy vọng điều này giúp

0

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

ActionBarActivity là không được chấp nhận; sử dụng AppCompatActivity thay vì

((AppCompatActivity)getActivity()).getSupportActionBar(); 
Các vấn đề liên quan