วิธีรับ Toolbar จากแฟรกเมนต์


107

ฉันต้องActionBarActivityมีNavigationDrawerและการใช้ support_v7 Toolbarเป็น ActionBar ในแถบเครื่องมือเศษชิ้นส่วนของฉันมีมุมมองที่กำหนดเอง ในส่วนอื่น ๆToolbarควรแสดงชื่อเรื่อง

วิธีรับToolbarอินสแตนซ์สำหรับการปรับแต่งจากชิ้นส่วน? ฉันสามารถรับ ActionBar ได้getActivity().getActionBar()แต่ถ้าฉันเรียกsetTitle()อินสแตนซ์นี้ว่า ActionBar จะไม่ทำอะไรเลย

UPD:

ในกรณีของฉัน

((ActionBarActivity) getActivity()).getSupportActionBar().setTitle();

(ตามที่ MrEngineer13 กล่าว) ไม่ทำงานในการสร้างส่วนแรกเพราะฉันเรียกมันจาก onHiddenChanged () ตอนนี้ฉันเพิ่มอีกหนึ่งรายการใน onCreateView () และใช้งานได้ดี


ส่วนย่อยไม่มีแถบการดำเนินการ / กิจกรรมแถบเครื่องมือ
tyczj

(MainAcivity) this.getActivity ()). getToolbar (); จะเป็นคำตอบที่ถูกต้อง !! เพื่อรับ Toolbar ในส่วนย่อย !!
LOG_TAG

คำตอบ:


201

คุณจำเป็นต้องโยนกิจกรรมของคุณจากgetActivity()ไปAppCompatActivityครั้งแรก นี่คือตัวอย่าง:

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

เหตุผลที่คุณต้องแคสต์เพราะgetActivity()ส่งคืน a FragmentActivityและคุณต้องการไฟล์AppCompatActivity

ใน Kotlin:

(activity as AppCompatActivity).supportActionBar?.title = "My Title"

8
การรับ 'supportActionBar' และ 'toolbar' เป็นสิ่งเดียวกันหรือไม่?
Darpan

@Darpan ไม่แน่ใจ
Konstantin Konopko

ถ้าฉันเพิ่มสิ่งนี้มันจะเปลี่ยนชื่อเรื่อง .. แต่ถ้าฉันกลับไปที่กิจกรรมหลักจะเปลี่ยนชื่ออีกครั้งได้อย่างไร ฉันหมายความว่าฉันมีลิ้นชักนำทาง ลิ้นชักด้านข้างมีเศษชิ้นส่วนและกิจกรรมหลักมีชื่อของตัวเอง เมื่อฉันตั้งชื่อกิจกรรมหลักมันทำงานและเป็นส่วน ๆ วิธีที่คุณกล่าวถึงทำงานได้อย่างสมบูรณ์แบบ แต่ฉันจะเปลี่ยนชื่อกิจกรรมในการย้อนกลับได้อย่างไร?
Kylo Ren

82

ในกรณีที่ชิ้นส่วนควรมีมุมมองที่กำหนดเองของ ToolBar คุณสามารถใช้ ToolBar สำหรับแต่ละส่วนแยกกันได้

เพิ่ม ToolBar ลงใน fragment_layout:

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimaryDark"/>

ค้นหาในส่วน:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment, container, false);
        Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);

        //set toolbar appearance
        toolbar.setBackground(R.color.material_blue_grey_800);

        //for crate home button
        AppCompatActivity activity = (AppCompatActivity) getActivity();
        activity.setSupportActionBar(toolbar);
        activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

ตัวฟังเมนูสามารถสร้างได้สองวิธี: แทนที่ onOptionsItemSelected ในส่วนของคุณ:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch(item.getItemId()){
        case android.R.id.home:
            getActivity().onBackPressed();
    }
    return super.onOptionsItemSelected(item);
}

หรือตั้งค่า Listener สำหรับแถบเครื่องมือเมื่อสร้างใน onCreateView ():

toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {
                return false;
            }
        });

1
ฉันแค่ต้องการยืนยันว่าวิธีนี้ถูกต้อง? ถ้าเราโหลดส่วนต่าง ๆ ด้วยแถบเครื่องมือใน viewpager + Tablayout หรือ Pagertabstripe มันจะส่งผลต่อประสิทธิภาพของแอพในขณะที่ปัด?
LOG_TAG

1
@LOG_TAG ฉันมีการออกแบบลิ้นชักโดยแต่ละส่วนที่ใช้แถบเครื่องมือ (และมีแถบเครื่องมืออยู่ในไฟล์เลย์เอาต์) และโค้ดด้านบนก็ใช้ได้ดีสำหรับฉัน
MattBoothDev

ขอบคุณ! ทำงานอย่าง HEYUL !! :) Btw ดีกว่าที่จะแทนที่กิจกรรมของผู้ปกครองonOptionsItemSelected()แทนที่จะเป็น Fragment เพื่อหลีกเลี่ยงการซ้ำรหัส
Aditya Naique

@ChadMx ไม่ทำไมเขาถึงเขียนเกี่ยวกับการเพิ่มแถบเครื่องมือใน xml เป็นต้น ผู้เขียนถามวิธีรับแถบเครื่องมือโดยทางโปรแกรมจากส่วนย่อย ดังนั้นstackoverflow.com/a/26998718/4548520นี้เป็นที่ดีที่สุด / คำตอบที่ถูกต้องและมันสั้น
user25

43

คุณมีสองทางเลือกในการรับ Toolbar ในส่วนย่อย

คนแรก

Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);

และอันที่สอง

Toolbar toolbar = ((MainActivity) getActivity()).mToolbar;

แต่นี่เป็นวิธีที่ถูกต้อง .. bcoz เรามี getSupportedActionBar ด้วยหรือเปล่า?
Code_Life

9
toolbar = (Toolbar) getView().findViewById(R.id.toolbar);
AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.setSupportActionBar(toolbar);

2

สำหรับผู้ใช้ Kotlin (activity as AppCompatActivity).supportActionBar?.show()


!!สามารถหลีกเลี่ยงได้อย่างสมบูรณ์?และจะช่วยให้คุณไม่เกิดความผิดพลาด
JonZarate

ฉันเชื่อว่าสิ่งนี้ดีกว่า(activity as? AppCompatActivity)?.supportActionBar?.show()
JonZarate


1

จาก Fragment ของคุณ: (รับ Toolbar จาก Fragment?)

// get toolbar
((MainAcivity)this.getActivity()).getToolbar();  // getToolbar will be method in Activity that returns Toolbar!!  don't use getSupportActionBar for getting toolbar!!
// get action bar
this.getActivity().getSupportActionBar();

สิ่งนี้มีประโยชน์มากเมื่อคุณใช้ spinner ใน Toolbar และเรียกใช้spinnerหรือมุมมองแบบกำหนดเองใน Toolbar จากส่วนย่อย!

จากกิจกรรมของคุณ:

// get toolbar
this.getToolbar();
// get Action Bar
this.getSupportActionBar();

3
คุณต้องมีเมธอดในกิจกรรมของคุณที่เรียกว่าgetToolbar ()ซึ่งไม่ดีเพราะนั่นไม่ใช่วิธีการสื่อสารระหว่างกิจกรรมและส่วนย่อยที่ควรทำ
Marko

2
ใช่ไม่มีวิธีอื่นสำหรับสิ่งนี้ !! libs ลิ้นชักการนำทางจำนวนมากใช้สไตล์นี้เท่านั้น !!! บางครั้งเราต้องแคสต์กิจกรรมเพราะ AppCompatActivity (AppCompatActivity) getActivity () นั่นคืออีกจุดที่เจ็บปวด !!! เนื้อหาทั้งหมดนี้ฆ่าเวลาในการพัฒนาโดยสิ้นเชิง :(
LOG_TAG

1

ใน XML

 <androidx.appcompat.widget.Toolbar
  android:id="@+id/main_toolbar"
  android:layout_width="match_parent"
  android:layout_height="?attr/actionBarSize"
  app:layout_scrollFlags="scroll|enterAlways">
 </androidx.appcompat.widget.Toolbar>

Kotlin: ใน fragment.kt -> onCreateView ()

setHasOptionsMenu(true)

val toolbar = view.findViewById<Toolbar>(R.id.main_toolbar)

(activity as? AppCompatActivity)?.setSupportActionBar(toolbar)

(activity as? AppCompatActivity)?.supportActionBar?.show()

-> onCreateOptionsMenu ()

   override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
       inflater.inflate(R.menu.app_main_menu,menu)
       super.onCreateOptionsMenu(menu, inflater)
   }

-> onOptionsItemSelected ()

   override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
             R.id.selected_id->{//to_do}
             else -> super.onOptionsItemSelected(item)
        }
    }

0

ฉันทำได้โดยใช้ขั้นตอนเหล่านี้

  1. ตั้งชื่อเรื่องโดยใช้รหัสด้านล่างในonCreateViewส่วนหลัก
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle("Your title");
  1. สำหรับการแลกเปลี่ยนระหว่างชิ้นส่วนฉันใช้แถบนำทางด้านล่างซึ่งใช้กับMainActivity(กิจกรรมหลัก) ของส่วน แม้ว่าคุณจะใช้ปุ่มหรือรายการเมนูใด ๆ คุณก็สามารถเปลี่ยนชื่อเรื่องได้onSelectedItemClickListenerเช่นเดียวกับที่ฉันทำในกรณีของฉัน
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        switch (menuItem.getItemId()){
            case R.id.menu_dashboard:
                getSupportActionBar().setTitle("Dashboard");
                fm.beginTransaction().hide(active).show(dashboardFragment).commit();
                active = dashboardFragment;
                return true;
            case R.id.menu_workshop:
                getSupportActionBar().setTitle("Workshops");
                fm.beginTransaction().hide(active).show(workshopFragment).commit();
                active = workshopFragment;
                return true;
         }
         return false;
    }

0

หากคุณใช้แถบเครื่องมือที่กำหนดเองหรือ ActionBarและคุณต้องการได้รับการอ้างอิงของแถบเครื่องมือ / แถบการกระทำของคุณจาก Fragments ก่อนอื่นคุณต้องรับอินสแตนซ์ของกิจกรรมหลักของคุณจากวิธีonCreateViewของ Fragment ดังด้านล่าง

MainActivity activity = (MainActivity) getActivity();

จากนั้นใช้กิจกรรมเพื่อนำไปใช้งานเพิ่มเติมดังด้านล่าง

ImageView vRightBtn = activity.toolbar.findViewById(R.id.toolbar_right_btn);

ก่อนที่จะเรียกสิ่งนี้คุณต้องเริ่มต้นแถบเครื่องมือที่กำหนดเองใน MainActivity ของคุณดังต่อไปนี้

ชุดแรกกำหนดแถบเครื่องมือของคุณแบบสาธารณะ

public Toolbar toolbar;
public ActionBar actionBar;

และในonCreate ()วิธีการกำหนดรหัสแถบเครื่องมือที่กำหนดเอง

toolbar = findViewById(R.id.custom_toolbar);
setSupportActionBar(toolbar);
actionBar = getSupportActionBar();

แค่นั้นแหละ. มันจะทำงานใน Fragment

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