Android Material Design NavigationView 及 Palette 顏色提取器

来源:http://www.cnblogs.com/284628487a/archive/2016/03/14/5275471.html
-Advertisement-
Play Games

Android Material Design DrawerLayout和NavigationView及Palette


DrawerLayout + NavigationView

DrawerLayout佈局,通常在裡面添加兩個子控制項,程式主界面添加到NavitagionView前面。

<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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">
    <include
        layout="@layout/app_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
<android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header_main" app:menu="@menu/activity_main_drawer" /> </android.support.v4.widget.DrawerLayout>

這裡有兩個重要的屬性headerLayout和menu,分別表示header部分佈局和menu菜單資源。

程式主界面佈局app_main,包含AppBarLayout和content_main,以及一個FloatingActionButton。

<android.support.design.widget.CoordinatorLayout 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.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>

上面的主界面佈局也以隨意切換成其它佈局。

註意事項:

1.DrawerLayout指定openDrawer為start,NavigationView指定layout_gravity為start。

2.指定NavigationView的headerLayout屬性和menu屬性,分別為layout佈局文件和menu文件。

headerLayout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/nav_header_height"
    android:background="@drawable/side_nav_bar"
    android:gravity="bottom"
    android:orientation="vertical"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:src="@android:drawable/sym_def_app_icon" />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:text="Android Studio"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="[email protected]" />
</LinearLayout>

menu菜單資源

調用 setNavigationItemSelectedListener() 後,在菜單項被選中的時候,你會通過OnNavigationItemSelectedListener 得到回調。在處理回調時,你會知道是哪個菜單項被點擊,此時你可以處理選擇事件,修改選中狀態,載入新的內容,以及通過代碼來關閉 drawer,或者其他任何你想執行的操作。

<menu xmlns:android="http://schemas.android.com/apk/res/android"><group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_camera"
            android:icon="@drawable/ic_menu_camera"
            android:title="Import" />
        <item
            android:id="@+id/nav_gallery"
            android:icon="@drawable/ic_menu_gallery"
            android:title="Gallery" />
        <item
            android:id="@+id/nav_slideshow"
            android:icon="@drawable/ic_menu_slideshow"
            android:title="Slideshow" />
        <item
            android:id="@+id/nav_manage"
            android:icon="@drawable/ic_menu_manage"
            android:title="Tools" />
    </group>
    <item android:title="Communicate">
        <menu>
            <item
                android:id="@+id/nav_share"
                android:icon="@drawable/ic_menu_share"
                android:title="Share" />
            <item
                android:id="@+id/nav_send"
                android:icon="@drawable/ic_menu_send"
                android:title="Send" />
        </menu>
    </item>
</menu>

下麵是涉及到的styles文件

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>

Activity

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();
        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
    }
    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        int id = item.getItemId();
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }
}

Toolbar設置

        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        mToolbar.setTitle("Rocko");
        // 標題的文字需在setSupportActionBar之前,不然會無效
        // toolbar.setSubtitle("副標題");
        setSupportActionBar(mToolbar);
        /* 這些通過ActionBar來設置也是一樣的,註意要在setSupportActionBar(toolbar);之後,不然就報錯了 */
        // getSupportActionBar().setTitle("標題");
        // getSupportActionBar().setSubtitle("副標題");
        // getSupportActionBar().setLogo(R.drawable.ic_launcher);
        /* 菜單的監聽可以在toolbar里設置,也可以像ActionBar那樣,通過下麵的兩個回調方法來處理 */
        mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.action_settings:
                        Toast.makeText(MainActivity.this, "action_settings", Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.action_share:
                        Toast.makeText(MainActivity.this, "action_share", Toast.LENGTH_SHORT).show();
                        break;
                    default:
                        Log.e("tag", item.toString());
                        break;
                }
                return true;
            }
        });

設置ActionBar及StatusBar背景顏色,在Api21及以上才有。

        if (null != vibrant) {
                /* 界面顏色UI統一性處理,看起來更Material一些 */
            mPagerSlidingTabStrip.setBackgroundColor(vibrant.getRgb());
            mPagerSlidingTabStrip.setTextColor(vibrant.getTitleTextColor());
            // 其中狀態欄、游標、底部導航欄的顏色需要加深一下,也可以不加,具體情況在代碼之後說明
            mPagerSlidingTabStrip.setIndicatorColor(colorBurn(vibrant.getRgb()));
            mToolbar.setBackgroundColor(vibrant.getRgb());
            if (android.os.Build.VERSION.SDK_INT >= 21) {
                Window window = getWindow();
                // 很明顯,這兩貨是新API才有的。
                window.setStatusBarColor(colorBurn(vibrant.getRgb()));
                window.setNavigationBarColor(colorBurn(vibrant.getRgb()));
            }
        }

colorBurn

    private int colorBurn(int RGBValues) {
        int alpha = RGBValues >> 24;
        int red = RGBValues >> 16 & 0xFF;
        int green = RGBValues >> 8 & 0xFF;
        int blue = RGBValues & 0xFF;
        red = (int) Math.floor(red * (1 - 0.1));
        green = (int) Math.floor(green * (1 - 0.1));
        blue = (int) Math.floor(blue * (1 - 0.1));
        return Color.rgb(red, green, blue);
    }

Palette

根據圖片來決定標題的顏色和標題欄的背景色,這樣視覺上更具有衝擊力和新鮮感,而不像統一色調那樣呆板。 

Palette是什麼?它能讓你從圖像中提取突出的顏色。這個類能提取以下突出的顏色:

  1. Vibrant(充滿活力的)

  2. Vibrant dark(充滿活力的黑)

  3. Vibrant light(充滿活力的亮)

  4. Muted(柔和的)

  5. Muted dark(柔和的黑)

  6. Muted lighr(柔和的亮)

如何使用?

要提取這些顏色,在你載入圖片的後臺線程中傳遞一個點陣圖對象給Palette.generate()靜態方法。如果不使用線程,則調用Palette.generateAsync()方法並且提供一個監聽器去替代。

你可以在Palette類中使用getter方法來從檢索突出的顏色,比如Palette.getVibrantColor。

Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
      xx.setBackgroundColor(palette.getVibrantColor(mContext
             .getResources().getColor(R.color.black_translucent_60)));
  }
});

2.

Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
      xx.setBackgroundColor(palette.getVibrantColor(mContext
             .getResources().getColor(R.color.black_translucent_60)));
  }
});
Palette.generateAsync(bitmap,new Palette.PaletteAsyncListener() {  
   @Override  
   public void onGenerated(Palette palette) {  
        Palette.Swatch vibrant =palette.getVibrantSwatch();  
         if (swatch != null) {  
             // If we have a vibrant color  
             // update the title TextView  
             titleView.setBackgroundColor(vibrant.getRgb());  
             titleView.setTextColor(vibrant.getTitleTextColor());  
         }  
   }  
});

上面的代碼展示瞭如何從一張圖片中提取顏色將textView的背景色設置成圖片的主色調,然後再使用getTitleTextColor()來設置一個匹配的文字顏色。

比如如果你的TextView 有個背景圖片,要想讓字體顏色能夠和背景圖片匹配,則使用getBodyTextColor()比較合適,getTitleTextColor()其實應該和getBodyTextColor()差不多。

size的問題

你還可以使用如下方法一次性獲得所有的swatch:

List<Palette.Swatch> swatches = palette.getSwatches();

在上面的代碼中,你可能註意到了可以設置palette的size。size越大,花費的時間越長,而越小,可以選擇的色彩也越小。最佳的選擇是根據image的用途:

  • 頭像之類的,size最好在24-32之間;
  • 風景大圖之類的 size差不多在8-16;
  • 預設是16. 

有四種創建Palette實例的方法:

// Synchronous methods.
// --------------------------------
// These should be used when you have access to the underlying image loading thread.
// Picasso allows this through a Transformation. For other libraries, YMMV.
// Uses the default palette size (16).
Palette p = Palette.generate(bitmap);
// Allows you to specify the maximum palette size, in this case 24.
Palette p = Palette.generate(bitmap, 24);
// Asynchronous methods
// --------------------------------
// This is the quick and easy integration path. Internally uses an AsyncTask so
// this may not be optimal (since you're dipping in and out of threads)
// Uses the default palette size (16).
Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() {
    @Override
    public void onGenerated(Palette palette) {
       // Here's your generated palette
    }
});
// Allows you to specify the maximum palette size, in this case 24.
Palette.generateAsync(bitmap, 24, new Palette.PaletteAsyncListener() {
    @Override
    public void onGenerated(Palette palette) {
       // Here's your generated palette
    }
});
 

創建完一個實例之後,我們還需要得到一種採集的樣本(swatch),有6中樣本(swatch):

Vibrant. Palette.getVibrantSwatch()
Vibrant dark. Palette.getDarkVibrantSwatch()
Vibrant light. Palette.getLightVibrantSwatch()
Muted. Palette.getMutedSwatch()
Muted dark. Palette.getDarkMutedSwatch()
Muted light. Palette.getLightMutedSwatch()

具體選擇哪一種取決於你自己,大多數情況下我們都使用Vibrant and Dark Vibrant。

使用樣本(swatch)

swatch有以下方法:

getPopulation(): the amount of pixels which this swatch represents.
getRgb(): the RGB value of this color.
getHsl(): the HSL value of this color.
getBodyTextColor(): the RGB value of a text color which can be displayed on top of this color.
getTitleTextColor(): the RGB value of a text color which can be displayed on top of this color.

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  •   function person(name,age) { //局部變數 var name = name; var age = age; var addYear = function() { age++; alert(age); } return addYear; }//閉包:局部變數和函數運行完成
  • 有時候我們需要利用js來動態生成頁面上style標簽中的css代碼,方法很直接,就是直接創建一個style元素,然後設置style元素裡面的css代碼,最後把它插入到head元素中。 但有些相容性問題我們需要解決。首先在符合w3c標準的瀏覽器中我們只需要把要插入的css代碼作為一個文本節點插入到st
  • 簡歷非常能反映一個人的性格和水平,相比於你在學校獲得多少獎項,工作經歷、項目經 歷、熟悉的技術等更加關鍵,如果還有博客和一些 Github 上的項目,好感度++,但記得在去面試前收拾下,我們真的會挨個文件 review 你的開源代碼的。我們還喜歡關註一些細節,比如簡歷里關鍵字的拼寫,看似無關緊要但很
  • There are only two hard things in Computer Science: cache invalidation and naming things.在電腦科學中只有兩件難事:緩存失效和命名。 – Phil Karlton 電腦語言是人和電腦之間通訊的媒介。好的代碼
  • Android Material Design
  • 游戲項目尾聲,做下總結: 1.sharesdk微信微博分享(1) 如果接入眾多渠道,選用服務端獲取代碼配置參數的方式(微信:app_id 微博: app_key, app_secret)代碼配置2.x版本需註意setPlatformConfig設置參數時Android和ios設置key不同(Andr
  • 今天發現之前自己一直有個誤區,new Runnable(run()方法){}原來它不是一定創建一個線程 如果用主線程的handler去post(Runnable),他就不會創建子線程,而是在主線程上執行的Runnable方法 如果用new Thread(Runnable).start();那他就是在
  • 在網上找到了一篇總結的非常好的文章,我這裡就貼出他的博文地址。自己就不再寫這個方面的總結了。 "Activity與Fragment通信(99%)完美解決方案"
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...