Android沉浸式設計

鋸齒流沙發表於2017-12-26

簡介

一個好的APP設計能夠增強使用者體驗,留住使用者,在UI上更加美觀,給使用者更加舒服的體驗。而沉浸式設計能夠使APP整體UI設計呈現一體化,使APP介面圖片延伸到狀態列, 應用本身沉浸於狀態列。

沉浸式設計就是讓人專注於當前的目標(有設計者營造)情境下感到愉悅和滿足,而忘記真實世界的情景的設計方法。

Android沉浸式設計

對於Android5.0以後的API,已經自動實現了沉浸式效果了,狀態列會跟隨你的主題colorPrimaryDark屬性。5.0以後的API有三種方式可以設定沉浸式設計:

1)所以通過設定主題的樣式即可達到沉浸式設計。

沉浸式設計

上圖中在styles.xml指定主題樣式即可。

2)在樣式中設定android:statusBarColor

沉浸式設計

設定android:statusBarColor需要在API21(也就是5.0)以上才能支援。

3)通過程式碼設定

沉浸式設計

注意:這種方法設定需要放在setContentView方法之前設定,而且同樣是需要在5.0以後的API才能設定。

沉浸式設計

Android5.0以後的版本使用沉浸式設計固然簡單,但是唯一的缺點就是不支援低於5.0的版本,我們知道Android的絕大部分手機使用者的版本還是在5.0以下的,這就需要我們做相容開發了。

做沉浸式設計,目前最低只能相容到4.4版本,低於Android4.4版本,是不可能做到沉浸式設計的,因為Android4.4新出的API,可以設定狀態列為透明狀態,低於該版本就不能設定狀態列為透明狀態,因此低於Android4.4版本不能做到沉浸式設計。

沉浸式相容到Android4.4版本(一)

能夠做到相容到Android4.4版本的,需要我們做一些特殊處理,就是利用Android4.4版本新出的API,設定狀態列為透明狀態。

兩種方式可以設定狀態列為透明狀態:

1)在屬性樣式裡面設定

true 一般我們不會推薦使用這種方式,因為相容性不好。

2)在程式碼裡設定

沉浸式設計

注意:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);需要在setContentView方法之前設定。

下面給出該例項程式碼:

Activity:

public class TranslucentActivity01 extends AppCompatActivity {

    private Toolbar mToolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //設定全屏
        //getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        //設定透明狀態列
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        setContentView(R.layout.activity_translucent01);
        mToolbar = (Toolbar)this.findViewById(R.id.tool_bar);
        setSupportActionBar(mToolbar);
    }
}
複製程式碼

xml佈局:

<RelativeLayout
    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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.main.translucent.TranslucentActivity01">

    <com.main.toolbar.MyScrollView
        android:id="@+id/scrollView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#ffffffff"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:paddingTop="?attr/actionBarSize">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical">

            <Button
                android:id="@+id/button1"
                style="?android:attr/buttonStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:text="Button0"/>

            <Button
                style="?android:attr/buttonStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:text="Button1"/>

            <Button
                style="?android:attr/buttonStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:text="Button2"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"/>
        </LinearLayout>
    </com.main.toolbar.MyScrollView>

    <android.support.v7.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:fitsSystemWindows="true">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="標題"/>
    </android.support.v7.widget.Toolbar>

</RelativeLayout>
複製程式碼

注意:

Toolbar需要新增android:fitsSystemWindows="true",否則APP的內容頂到最上面去了,即狀態列會遮擋一部分介面,該屬性的作用:設定佈局時,是否考慮當前系統視窗的佈局,如果為true就會調整整個系統視窗,佈局(包括狀態列的view)以適應你的佈局。

執行效果

沉浸式設計

沉浸式相容到Android4.4版本(二)

上面的沉浸式設計的方法已經可以相容到Android4.4版本,但是還是有bug,當裡面有ScrollView並且ScrollView裡面有Edittext的時候,就會出現軟鍵盤一彈起就會把toolbar拉下來。

在這裡講解第二種相容方法,並且解決該bug:

1)同樣需要在程式碼種設定狀態列的透明狀態。

public class TranslucentActivity02 extends AppCompatActivity {

    private Toolbar mToolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //設定透明狀態列
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        setContentView(R.layout.activity_translucent);
        mToolbar = (Toolbar)this.findViewById(R.id.tool_bar);
        setSupportActionBar(mToolbar);
    }
}
複製程式碼

2)給佈局最外層容器設定android:fitsSystemWindows="true"屬性,並且給最外層容器(也可以修改android:windowBackground顏色)設定狀態列想要的顏色。

沉浸式設計

3)內容佈局需要包裹一層並且設定背景顏色即可。

沉浸式設計

下面給出整個xml佈局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:background="?attr/colorPrimary"
    tools:context="com.main.translucent.TranslucentActivity02">

    <com.main.toolbar.MyScrollView
        android:background="#ffffffff"
        android:id="@+id/scrollView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:paddingTop="?attr/actionBarSize">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical">

            <Button
                android:id="@+id/button1"
                style="?android:attr/buttonStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:text="Button0"/>

            <Button
                style="?android:attr/buttonStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:text="Button1"/>

            <Button
                style="?android:attr/buttonStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:text="Button2"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"/>
        </LinearLayout>
    </com.main.toolbar.MyScrollView>

    <android.support.v7.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:title="沉浸式03">
    </android.support.v7.widget.Toolbar>

</RelativeLayout>

複製程式碼

得到的沉浸式效果圖:

沉浸式設計

沉浸式相容到Android4.4版本(三)

以上的方法都能夠相容到Android4.4版本,實現沉浸式設計,當然還有另外的方案可以實現沉浸式,那就是通過修改Toolbar的高度。

1)修改狀態列為透明狀態;

getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); setContentView(R.layout.activity_translucent03);

2)不需要給Toolbar設定android:fitsSystemWindows="true";

<android.support.v7.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary">
        <TextView
            android:layout_width="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_height="wrap_content"
            android:text="標題"/>
    </android.support.v7.widget.Toolbar>
複製程式碼

3)通過反射獲取得到狀態列高度。

沉浸式設計

通過原始碼我們知道狀態列執行的類:android.R.dimen,其屬性為status_bar_height

因此我們通過反射可以獲取得到狀態列高度。

private int getStatusBarHeight(Context context){
        // 反射執行的類:android.R.dimen.status_bar_height.
        int mStatusHeight = -1;
        try {
            Class<?> mClass =Class.forName("com.android.internal.R$dimen");
            Object object = mClass.newInstance();
            String heightStr = mClass.getField("status_bar_height").get(object).toString();
            int height = Integer.valueOf(heightStr);
            //dp--->px
            mStatusHeight = context.getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mStatusHeight;
    }
複製程式碼

4)修改Toolbar的PaddingTop

沉浸式設計

下面是該例項的程式碼:

Activity:

public class TranslucentActivity03 extends AppCompatActivity {

    private Toolbar mToolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        setContentView(R.layout.activity_translucent03);

        mToolbar = (Toolbar) this.findViewById(R.id.tool_bar);
        mToolbar.setPadding(
                mToolbar.getPaddingLeft(),
                mToolbar.getPaddingTop() + getStatusBarHeight(this),
                mToolbar.getPaddingRight(),
                mToolbar.getPaddingBottom());

    }


    /**
     * 獲取狀態列高度
     *
     * @param context
     * @return
     */
    private int getStatusBarHeight(Context context) {
        // 反射執行的類:android.R.dimen.status_bar_height.
        int mStatusHeight = -1;
        try {
            Class<?> mClass = Class.forName("com.android.internal.R$dimen");
            Object object = mClass.newInstance();
            String heightStr = mClass.getField("status_bar_height").get(object).toString();
            int height = Integer.valueOf(heightStr);
            //dp--->px
            mStatusHeight = context.getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mStatusHeight;
    }

}
複製程式碼

xml佈局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.main.translucent.TranslucentActivity03">
    <com.main.toolbar.MyScrollView
        android:background="#ffffffff"
        android:id="@+id/scrollView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:paddingTop="?attr/actionBarSize">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical">

            <Button
                android:id="@+id/button1"
                style="?android:attr/buttonStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:text="Button0"/>

            <Button
                style="?android:attr/buttonStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:text="Button1"/>

            <Button
                style="?android:attr/buttonStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:text="Button2"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"/>
        </LinearLayout>
    </com.main.toolbar.MyScrollView>

    <android.support.v7.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary">
        <TextView
            android:layout_width="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_height="wrap_content"
            android:text="標題"/>
    </android.support.v7.widget.Toolbar>

</RelativeLayout>

複製程式碼

執行效果圖:

沉浸式設計

沉浸式相容到Android4.4版本(四)

除了以上的實現方式,當然我們可以使用第三方來實現Android的沉浸式設計。這裡例項採用的是SystemTint第三方。

1)在app下的build.gradle新增依賴

沉浸式設計

2)新建BaseActivity,統一處理,新的Activity只需要繼承BaseActivity即可。

public class BaseActivity extends AppCompatActivity {

    private SystemBarTintManager tintManager;

    private boolean mIsOpenBar = true;
    private int color = 0xff3F51B5;//預設顏色

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initTint();
    }

    /**
     * 是否需要實現沉浸式
     * @param openBar
     */
    public void setOpenBar(boolean openBar) {
        mIsOpenBar = openBar;
    }

    /**
     * 設定沉浸式顏色
     * @param color
     */
    public void setColor(int color) {
        this.color = color;
        if (mIsOpenBar){
            setTintBar(color);
        }
    }

    /**
     * 初始化
     */
    private void initTint() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
        // create our manager instance after the content view is set
        tintManager = new SystemBarTintManager(this);
        // enable status bar tint
        tintManager.setStatusBarTintEnabled(true);
        // enable navigation bar tint
        tintManager.setNavigationBarTintEnabled(true);

        if (mIsOpenBar){
            setTintBar(color);
        }
    }

    /**
     * 設定沉浸式
     * @param color
     */
    private void setTintBar(int color) {
        // set a custom tint color for all system bars
        tintManager.setTintColor(color);
        // set a custom navigation bar resource
        tintManager.setNavigationBarTintColor(color);
        // set a custom status bar drawable
        tintManager.setStatusBarTintColor(color);
//        tintManager.setStatusBarTintResource(R.color.colorAccent);
    }
}

複製程式碼

初始化SystemTint和設定狀態列顏色等等在BaseActivity處理即可。具體可檢視註釋。

3)新Activity繼承BaseAcitivity,通過setColor來設定狀態列顏色即可。

public class TranslucentActivity04 extends BaseActivity {

    private Toolbar mToolbar;
    //需要在根佈局加入一下的
//    android:clipToPadding="false"
//    android:fitsSystemWindows="true"

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_translucent04);
        mToolbar = (Toolbar) this.findViewById(R.id.tool_bar);
        this.findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                setColor(0xffffD306);
                mToolbar.setBackgroundColor(0xffffD306);
            }
        });
    }
}
複製程式碼

4)xml佈局的根佈局需要新增

android:clipToPadding="false"和android:fitsSystemWindows="true"屬性

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:fitsSystemWindows="true"
    tools:context="com.main.translucent.TranslucentActivity04">

    <com.main.toolbar.MyScrollView
        android:id="@+id/scrollView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#ffffffff"
        android:paddingTop="?attr/actionBarSize">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical">

            <Button
                android:id="@+id/button1"
                style="?android:attr/buttonStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:text="Button0"/>

            <Button
                style="?android:attr/buttonStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:text="Button1"/>

            <Button
                style="?android:attr/buttonStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:text="Button2"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"/>
        </LinearLayout>
    </com.main.toolbar.MyScrollView>

    <android.support.v7.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="標題"/>
    </android.support.v7.widget.Toolbar>

</RelativeLayout>

複製程式碼

執行效果圖:

沉浸式設計

通過以上的學習,我們可以做出Android的沉浸式設計效果,並且能夠相容到Android4.4版本,給使用者精美的UI效果。

相關文章