基於ToolBar等MD相關控件實現的沉浸式聯動效果

前言


Drawing

提前下班了!!!

綜述

先來看一下最終的效果圖


這裏寫圖片描述

功能點

1、CoordinatorLayout、AppBarLayout、CollapsingToolbarLayout、Toolbar、TabLayout、ViewPager聯動使用

2、聯動過程中保持沉浸式狀態欄效果

3、ToolBar的基本使用,如自定義居中的title, Toolbar和Menu的結合使用,自定義溢出菜單樣式
期間會涉及控件各種屬性的設置,這個比較細碎

中間遇到一個問題,就是給menu,navigation等設置圖片時,圖片被拉伸(原因:把基於1280*720的切圖放在了drawable文件夾下了,應該放在drawable-xhdpi)

4、解決應用啓動白屏的問題

各個突破

設置ToolBar

  private void setupToolbar() {
        toolbar = (Toolbar) findViewById(R.id.toolbar);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            int statusBarHeight = getStatusBarHeight(this);
            FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) toolbar.getLayoutParams();
            layoutParams.topMargin = statusBarHeight;
        }

        appbar = (AppBarLayout) findViewById(R.id.appbar);

        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true); //使用系統自帶的返回按鈕
        getSupportActionBar().setHomeAsUpIndicator(R.drawable.icon_back_normal);//替換系統自帶的返回圖標

        toolbar.setOnMenuItemClickListener(onMenuItemClick);
    }

    private Toolbar.OnMenuItemClickListener onMenuItemClick = new Toolbar.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem menuItem) {
            switch (menuItem.getItemId()) {
                case R.id.action_share:
                    Toast.makeText(MainActivity.this, "收藏", Toast.LENGTH_SHORT).show();
                    //其餘的省略
                    break;
            }

            return true;
        }
    };

    private void setupCollapsingToolbar() {
        collapseToolbar = (CollapsingToolbarLayout) findViewById(
                R.id.collapse_toolbar);

        collapseToolbar.setTitleEnabled(false);
    }

OnOffsetChangedListener聯動顯示

實現AppBarLayout的OnOffsetChangedListener

   @Override
    protected void onResume() {
        super.onResume();
        appbar.addOnOffsetChangedListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        appbar.removeOnOffsetChangedListener(this);
    }
@Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
        if (lastPosition == verticalOffset) {
            return;
        }
        lastPosition = verticalOffset;
        if (verticalOffset == 0) {
            getSupportActionBar().setTitle("");
            btnRight.setVisibility(View.GONE);
            viewTitle.setPadding(0, 6, 0, 0);
            toolbarTitle.setText("");
            return;
        } else if (verticalOffset < -dip2px(this, 110)) {
            viewTitle.setPadding(0, 0, 0, 0);
            getSupportActionBar().setTitle("");
            btnRight.setVisibility(View.GONE);
            toolbarTitle.setText("");
        } else {
            viewTitle.setPadding(0, 6, 0, 0);
            getSupportActionBar().setTitle("");
            toolbarTitle.setText("軍團再臨");
            btnRight.setVisibility(View.VISIBLE);
        }
    }

自定義溢出菜單樣式

定義樣式

  <!--溢出菜單樣式 -->
    <style name="OverflowMenuStyle" parent="@style/Widget.AppCompat.Light.PopupMenu.Overflow">
        <item name="overlapAnchor">false</item>
        <item name="android:dropDownWidth">wrap_content</item>
        <item name="android:paddingRight">5dp</item>
        <item name="android:popupBackground">@color/dcdcdc</item>
        <item name="android:dropDownVerticalOffset">4dip</item>
        <item name="android:dropDownHorizontalOffset">-4dip</item>
    </style>

添加到application theme中(前兩個屬性是爲了解決啓動白屏的問題)

Android 啓動白屏或者黑屏閃現解決

  <style name="Theme.AppStartLoadTranslucent" parent="AppTheme">
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowNoTitle">true</item>
        <!--<item name="actionOverflowMenuStyle">@style/OverflowMenuStyle</item>-->
    </style>

AndroidManifest.xml
設置theme爲Theme.AppStartLoadTranslucent

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.soulrelay.coordinatorlayoutdemo">

    <!-- To access Google+ APIs: -->
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppStartLoadTranslucent">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

其實,之前實現類似菜單功能採用popupwindow居多

Toolbar中Menu中圖標不顯示的問題

在menu中,圖標不會顯示。
有的人是採用 onMenuOpened() 來寫,可是仍然會有問題,對於AppCompactActivity你可以把onPrepareOptionsPanel(View v,Menu menu)代替 onMenuOpened() 。

@Override
    protected boolean onPrepareOptionsPanel(View view, Menu menu) {
        if (menu != null) {
            if (menu.getClass() == MenuBuilder.class) {
                try {
                    Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
                    m.setAccessible(true);
                    m.invoke(menu, true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return super.onPrepareOptionsPanel(view, menu);
    }

toolbar menu中app:showAsAction各個屬性值作用

android:showAsAction。這個屬性可接受的值有:

  • always:使菜單項一直顯示在ToolBar上。
  • ifRoom:如果有足夠的空間,這個值會使菜單項顯示在ToolBar上。
  • never:使菜單項永遠都不出現在ToolBar上,在…的子項中顯示。
  • withText:使菜單項和它的圖標,菜單文本一起顯示。

源碼下載

聯盟-暗影之月-傳送門

參考鏈接

Android佈局屬性android:clipToPadding的UI設計妙用
Android開發:最詳細的 Toolbar 開發實踐總結
fitsSystemWindows

發佈了97 篇原創文章 · 獲贊 87 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章