Chế độ xem tùy chỉnh Android Lollipop, AppCompat ActionBar không chiếm toàn bộ chiều rộng màn hình


97

Vì vậy, tôi vừa cập nhật cơ sở mã của mình lên Lollipop và tôi đang gặp sự cố với Thanh tác vụ. Tôi đang sử dụng AppCompat và ActionBarActivity, đồng thời thổi phồng chế độ xem tùy chỉnh. Có vẻ như chế độ xem tùy chỉnh không còn chiếm toàn bộ chiều rộng của màn hình, để lại một dải mỏng ở bên trái

Tòa nhà với 19 Nó từng trông như thế nào

Tòa nhà với 21 Bây giờ nó trông như thế nào

Đây là mã tôi đang sử dụng để thiết lập Thanh tác vụ. Ai có ý tưởng gì không?

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

Biên tập

Việc loại bỏ chế độ xem tùy chỉnh và thay đổi nền bây giờ chiếm toàn bộ chiều rộng. Vì vậy, vấn đề là, làm thế nào chúng ta có thể làm cho một CustomView chiếm toàn bộ chiều rộng của ActionBar?


Nếu bạn tạm thời nhận xét các phần của chế độ xem tùy chỉnh, nó có hoạt động tốt hơn không? Nếu không, tôi sẽ nghiêng về điều này có lẽ đến từ chủ đề của bạn.
CommonsWare

Tôi đã gỡ bỏ các giao diện tùy chỉnh, và thiết lập nền của nó như thể vẽ nền của ActionBar và nền không mất toàn bộ chiều rộng hiện nay
Stevie Kideckel

Bạn có thể xem xét hoạt động của mình trong Chế độ xem phân cấp, cả khi có và không có chế độ xem tùy chỉnh và xem liệu bạn có thể xác định quy tắc bố cục nào đang thay đổi do chế độ xem tùy chỉnh hay không. Có thể đây là một lỗi mới appcompat-v7.
CommonsWare

Đối với tôi đó là nơi dành riêng cho việc lên ImageView. Hãy thử tắt nó để bắt đầu.
Nikola Despotoski

1
Xin chào, có vẻ như đây là một giải pháp tốt để có chế độ xem tùy chỉnh chiếm toàn bộ chiều rộng. Tôi đã gặp phải tình trạng nó không mở rộng, ngay cả khi đã đặt trọng số bố cục. xem tại đây: stackoverflow.com/a/20794736/581574
ratana

Câu trả lời:


111

Có vẻ như điều này là do những thay đổi mới nhất ActionBartrong appcompat-v7bản cập nhật gần đây gây ra . Có vẻ như có những thay đổi đáng kể về cách bạn nên xử lý các thanh tác vụ.

Tôi phải đối mặt với vấn đề tương tự và sau khi đọc ActionBartài liệu , và đặc biệt là trích dẫn sau đây, tôi đã tìm ra giải pháp.

Bắt đầu với Android L (API cấp 21), thanh tác vụ có thể được đại diện bởi bất kỳ tiện ích con nào của Thanh công cụ trong bố cục ứng dụng. Ứng dụng có thể báo hiệu cho Hoạt động biết Thanh công cụ sẽ được coi là thanh tác vụ của Hoạt động. Các hoạt động sử dụng tính năng này nên sử dụng một trong các chủ đề .NoActionBar được cung cấp, đặt thuộc tính windowActionBar thành false hoặc không yêu cầu tính năng cửa sổ.

Theo cách tôi thấy, các AppCompatchủ đề đã được thay đổi và một mặt dường như phá vỡ một số thứ nhưng mặt khác cung cấp sự linh hoạt hơn nhiều. Tôi khuyên bạn nên làm theo các bước sau:

  1. Sử dụng .NoActionBarphong cách trong hoạt động của bạn như được mô tả trong phần trích dẫn ở trên
  2. Thêm a android.support.v7.widget.Toolbarvào bố cục Hoạt động của bạn
  3. Đặt app:contentInsetStart="0dp"thuộc tính. Đây là vấn đề chính với lợi nhuận mà bạn mô tả trong câu hỏi của mình
<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>

Thông thường, bạn nên làm điều đó trong một tệp bố cục riêng biệt và sử dụng includetrong bố cục hoạt động của mình, vì vậy bạn sẽ chỉ cần tùy chỉnh Thanh công cụ ở một nơi nếu được sử dụng trong nhiều hoạt động

<include layout="@layout/view_action_bar" />
  1. Sử dụng findViewByIdsetSupportActionBartrong Hoạt động của bạn 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. Khi bạn làm điều đó, tất cả các hành động được thêm vào onCreateOptionsMenusẽ được thêm vào thanh công cụ và nó sẽ được coi là thanh tác vụ hoạt động.
  2. Tùy chỉnh thêm Thanh công cụ như mong muốn (Thêm chế độ xem con, v.v.)

1
Tôi cố gắng để sử dụng thanh công cụ điều hướng ngăn kéo tuy nhiên tôi nhận được lỗiError inflating class fragment
Ahmed Nawaz

Tất cả mã liên quan được chia sẻ trên câu trả lời. Có vẻ như bạn nên bắt đầu một câu hỏi mới cho trường hợp của mình vì nó có vẻ là một vấn đề khác.
Muzikant

Cảm ơn. Tôi đã giải quyết vấn đề bằng cách thay thế thanh tác vụ bằng Thanh công cụ.
Ahmed Nawaz

9
Bạn không nên sử dụng tên gói rõ ràng trong khai báo vùng tên. Sử dụngxmlns:app="http://schemas.android.com/apk/res-auto"
Liminal

1
Không cần thiết setCustomView. Chỉ cần xây dựng một tập tin bố trí với công cụ mà bạn muốn bao gồm trong thanh công cụ của bạn (ví dụ thêm views con đến tập tin bố trí được mô tả trong phần 3 của câu trả lời)
Muzikant

51

Thay vì làm quá nhiều việc như Muzikant đã đề cập và thích câu trả lời này

    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

Bạn chỉ phải thêm hai dòng mã cuối cùng để giải quyết vấn đề của mình.

Tôi hy vọng điều này có thể giúp bạn và bất kỳ ai khác.

CẬP NHẬT: Sau khi thực hiện một số nghiên cứu về nó, tôi thấy rằng giải pháp này sẽ không hoạt động trong một số trường hợp. Khe hở bên trái (HOME hoặc QUAY LẠI) sẽ bị loại bỏ nhưng khe hở bên phải (MENU) sẽ vẫn như cũ. Dưới đây là giải pháp trong những trường hợp này.

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

Thêm bốn dòng này vào mã trên, để khoảng trống bên phải cũng được xóa khỏi thanh tác vụ hỗ trợ.


cảm ơn! cảm ơn! 2 dòng cuối cùng là những gì tôi đã tìm kiếm!
digitalmidges

Chúng ta thêm những dòng này vào đâu? Sau phần Thanh công cụ?
Zen

1
@summers có thêm chúng ngay lập tức sau mã thanh công cụ.
Amrut Bidri

31

Tôi nghĩ bạn cũng có thể làm điều đó trong các phong cách. thử cái này. đã thử nghiệm nó trên 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
Câu trả lời này là sai: android: contentInsetStart đòi hỏi mức API 21 (hiện tại là phút 14)
mr.boyfox

Nhưng, thành ngữ rất hay! Bạn cần viết kiểu riêng cho api 21 và các phiên bản cũ.
mr.boyfox

Đây là câu trả lời chính xác để loại bỏ lề trái nếu bạn vẫn đang sử dụng thanh tác vụ mặc định.
Tooroop

Điều này thực sự hoạt động! Với phiên bản mới nhất của hỗ trợ lib, tôi nghĩ bạn không cần phải khai báo các thuộc tính hai lần (android: những cái là không cần thiết).
BoD

Tôi đã tìm kiếm vấn đề này và khi tôi tìm thấy câu trả lời của bạn, tôi thấy rằng tôi đã ủng hộ nó! Vì vậy, cảm ơn hai lần.
user1732313

8

Không có câu trả lời nào khác phù hợp với tôi, vì vậy tôi đã xem xét các kiểu AppCompat v7 thực tế, được tìm thấy tại đây .

Nếu bạn nhìn vào kiểu Base.Widget.AppCompat.ActionBar, nó có:

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

Vì vậy, rõ ràng là chúng ta chỉ cần ghi đè các thuộc tính đó trong kiểu thanh tác vụ của riêng mình:

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

Điều này rất hiệu quả đối với tôi, hy vọng nó cũng giúp ích cho những người khác.


Đúng, như câu trả lời đã chọn nêu rõ, chìa khóa là thuộc tính contentInsetStart và contentInsetEnd của ActionBar / Toolbar. Đó là hợp lệ để xác định phong cách riêng của bạn, nhưng bạn cũng có thể đặt chúng vào 0dp về các thuộc tính của Thanh công cụ trong xml của bạn
Stevie Kideckel

1

Sau nhiều lần đập đầu vào màn hình, điều này đã hiệu quả với tôi

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

GetCustomView (). GetParent () chính là thủ thuật


0

Tôi cũng vừa gặp phải sự cố này hôm nay, sau đó tôi phát hiện ra mình đang gặp sự cố res/values-v21/styles.xmlbên trong dự án được tạo tự động bởi Android Studio và đó là nguyên nhân.

Tại sao?

Bởi vì res/values-v21/styles.xmlnội dung của tôi là:

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

Và của tôi res/values/styles.xmlchứa một cái gì đó như:

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

Sau đó, khi tôi chạy ứng dụng của mình trên Lollipop, ứng dụng res/values-v21/styles.xmlđã được sử dụng và gây ra vấn đề chính xác mà OP gặp phải. Vì vậy, tôi đã đến một bản sửa lỗi đơn giản là chỉ xóa:

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

trong res/values-v21/styles.xml


0

đến điểm:

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

đảm bảo nhập đúng thanh công cụ - android.support.v7.widget.Toolbar;


0

Viết hai dòng này cùng với mã của bạn

Toolbar toolbar=(Toolbar)viewActionBar.getParent();
toolbar.setContentInsetsAbsolute(0,0);
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.