Android Lollipop มุมมองที่กำหนดเองของ AppCompat ActionBar ไม่ใช้ความกว้างของหน้าจอทั้งหมด


97

ดังนั้นฉันเพิ่งอัปเดต codebase ของฉันเป็น Lollipop และฉันมีปัญหากับ Action Bar ฉันใช้ AppCompat และ ActionBarActivity และขยายมุมมองที่กำหนดเอง ดูเหมือนว่ามุมมองแบบกำหนดเองจะไม่ใช้ความกว้างทั้งหมดของหน้าจออีกต่อไปโดยปล่อยให้มีแถบบาง ๆ ทางด้านซ้าย

อาคารที่มี 19 แบบที่เคยดู

อาคารที่มี 21 หน้าตาตอนนี้

นี่คือรหัสที่ฉันใช้ตั้งค่าแถบการดำเนินการ ใครมีไอเดียบ้าง

final ActionBar actionBar = getSupportActionBar();
if(actionBar != null) {
    actionBar.setDisplayHomeAsUpEnabled(false);
    actionBar.setDisplayShowHomeEnabled(false);
    actionBar.setDisplayShowTitleEnabled(false);
    actionBar.setDisplayShowCustomEnabled(true);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
    actionBar.setCustomView(R.layout.action_bar_content_search_custom_view);
    actionBar.setBackgroundDrawable(null);
    // actionBar.setStackedBackgroundDrawable(null);
    TextView title = (TextView) actionBar.getCustomView().findViewById(R.id.action_bar_title);
    title.setText(R.string.youtube);
    ImageView back = (ImageView) actionBar.getCustomView().findViewById(R.id.action_bar_back);
    back.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            finish();
        }
    });
}

แก้ไข

การออกจากมุมมองแบบกำหนดเองและการเปลี่ยนพื้นหลังจะใช้ความกว้างทั้งหมด ปัญหาคือเราจะทำให้ CustomView ใช้ความกว้างทั้งหมดของ ActionBar ได้อย่างไร


หากคุณแสดงความคิดเห็นชั่วคราวในส่วนของมุมมองที่กำหนดเองจะทำงานได้ดีขึ้นหรือไม่ ถ้าไม่ฉันจะเอนเอียงไปทางนี้บางทีอาจมาจากธีมของคุณ
CommonsWare

ฉันลบมุมมองที่กำหนดเองและตั้งค่าพื้นหลังเป็นพื้นหลังที่วาดได้ของ ActionBar และพื้นหลังจะใช้ความกว้างทั้งหมดในขณะนี้
Stevie Kideckel

คุณอาจดูกิจกรรมของคุณในมุมมองลำดับชั้นทั้งที่มีและไม่มีมุมมองแบบกำหนดเองและดูว่าคุณสามารถกำหนดได้หรือไม่ว่ากฎการจัดวางจะเปลี่ยนไปจากมุมมองที่กำหนดเองหรือไม่ เป็นไปได้ว่านี่เป็นข้อบกพร่องในไฟล์appcompat-v7.
CommonsWare

ImageViewหน้าตาที่ผมว่าเป็นสถานที่ที่สงวนไว้สำหรับขึ้น ลองปิดการใช้งานเพื่อเริ่มต้น
Nikola Despotoski

1
สวัสดีดูเหมือนว่านี่เป็นทางออกที่ดีที่จะให้มุมมองแบบกำหนดเองใช้ความกว้างทั้งหมด ฉันพบว่ามันไม่ขยายแม้จะมีการตั้งค่าน้ำหนักเลย์เอาต์ ดูที่นี่: stackoverflow.com/a/20794736/581574
รัตนา

คำตอบ:


111

ดูเหมือนว่าจะเกิดจากการเปลี่ยนแปลงล่าสุดActionBarในการappcompat-v7อัปเดตล่าสุด ดูเหมือนว่ามีการเปลี่ยนแปลงที่สำคัญเกี่ยวกับวิธีจัดการกับแถบการทำงาน

ฉันประสบปัญหาเดียวกันและหลังจากอ่านActionBarเอกสารและโดยเฉพาะอย่างยิ่งคำพูดต่อไปนี้ฉันพบวิธีแก้ปัญหา

เริ่มต้นด้วย Android L (API ระดับ 21) แถบการทำงานอาจแสดงโดยวิดเจ็ต Toolbar ใดก็ได้ภายในเค้าโครงแอปพลิเคชัน แอปพลิเคชันอาจส่งสัญญาณถึงกิจกรรมที่แถบเครื่องมือควรถือเป็นแถบการทำงานของกิจกรรม กิจกรรมที่ใช้คุณลักษณะนี้ควรใช้หนึ่งในธีม. NoActionBar ที่ให้มาตั้งค่าแอ็ตทริบิวต์ windowActionBar เป็น false หรือมิฉะนั้นจะไม่ร้องขอคุณลักษณะหน้าต่าง

วิธีที่ฉันเห็นAppCompatธีมก็เปลี่ยนไปและในแง่หนึ่งดูเหมือนจะทำลายบางสิ่ง แต่ให้ความยืดหยุ่นมากกว่าในอีกเรื่อง ขอแนะนำให้ทำตามขั้นตอนเหล่านี้:

  1. ใช้.NoActionBarสไตล์ในกิจกรรมของคุณตามที่อธิบายไว้ในคำพูดข้างต้น
  2. เพิ่มandroid.support.v7.widget.Toolbarในรูปแบบกิจกรรมของคุณ
  3. ตั้งค่าapp:contentInsetStart="0dp"แอตทริบิวต์ นี่เป็นปัญหาหลักเกี่ยวกับระยะขอบที่คุณอธิบายในคำถามของคุณ
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/actionBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:contentInsetEnd="0dp"
    app:contentInsetStart="0dp" >
</android.support.v7.widget.Toolbar>

โดยปกติจะแนะนำให้คุณทำในไฟล์เลย์เอาต์แยกต่างหากและใช้includeในรูปแบบกิจกรรมของคุณดังนั้นคุณจะต้องปรับแต่งแถบเครื่องมือในที่เดียวหากใช้ในหลายกิจกรรม

<include layout="@layout/view_action_bar" />
  1. ใช้findViewByIdและsetSupportActionBarในกิจกรรมของคุณonCreateเพื่อsignal to the Activity which Toolbar should be treated as the Activity's action bar
Toolbar actionBar = (Toolbar) findViewById(R.id.actionBar);
setSupportActionBar(actionBar);
  1. เมื่อคุณทำเช่นนั้นการกระทำทั้งหมดที่เพิ่มเข้ามาonCreateOptionsMenuจะถูกเพิ่มลงในแถบเครื่องมือและจะถือว่าเป็นแถบการดำเนินการของกิจกรรม
  2. ปรับแต่ง Toolbar เพิ่มเติมตามต้องการ (เพิ่มมุมมองเด็ก ฯลฯ )

1
ฉันพยายามใช้ Toolbar กับลิ้นชักการนำทาง แต่ฉันได้รับข้อผิดพลาดError inflating class fragment
Ahmed Nawaz

มีการแบ่งปันรหัสที่เกี่ยวข้องทั้งหมดในคำตอบ ดูเหมือนว่าคุณควรเริ่มคำถามใหม่สำหรับกรณีของคุณเพราะดูเหมือนว่าจะเป็นปัญหาอื่น
Muzikant

ขอบคุณ. ฉันแก้ไขปัญหาโดยการแทนที่ actionbar ด้วย Toolbar
Ahmed Nawaz

9
คุณไม่ควรใช้ชื่อแพ็กเกจที่ชัดเจนในการประกาศเนมสเปซ ใช้xmlns:app="http://schemas.android.com/apk/res-auto"
Liminal

1
ไม่มีความจำเป็นสำหรับsetCustomView. เพียงสร้างไฟล์เลย์เอาต์ด้วยวิดเจ็ตที่คุณต้องการรวมไว้ในแถบเครื่องมือของคุณ (เช่นเพิ่มมุมมองเด็กลงในไฟล์เลย์เอาต์ที่อธิบายไว้ในส่วนที่ 3 ของคำตอบ)
Muzikant

51

แทนที่จะทำงานมากมายตามที่Muzikantกล่าวไว้และชอบคำตอบนี้

    getSupportActionBar().setDisplayShowHomeEnabled(false);
    getSupportActionBar().setDisplayShowTitleEnabled(false);
    getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.WHITE));
    LayoutInflater mInflater = LayoutInflater.from(this);

    View mCustomView = mInflater.inflate(R.layout.action_bar_home, null);
    getSupportActionBar().setCustomView(mCustomView);
    getSupportActionBar().setDisplayShowCustomEnabled(true);
    Toolbar parent =(Toolbar) mCustomView.getParent();//first get parent toolbar of current action bar 
    parent.setContentInsetsAbsolute(0,0);// set padding programmatically to 0dp

คุณต้องเพิ่มโค้ดเพียงสองบรรทัดสุดท้ายเพื่อแก้ปัญหาของคุณ

ฉันหวังว่านี่อาจช่วยคุณและใครก็ได้

UPDATE:หลังจากทำการวิจัยบางอย่างแล้วฉันพบว่าวิธีนี้จะใช้ไม่ได้ในบางกรณี ช่องว่างด้านซ้าย (HOME หรือ BACK) จะถูกลบออก แต่ช่องว่างด้านขวา (MENU) จะยังคงอยู่ตามเดิม ด้านล่างนี้เป็นวิธีแก้ปัญหาในกรณีเหล่านี้

View v = getSupportActionBar().getCustomView();
LayoutParams lp = v.getLayoutParams();
lp.width = LayoutParams.MATCH_PARENT;
v.setLayoutParams(lp);

เพิ่มสี่บรรทัดเหล่านี้ในโค้ดด้านบนเพื่อให้ช่องว่างด้านขวาถูกลบออกจากแถบการสนับสนุน


ขอบคุณ! ขอบคุณ! 2 บรรทัดสุดท้ายคือสิ่งที่ฉันกำลังมองหา!
digitalmidges

เราจะเพิ่มบรรทัดเหล่านี้ได้ที่ไหน? หลังจากส่วน Toolbar?
Zen

1
@summers ใช่เพิ่มทันทีหลังรหัสแถบเครื่องมือ
Amrut Bidri

31

ฉันคิดว่าคุณสามารถทำแบบนั้นได้เช่นกัน ลองดู ทดสอบบน kitkat

<style name="AppTheme" parent="Theme.AppCompat">
  <item name="toolbarStyle">@style/AppThemeToolbar</item>
</style>

<style name="AppThemeToolbar" parent="Widget.AppCompat.Toolbar" >
  <item name="contentInsetStart">0dp</item>
</style>

1
คำตอบนี้ไม่ถูกต้อง: android: contentInsetStart ต้องการ API ระดับ 21 (ขั้นต่ำปัจจุบันคือ 14)
mr.boyfox

แต่สำนวนดีมาก! คุณต้องเขียนสไตล์แยกต่างหากสำหรับ api 21 และเวอร์ชันเก่า
mr.boyfox

นี่คือคำตอบที่ถูกต้องในการลบขอบด้านซ้ายหากคุณยังคงใช้แถบการทำงานเริ่มต้น
Tooroop

ใช้งานได้จริง! ด้วยเวอร์ชันล่าสุดของการสนับสนุน lib ฉันคิดว่าคุณไม่จำเป็นต้องประกาศแอตทริบิวต์ซ้ำสองครั้ง (ไม่จำเป็นต้องใช้ android: ones)
BoD

ฉันได้ค้นหาปัญหานี้และเมื่อฉันพบคำตอบของคุณฉันเห็นว่าฉันโหวตแล้ว! ขอบคุณสองครั้ง
user1732313

8

ไม่มีคำตอบอื่นใดที่เหมาะกับฉันดังนั้นฉันจึงดูรูปแบบ AppCompat v7 ที่แท้จริงซึ่งพบได้ที่นี่ที่นี่

หากคุณดูสไตล์ Base.Widget.AppCompat.ActionBar จะมี:

<item name="contentInsetStart">@dimen/abc_action_bar_content_inset_material</item>
<item name="contentInsetEnd">@dimen/abc_action_bar_content_inset_material</item>

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

<style name="ActionBar" parent="@style/Base.Widget.AppCompat.ActionBar">
        <item name="contentInsetStart">0dp</item>
        <item name="contentInsetEnd">0dp</item>
</style>

สิ่งนี้ได้ผลดีสำหรับฉันหวังว่ามันจะช่วยคนอื่นด้วย


ใช่ตามที่ระบุคำตอบที่เลือกคีย์คือแอตทริบิวต์ contentInsetStart และ contentInsetEnd ของ ActionBar / Toolbar สามารถกำหนดสไตล์ของคุณเองได้ แต่คุณสามารถตั้งค่าเป็น 0dp บนคุณลักษณะของ Toolbar ใน xml ของคุณได้
Stevie Kideckel

1

หลังจากเอาหัวไปชนกับจอมอนิเตอร์บ่อยครั้งสิ่งนี้ก็ได้ผลสำหรับฉัน

 Toolbar toolbar = (Toolbar) actionBar.getCustomView().getParent();
        toolbar.setContentInsetStartWithNavigation(0);
        toolbar.setContentInsetEndWithActions(0);
        toolbar.setContentInsetsAbsolute(0, 0);
        toolbar.setPadding(0, 0, 0, 0);

getCustomView (). getParent () คือสิ่งที่หลอกลวง


0

ฉันเพิ่งพบปัญหานี้ในวันนี้เช่นกันจากนั้นฉันก็พบว่าฉันมี res/values-v21/styles.xmlอยู่ในโครงการของฉันซึ่ง Android Studio สร้างขึ้นโดยอัตโนมัติและนั่นคือสาเหตุ

ทำไม?

เนื่องจากres/values-v21/styles.xmlเนื้อหาของฉันคือ:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="BaseAppTheme" parent="android:Theme.Material.Light">
    </style>
</resources>

และของฉันres/values/styles.xmlมีบางอย่างเช่น:

<style name="BaseAppTheme" parent="android:Theme.Holo.Light">
    <!-- Customize your theme here. -->
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:soundEffectsEnabled">false</item>
</style>

จากนั้นเมื่อฉันรันแอพของฉันบน Lollipop แอพนั้นres/values-v21/styles.xmlก็ถูกใช้งานและนั่นทำให้เกิดปัญหาแน่นอนที่ OP มี ดังนั้นฉันจึงมาแก้ไขง่ายๆคือการลบ:

    <style name="BaseAppTheme" parent="android:Theme.Material.Light">
    </style>

ใน res/values-v21/styles.xml


0

ตรงประเด็น:

 ActionBar actionBar = getSupportActionBar();
                actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
                actionBar.setCustomView(R.layout.actionbar_layout);
                Toolbar toolbar = (Toolbar) actionBar.getCustomView().getParent();
                    toolbar.setContentInsetsAbsolute(0, 0);
                    toolbar.setPadding(0, 0, 0, 0);

ตรวจสอบให้แน่ใจว่านำเข้าแถบเครื่องมือที่ถูกต้อง - android.support.v7.widget.Toolbar;


0

เขียนสองบรรทัดนี้เพิ่มเติมด้วยรหัสของคุณ

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