Câu hỏi Ngăn điều hướng bán trong suốt trên thanh trạng thái không hoạt động


Tôi đang làm việc trên dự án Android và tôi đang triển khai Ngăn điều hướng. Tôi đang đọc qua Vật liệu thiết kế Spec và Danh sách kiểm tra thiết kế material design.
Thông số kỹ thuật nói rằng cửa sổ trượt ra phải nổi lên trên mọi thứ khác bao gồm thanh trạng thái và bán trong suốt trên thanh trạng thái.

Bảng điều hướng của tôi nằm trên thanh trạng thái nhưng nó không có bất kỳ sự minh bạch nào. Tôi đã theo mã từ đây VÌ THẾ đăng như được đề xuất trong trang blog của nhà phát triển Google, liên kết ở trên Làm thế nào để sử dụng DrawerLayout để hiển thị trên ActionBar / Thanh công cụ và dưới thanh trạng thái?.

Dưới đây là bố cục XML của tôi

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/my_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <android.support.v7.widget.Toolbar
            android:id="@+id/my_awesome_toolbar"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:minHeight="?attr/actionBarSize"
            android:background="@color/appPrimaryColour" />
    </LinearLayout>
    <LinearLayout android:id="@+id/linearLayout"
        android:layout_width="304dp"
        android:layout_height="match_parent"
        android:layout_gravity="left|start"
        android:fitsSystemWindows="true"
        android:background="#ffffff">
        <ListView android:id="@+id/left_drawer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:choiceMode="singleChoice"></ListView>
    </LinearLayout>
</android.support.v4.widget.DrawerLayout>

Dưới đây là chủ đề ứng dụng của tôi

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/appPrimaryColour</item>
        <item name="colorPrimaryDark">@color/appPrimaryColourDark</item>
        <item name="colorAccent">@color/appPrimaryColour</item>
        <item name="windowActionBar">false</item>
        <item name="windowActionModeOverlay">true</item>

    </style>

Dưới đây là chủ đề ứng dụng v21 của tôi

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/appPrimaryColour</item>
    <item name="colorPrimaryDark">@color/appPrimaryColourDark</item>
    <item name="colorAccent">@color/appPrimaryColour</item>
    <item name="windowActionBar">false</item>
    <item name="windowActionModeOverlay">true</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

Dưới đây là phương pháp onCreate của tôi

protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
    setSupportActionBar(toolbar);

    mDrawerLayout = (DrawerLayout)findViewById(R.id.my_drawer_layout);
    mDrawerList = (ListView)findViewById(R.id.left_drawer);

    mDrawerLayout.setStatusBarBackgroundColor(
        getResources().getColor(R.color.appPrimaryColourDark));

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    {
        LinearLayout linearLayout = 
            (LinearLayout)findViewById(R.id.linearLayout);
        linearLayout.setElevation(30);
    }

Dưới đây là một ảnh chụp màn hình ngăn điều hướng của tôi hiển thị trên cùng không phải là bán trong suốt

Screenshot showing non transparent over the status bar


76
2017-11-04 21:23


gốc


Đăng ảnh chụp màn hình kết quả của bạn. - Alok Nair
@AlokNair Tôi đã cập nhật câu hỏi của mình để bao gồm ảnh chụp màn hình - Boardy
@Boardy bạn đã quản lý để có được nó để làm việc? - dev.mi
Câu hỏi này đã giải quyết được vấn đề của tôi :-) - Tinashe
Không thể đặt hiệu ứng Trong suốt trong thanh trạng thái.Pl thoát khỏi nó. - Ronak Gadhia


Các câu trả lời:


Nền thanh trạng thái của bạn có màu trắng, nền của ngăn kéo của bạn LinearLayout. Tại sao? Bạn là cài đặt fitsSystemWindows="true" cho bạn DrawerLayout và LinearLayout bên trong nó. Điều này khiến bạn LinearLayout mở rộng phía sau thanh trạng thái (trong suốt). Do đó, làm nền cho phần ngăn kéo của thanh trạng thái trắng.

enter image description here
Nếu bạn không muốn ngăn kéo mở rộng phía sau thanh trạng thái (muốn có nền nửa trong suốt cho toàn bộ thanh trạng thái), bạn có thể làm hai việc:

1) Bạn có thể chỉ cần xóa mọi giá trị nền khỏi LinearLayout và tô màu nền cho nội dung của bạn bên trong nó. Hoặc là

2) Bạn có thể xóa fitsSystemWindows="true" từ của bạn LinearLayout. Tôi nghĩ đây là một cách tiếp cận hợp lý và sạch hơn. Bạn cũng sẽ tránh có một bóng được đúc dưới thanh trạng thái, nơi ngăn kéo điều hướng của bạn không mở rộng.

enter image description here
Nếu bạn muốn ngăn kéo của mình mở rộng ra sau thanh trạng thái và có lớp phủ có kích thước thanh trạng thái bán trong suốt, bạn có thể sử dụng ScrimInsetFrameLayout dưới dạng vùng chứa cho nội dung ngăn kéo của bạn (ListView) và đặt nền thanh trạng thái bằng app:insetForeground="#4000". Tất nhiên, bạn có thể thay đổi #4000 bất cứ điều gì bạn muốn. Đừng quên giữ fitsSystemWindows="true" đây!

Hoặc nếu bạn không muốn che phủ nội dung của mình và chỉ hiển thị màu đồng nhất, bạn có thể chỉ thiết lập nền của LinearLayout bất cứ điều gì bạn muốn. Đừng quên để thiết lập nền của nội dung của bạn một cách riêng biệt mặc dù!

CHỈNH SỬA: Bạn không còn cần phải đối phó với bất kỳ điều này. Xin vui lòng xem Thư viện hỗ trợ thiết kế cho một lần dễ dàng hơn Navigation Drawer / Xem thực hiện.


95
2017-11-14 14:27



Cảm ơn bạn đã giúp đỡ. Xin lỗi vì sự chậm trễ trong việc trở lại, được điên bận rộn. Tôi đã thiết lập một tiền thưởng khác để thưởng cho câu trả lời của bạn như ban đầu tôi đã thiết lập nhưng nó đã hoàn thành trước khi tôi có thời gian để thực hiện các đề xuất của bạn. Tôi đã phải chờ đợi 23 giờ không may vì vậy tôi sẽ thêm nó ngay khi tôi có thể - Boardy
Thận trọng! Với các tùy chọn 1 hoặc 2, hãy chắc chắn để xem overdraws của bạn (bạn có thể kiểm tra chúng trong các tùy chọn dev trong cài đặt điện thoại). Khi tôi chỉ thiết lập nền của nội dung bên trong tất cả mọi thứ phía sau ngăn kéo cũng đã được rút ra. Nếu không câu trả lời tuyệt vời, chắc chắn đã cứu tôi một thời gian :) - Daiwik Daarun
Bạn có thể giải thích chúng ta cần sử dụng giải pháp nào khi sử dụng thư viện hỗ trợ thiết kế? Tôi đang gặp một số vấn đề, ngay cả với câu trả lời của Chris Banes. - mDroidd


Tất cả những gì bạn cần làm là sử dụng một số màu trong suốt cho thanh trạng thái. Thêm những dòng này vào chủ đề v21 của bạn:

<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@color/desired_color</item>

Đừng quên rằng color (tài nguyên) phải luôn ở định dạng #AARRGGBB. Điều này có nghĩa là màu sắc cũng sẽ bao gồm giá trị alpha.


29
2017-11-05 20:52



Thnks nhưng tôi đã có nó trong V21 của tôi - Boardy
Bạn là người đàn ông, nhưng ... Bạn có thể cho tôi biết tại sao điều này chỉ hoạt động trong Hoạt động có ngăn kéo? Những người khác, những người không có, họ hiển thị thanh trạng thái màu xám. - Joaquin Iurchuk


Tại sao không sử dụng một cái gì đó tương tự như thế này?

<android.support.v4.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >

    <FrameLayout
            android:id="@+id/content_frame"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    <ListView
            android:id="@+id/left_drawer"
            android:layout_width="240dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:choiceMode="singleChoice"
            android:divider="@android:color/transparent"
            android:dividerHeight="0dp"
            android:background="#80111111"/>
</android.support.v4.widget.DrawerLayout>

Đoạn mã trên sử dụng tài nguyên alpha trong android:background để có thể hiển thị độ trong suốt trong thanh hành động.

Có nhiều cách khác để làm điều này thông qua mã, như các câu trả lời khác cho thấy. Câu trả lời của tôi ở trên, có cần thiết trong tệp bố cục xml không, mà theo ý kiến ​​của tôi thì có thể dễ dàng chỉnh sửa.


15
2017-11-11 12:27



Tại sao không, nhưng nó không rõ ràng những gì bạn đang thay đổi và làm thế nào điều này là trả lời các câu hỏi. - rds
đặt dải phân cách thành mã alpha trong suốt và được sử dụng trong màu nền - dev.mi


Bạn cần bọc bố cục ngăn điều hướng bên trong ScrimLayout.

A ScrimLayout về cơ bản vẽ hình chữ nhật nửa trong suốt trên bố cục ngăn điều hướng của bạn. Để lấy kích thước của inset, chỉ cần ghi đè fitSystemWindows trong của bạn ScrimLayout.

@Override
protected boolean fitSystemWindows(Rect insets) {
    mInsets = new Rect(insets);
    return true;
}

Ghi đè sau onDraw để vẽ hình chữ nhật nửa trong suốt.

An thí dụ triển khai có thể được tìm thấy trong nguồn ứng dụng Google IO. Đây bạn có thể thấy nó được sử dụng như thế nào trong layout xml.


8
2017-11-14 09:43





Nếu bạn muốn bảng điều hướng nằm trên thanh trạng thái và bán trong suốt trên thanh trạng thái. Nguồn ứng dụng Android I / O của Google cung cấp một giải pháp tốt (APK trong Cửa hàng Play không được cập nhật lên phiên bản kéo dài)

Đầu tiên bạn cần ScrimInsetFrameLayout

/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* A layout that draws something in the insets passed to {@link #fitSystemWindows(Rect)}, i.e. the area above UI chrome
* (status and navigation bars, overlay action bars).
*/
public class ScrimInsetsFrameLayout extends FrameLayout {
    private Drawable mInsetForeground;

    private Rect mInsets;
    private Rect mTempRect = new Rect();
    private OnInsetsCallback mOnInsetsCallback;

    public ScrimInsetsFrameLayout(Context context) {
        super(context);
        init(context, null, 0);
    }

    public ScrimInsetsFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public ScrimInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        final TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.ScrimInsetsView, defStyle, 0);
        if (a == null) {
            return;
        }
        mInsetForeground = a.getDrawable(R.styleable.ScrimInsetsView_insetForeground);
        a.recycle();

        setWillNotDraw(true);
    }

    @Override
    protected boolean fitSystemWindows(Rect insets) {
        mInsets = new Rect(insets);
        setWillNotDraw(mInsetForeground == null);
        ViewCompat.postInvalidateOnAnimation(this);
        if (mOnInsetsCallback != null) {
            mOnInsetsCallback.onInsetsChanged(insets);
        }
        return true; // consume insets
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        int width = getWidth();
        int height = getHeight();
        if (mInsets != null && mInsetForeground != null) {
            int sc = canvas.save();
            canvas.translate(getScrollX(), getScrollY());

            // Top
            mTempRect.set(0, 0, width, mInsets.top);
            mInsetForeground.setBounds(mTempRect);
            mInsetForeground.draw(canvas);

            // Bottom
            mTempRect.set(0, height - mInsets.bottom, width, height);
            mInsetForeground.setBounds(mTempRect);
            mInsetForeground.draw(canvas);

            // Left
            mTempRect.set(0, mInsets.top, mInsets.left, height - mInsets.bottom);
            mInsetForeground.setBounds(mTempRect);
            mInsetForeground.draw(canvas);

            // Right
            mTempRect.set(width - mInsets.right, mInsets.top, width, height - mInsets.bottom);
            mInsetForeground.setBounds(mTempRect);
            mInsetForeground.draw(canvas);

            canvas.restoreToCount(sc);
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (mInsetForeground != null) {
            mInsetForeground.setCallback(this);
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mInsetForeground != null) {
            mInsetForeground.setCallback(null);
        }
    }

    /**
     * Allows the calling container to specify a callback for custom processing when insets change (i.e. when
     * {@link #fitSystemWindows(Rect)} is called. This is useful for setting padding on UI elements based on
     * UI chrome insets (e.g. a Google Map or a ListView). When using with ListView or GridView, remember to set
     * clipToPadding to false.
     */
    public void setOnInsetsCallback(OnInsetsCallback onInsetsCallback) {
        mOnInsetsCallback = onInsetsCallback;
    }

    public static interface OnInsetsCallback {
        public void onInsetsChanged(Rect insets);
    }
}

Sau đó, trong bố cục XML của bạn, hãy thay đổi phần này

<LinearLayout android:id="@+id/linearLayout"
    android:layout_width="304dp"
    android:layout_height="match_parent"
    android:layout_gravity="left|start"
    android:fitsSystemWindows="true"
    android:background="#ffffff">
    <ListView android:id="@+id/left_drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:choiceMode="singleChoice"></ListView>
</LinearLayout>

Thay đổi LinearLayout thành ScrimInsetFrameLayout của bạn như thế này

<com.boardy.util.ScrimInsetFrameLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/linearLayout"
    android:layout_width="304dp"
    android:layout_height="match_parent"
    android:layout_gravity="left|start"
    android:fitsSystemWindows="true"
    app:insetForeground="#4000">
    <ListView android:id="@+id/left_drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:choiceMode="singleChoice"></ListView>
</com.boardy.util.ScrimInsetFrameLayout>

6
2017-11-15 08:49



HI, cảm ơn cho câu trả lời .. Tôi không thể tìm thấy rằng, từ nơi chúng tôi nhận được OnInsetsCallback ... Cảm ơn trước. - Ashok Chakravarthi
bạn có thể đặt ScrimInsetsView_insetForeground thuộc tính. - reegan29
Sử dụng android.support.design.internal.ScrimInsetsFrameLayout từ thư viện hỗ trợ - Roman
@Roman Sử dụng ScrimInsetsFrameLayout từ thư viện hỗ trợ đã giải quyết vấn đề cho tôi ở đây. Cảm ơn rất nhiều. - Aritra Roy


Tôi đã có một tính năng tương tự để thực hiện trong dự án của tôi. Và để làm cho ngăn kéo của tôi trong suốt, tôi chỉ sử dụng minh bạch cho hex màu sắc. Sử dụng 6 chữ số thập phân, bạn có 2 chữ số thập phân cho mỗi giá trị của màu đỏ, xanh lục và xanh lam tương ứng. nhưng nếu bạn đặt hai chữ số bổ sung (8 chữ số thập phân), vì vậy bạn có ARGB (hai chữ số cho giá trị alpha) (Nhìn đây).

Dưới đây là Giá trị Độ mờ của Hex: cho 2 chữ số bổ sung

100% — FF
95% — F2
90% — E6
85% — D9
80% — CC
75% — BF
70% — B3
65% — A6
60% — 99
55% — 8C
50% — 80
45% — 73
40% — 66
35% — 59
30% — 4D
25% — 40
20% — 33
15% — 26
10% — 1A
5% — 0D
0% — 00

Ví dụ: nếu bạn có màu hex (# 111111) chỉ cần đặt một trong các giá trị độ mờ để có độ trong suốt. như thế này: (# 11111100)

Ngăn kéo của tôi không bao gồm thanh tác vụ (giống như của bạn) nhưng độ trong suốt cũng có thể được áp dụng trong những trường hợp này. Đây là mã của tôi:

     <ListView
          android:id="@+id/left_drawer"
          android:layout_width="240dp"
          android:layout_height="match_parent"
          android:layout_gravity="start"
          android:background="#11111100"
          android:choiceMode="singleChoice"
          android:divider="@android:color/transparent"
          android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>

Và đây là một bài báo có thể giúp bạn hiểu mã alpha bằng màu hex.


4
2017-11-14 13:24





Tất cả các câu trả lời được đề cập ở đây quá cũ và dài. Giải pháp tốt nhất và ngắn gọn phù hợp với Navigationview mới nhất là

@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
    super.onDrawerSlide(drawerView, slideOffset);

    try {
        //int currentapiVersion = android.os.Build.VERSION.SDK_INT;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
            // Do something for lollipop and above versions

        Window window = getWindow();

        // clear FLAG_TRANSLUCENT_STATUS flag:
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        // add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

        // finally change the color to any color with transparency

         window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDarktrans));}

    } catch (Exception e) {

        Crashlytics.logException(e);

    }
}

điều này sẽ thay đổi màu thanh trạng thái thành màu trong suốt khi bạn mở ngăn

Bây giờ khi bạn đóng ngăn kéo bạn cần phải thay đổi màu sắc thanh trạng thái một lần nữa để dark.So bạn có thể làm điều đó theo cách này.

@Override
public void onDrawerClosed(View drawerView) {
   super.onDrawerClosed(drawerView);
    try {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            // Do something for lollipop and above versions

            Window window = getWindow();

            // clear FLAG_TRANSLUCENT_STATUS flag:
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

            // add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

            // finally change the color again to dark
            window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));
        }
    } catch (Exception e) {
        Crashlytics.logException(e);
    }
}

và sau đó trong bố cục chính, thêm một dòng duy nhất

            android:fitsSystemWindows="true"

và bố cục ngăn kéo của bạn sẽ trông giống như

            <android.support.v4.widget.DrawerLayout     
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/drawer_layout"
            android:fitsSystemWindows="true"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

và chế độ xem điều hướng của bạn sẽ trông giống như

    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/navigation_header"
        app:menu="@menu/drawer"
        />

Tôi đã thử nghiệm nó và làm việc đầy đủ của nó.Hope nó giúp somebody.This có thể không phải là cách tiếp cận tốt nhất nhưng nó hoạt động trơn tru và rất đơn giản để thực hiện. Đánh dấu nó nếu nó giúp.Happy mã :)


2
2018-02-12 12:28



Không làm việc. :( - Aks4125
Cảm ơn! Điều này đã cứu tôi rất nhiều thời gian. Nó hoạt động hoàn hảo với NavigationView mới nhất. Đối với bất kỳ ai không thể làm điều này để làm việc, hãy chắc chắn rằng bạn đã chọn một màu sắc với một số minh bạch cho "colorPrimaryDarktrans", nếu không bạn không thể thấy bất kỳ thay đổi nào cả. - Rui
Hoạt động hoàn hảo, nhược điểm duy nhất là thanh trạng thái 'nhấp nháy' khi onDrawerClosed được gọi nhưng nếu bạn đặt màu trong suốt colorPrimaryDarktrans thành # 05000000 thì gần như không đáng kể - Kirill Karmazin
@KirillKarmazin upvote nếu nó đã giúp :) - Harry Sharma