Material Design 最全解析_4 視圖和效果

概述

Material Design爲開發者提供了一系列的效果、特性和控件,對於開發者來說實在是福音。
今天這篇博客就記錄一下視圖和效果方面的知識。

先看一下大綱

這裏寫圖片描述


陰影的產生、高度的計算

陰影的產生是因爲高度差,陰影的大小是由相對高度差決定的。

陰影示例

在以前UI只是二維時,View的位置參數有以下公式
X = Left + translationX
Y = Top = translationY;
Material新增的第三維度同樣遵循這個公式
Z = elevation + translationZ

在初始化View的時候,elevation被複制,之後在Z軸上做屬性動畫,改變translationZ,兩者之和是View的絕對高度。

設置Elevation

  • 在layout.xml中設置
    android:elevation="2dp"

  • 在代碼中設置
    mButton.setElevation(4f);

Palette取色器

這個類挺有意思,在Android的版本發展中,UI越來越成爲Google的發展中心,這次的Android5.X創新的使用了Palette來提取顏色,從而讓主題能夠動態適應當前頁面的色調,使得整個app的顏色基本和諧統一。

Android內置了幾種提取顏色的種類:

  • Vibrant(充滿活力的)
  • Vibrant dark(充滿活力的黑)
  • Vibrant light(充滿活力的白)
  • Muted(柔和的)
  • Muted dark(柔和的黑)
  • Muted light(柔和的白)

使用:
1. gradle
compile 'com.android.support:palette-v7:21.0.+'
2. Api

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        etContentView(R.layout.activity_main);
        setPalette();
    }

    private void setPalette() {
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
        //創建Palette對象
        Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() {
            @Override
            public void onGenerated(Palette palette) {
                //通過Palette來獲取對應的色調
                Palette.Swatch vibrant = palette.getDarkVibrantSwatch();
                //將顏色設置給相應的組件
                getSupportActionBar().setBackgroundDrawable(new ColorDrawable(vibrant.getRgb()));
                Window window = getWindow();
                window.setStatusBarColor(vibrant.getRgb());
            }
        });
    }

3.效果
palette效果
4.分析

  • 生成Palette對象的方法有好多
Palette palette = Palette.from(bitmap).generate();
Palette palette = Palette.generate(bitmap);
Palette palette = Palette.generate(bitmap, 24);

這幾個都是同步的獲取,如果bitmap很小可以這樣使用,如果bitmap很大,就需要使用異步獲取。

Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() {
    @Override
    public void onGenerated(Palette palette) {

    }
});

然而以上方法最新版本都deprecated了,建議使用Builder來構建Palette,Builder方式也支持同步和異步兩種方式。

同步:

Palette palette = new Palette.Builder(bitmap).generate();

異步:

new Palette.Builder(bitmap).generate(new Palette.PaletteAsyncListener() {
    @Override
    public void onGenerated(Palette palette) {

    }
});

Ps:重要的一點
上面有一個方法傳了24,這個值代表的是取樣的最大顏色數,默認是16,建議範圍8-32.
數值越大,取樣耗時越長,但是取樣代表性越強,所以根據你的圖片的大小和需求,自己確定數值的大小。

取樣風格
Palette.Swatch vibrant = palette.getDarkVibrantSwatch();

Palette提供了6種取樣風格:

palette.getVibrantSwatch(); //充滿活力的
palette.getDarkVibrantSwatch(); //充滿活力的黑
palette.getLightVibrantSwatch(); //充滿活力的白
palette.getMutedSwatch(); //柔和的
palette.getDarkMutedSwatch(); //柔和的黑
palette.getLightMutedSwatch(); //柔和的白

Ps:這裏的黑、白是指深色系和淺色系

  • 樣本值
    Demo裏用到的vibrant.getRgb()是獲取取樣後的顏色RGB值
    除了這個api,還有以下:

    getPopulation():Swatch所代表的取樣樣本的像素個數
    getRgb():Swatch取樣的顏色RGB
    getHsl():Swatch取樣的顏色HLS
    getBodyTextColor():在此取樣顏色上,顯示Body文本的推薦色
    getTitleTextColor():在此取樣顏色上,顯示Title文本的推薦色

Tinting着色器

先看一個例子,Tinting的使用非常的簡單,只要在XML中配置好tint和tintMode就可以了,對於配置組合效果,只需要大家實際操作一下,就能非常清晰的理解處理效果。
“`

<TextView
    android:id="@+id/tv_rect"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:elevation="1dp" />

<TextView
    android:id="@+id/tv_circle"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:elevation="1dp" />
@Bind(R.id.tv_rect)
TextView tv1;

@Bind(R.id.tv_circle)
TextView tv2;

ViewOutlineProvider vlp1 = new ViewOutlineProvider() {
    @Override
    public void getOutline(View view, Outline outline) {
        outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), 30);
    }
};

ViewOutlineProvider vlp2 = new ViewOutlineProvider() {
    @Override
    public void getOutline(View view, Outline outline) {
        outline.setOval(0, 0, view.getWidth(), view.getHeight());
    }
};

tv1.setOutlineProvider(vlp1);
tv2.setOutlineProvider(vlp2);

方形裁剪 圓形裁剪
Ps:這個灰色邊框是因爲elevation>0而產生的陰影

打開Outline.java文件,公開的方法並不算多

outline.canClip();
是否支持裁剪,目前只有矩形、圓形、圓角矩形支持裁剪
outline.getAlpha();
設置透明度
outline.isEmpty();
是否是空的。剛創建的時候是空的,調用了setEmpty後是空的。
outline.offset(0, 0);
設置x、y的偏移量
outline.setAlpha(1);
設置透明度
outline.setConvexPath(null);
設置用於構造一個outline的path
outline.setEmpty();
置空
outline.setOval(0, 0, 0, 0);
設置橢圓
outline.setOval(new Rect(0, 0, 0, 0));
同上
outline.setRoundRect(0, 0, 0, 0, 10);
設置圓角矩形
outline.setRoundRect(new Rect(0, 0, 0, 0), 10);
同上

以上都是在操作outline,有了outline就可以用它來裁剪View。 view.setClipToOutline(true)

還用以上面的例子來說:
一個TextView,設置背景顏色
原始textview

<TextView
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:background="#d0d0d0"
    android:text="OutLine"
    android:gravity="center"
    android:elevation="2dp"/>

設置一個outline
tv.setOutlineProvider(outline);
設置outlineprovider的textview
你會發現並沒有變化。
因爲outline並沒有應用到裁剪view的內容,需要調用tv.setClipToOutline(true)
這句話會用當前的outline裁剪view的內容,需要canClip返回true,之前提到,目前只有矩形、圓形、圓角矩形支持裁剪。
裁剪結果:
裁剪效果

Ps:關於outline、clipping、background、alpha
Outline可以影響投影的輪廓,但如果setClipToOutline(false),那它並不會裁剪view的內容,所以也不能改變background和forground的形狀。
Outline只是用path描述的一種形狀,本身並沒有顏色,但是它卻有alpha值,並且它的alpha值會影響陰影的透明度。
按照Material的原則,光照不透明的實體纔會產生陰影,outline能影響陰影輪廓,卻又沒有改變view的實體形狀,這就不好理解了。
setClipToOutline內部調用了native方法,沒法知道具體的實現。


以上就是這篇文章的全部內容,從下一篇開始,就開始講解UI控件相關,相信是大多數人關心的。

本期節目就到這裏,感謝大家收看,我們下期再見~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章