概述
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.效果
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
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#d0d0d0"
android:text="OutLine"
android:gravity="center"
android:elevation="2dp"/>
設置一個outline
tv.setOutlineProvider(outline);
你會發現並沒有變化。
因爲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控件相關,相信是大多數人關心的。
本期節目就到這裏,感謝大家收看,我們下期再見~