getSupportActionBar จากด้านในของ Fragment ActionBarCompat


104

ฉันเริ่มโครงการใหม่ที่ใช้AppCompat/ActionBarCompatในการv7สนับสนุนห้องสมุด ฉันกำลังพยายามหาวิธีใช้getSupportActionBarจากภายในส่วน กิจกรรมของฉันที่โฮสต์แฟรกเมนต์ขยายออกไปActionBarActivityแต่ฉันไม่เห็นคลาสการสนับสนุนที่คล้ายกันสำหรับ Fragments

จากภายในส่วนของฉัน

    public class CrimeFragment extends Fragment {
          //...

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

          //...
    }

หน้า Google สำหรับใช้งาน ( http://android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html ) ระบุว่าไม่ควรมีการเปลี่ยนแปลงสำหรับv4ส่วนย่อย ฉันจำเป็นต้องส่งgetActivity()สายทั้งหมดไปที่ActionBarActivity? ดูเหมือนว่าการออกแบบที่ไม่ดี

คำตอบ:


290

หลังจากFragment.onActivityCreated (... )คุณจะมีกิจกรรมที่ใช้ได้ผ่าน getActivity ()

คุณจะต้องส่งไปยัง ActionBarActivity จากนั้นโทรออกเพื่อ getSupportActionBar ()

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

คุณไม่จำเป็นต้องมีนักแสดง ไม่ใช่การออกแบบที่แย่ แต่เข้ากันได้แบบย้อนกลับ


3
ขอบคุณ. ฉันหวังว่านี่จะไม่ใช่คำตอบ ฉันหวังว่า getActionBar () จะส่งคืน v7 ActionBar ที่ฉันจะส่งให้หากฉันต้องการฟังก์ชันพิเศษ ตอนนี้ Fragments ของฉันต้องตระหนักถึงประเภทของกิจกรรมที่พวกเขาโฮสต์อยู่
พอล

ไม่ไม่ใช่เพราะ getActionBar () เป็น Activity API ที่ไม่มีอยู่ใน SDK เวอร์ชันเก่า (pre-honeycomb) นี่คือเหตุผลที่เราต้องการคลาสการสนับสนุนที่สะท้อนการทำงานของคลาสและ API ใหม่และปรับปรุงใหม่ใน SDK ล่าสุด
Pierre-Antoine LaFayette

@ Pierre-AntoineLaFayette ทำไมถึงต้องทำใน onAttach ()? จะดีกว่าไหมใน onActivityCreated ()?
IgorGanapolsky

ใช่ตั้งแต่การเรียกครั้งแรกไปยัง getSupportActionBar () จะเริ่มต้น ActionBar โดยการค้นหามุมมองในกิจกรรมน่าจะดีกว่าสำหรับการเรียกนี้ใน onActivityCreated () ฉันพยายามมากขึ้นที่จะระบุว่าคุณต้องรอจนกว่าส่วนย่อยจะมีกิจกรรม ฉันจะอัปเดตคำตอบ
Pierre-Antoine LaFayette

2
ใช้ AppCompatActivity แทน ActionBarActivity
Aparajita Sinha

37

แม้ว่าคำถามนี้จะมีคำตอบที่ยอมรับอยู่แล้ว แต่ฉันต้องชี้ให้เห็นว่ามันไม่ถูกต้องทั้งหมด: การโทรgetSupportActionBar()จากFragment.onAttach()จะทำให้เกิดNullPointerExceptionการหมุนกิจกรรม

คำตอบสั้น ๆ :

ใช้((ActionBarActivity)getActivity()).getSupportActionBar()ในonActivityCreated()(หรือจุดใด ๆ หลังจากนั้นในวงจรชีวิตของมัน) onAttach()แทน

คำตอบยาว:

เหตุผลก็คือหากActionBarActivityสร้างขึ้นใหม่หลังจากการหมุนมันจะคืนค่า Fragments ทั้งหมดก่อนที่จะสร้างActionBarออบเจ็กต์จริง

ซอร์สโค้ดสำหรับActionBarActivityในsupport-v7ไลบรารี:

@Override
protected void onCreate(Bundle savedInstanceState) {
    mImpl = ActionBarActivityDelegate.createDelegate(this);
    super.onCreate(savedInstanceState);
    mImpl.onCreate(savedInstanceState);
}
  • ActionBarActivityDelegate.createDelegate()สร้างmImplวัตถุขึ้นอยู่กับเวอร์ชัน Android
  • super.onCreate()คือFragmentActivity.onCreate()ซึ่งจะคืนค่าส่วนก่อนหน้าหลังจากการหมุน ( FragmentManagerImpl.dispatchCreate(), & c)
  • mImpl.onCreate(savedInstanceState)คือActionBarActivityDelegate.onCreate()ซึ่งอ่านmHasActionBarตัวแปรจากลักษณะหน้าต่าง
  • ก่อนที่จะmHasActionBarเป็นความจริงมักจะกลับgetSupportActionBar()null

ที่มาสำหรับ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
ActionBarActivityเลิกใช้แล้ว ใช้AppCompatActivityแทน
สมานสัตรี

29

หากมีคนใช้ com.android.support:appcompat-v7: และ AppCompatActivity เป็นกิจกรรมสิ่งนี้จะได้ผล

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

5

ในแท็กfragment.xmlเพิ่มของคุณToolbarจากไลบรารีการสนับสนุน

 <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" />

ตอนนี้เราจะควบคุมมันจากMyFragmentชั้นเรียนได้อย่างไร? มาดูกัน

onCreateViewฟังก์ชันภายในเพิ่มสิ่งต่อไปนี้

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

และถ้าคุณต้องการเพิ่มitemsในแถบเครื่องมือภายในMyFragment คุณmustเพิ่มบรรทัดนี้ภายในonCreateViewฟังก์ชัน

        setHasOptionsMenu(true);

บรรทัดนี้สำคัญหากคุณลืม android จะไม่เติมรายการเมนูของคุณ

สมมติว่าเราระบุพวกเขาใน menu/fragment_menu.xml

หลังจากนั้นจะแทนที่ฟังก์ชันต่อไปนี้

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

หวังว่านี่จะช่วยได้


5

เป็นคำตอบที่อัปเดตสำหรับคำตอบของ Pierre-Antoine LaFayette

ActionBarActivity เลิกใช้งานแล้ว ใช้AppCompatActivityแทน

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.