寫在前面:最近由於學習興趣史無前例的高漲的,看到githup和各個網站的android的新特性,看起來確實很酷,一咬牙擠出時間也去看了文檔和借鑑別人的學習經驗拿來借鑑,寫一些demo(ps:這樣就都是我的了,哈哈整個世界都是朕的)
1. 瞭解Material Design
- 概念:融合卡片式,立體式,擬物化的設計風格,強調層次感,動畫,陰影等元素
- Android UI樣式風格發展:2.3版本(俗稱屎黃色)->4.0(Hole)->5.0(MaterialDesign)
- 國內翻譯介紹:查看 http://design.1sters.com
- 官網介紹:http://developer.android.com/training/material
2. 動態替換Theme
- MaterialTheme配色方案:http://www.materialpalette.com
- 動態替換Theme的步驟:
- 定義至少2套theme
- 在xml佈局中給控件指定顏色時要使用佔位符的方式,比如:
android:textColor="?android:colorAccent"
- 調用setTheme方法設置當前的theme,但是該方法要在setContentView之前,如:
setTheme(mTheme); setContentView(R.layout.activity_main);
- 設置了Theme,需要finish當前Activity,然後重啓當前Activity,讓Theme生效
Intent intent = getActivity().getIntent(); getActivity().finish();//結束當前的Activity getActivity().overridePendingTransition(0,0);//不要動畫 startActivity(intent);
3. View的高度與陰影,輪廓
- 官網介紹:https://developer.android.com/intl/zh-tw/training/material/shadows-clipping.html
- View增加了高度的概念,高度大的View會覆蓋在高度小的View之上,並帶有陰影效果:
- View高度有2個因素組成:
View高度 = elevation + translationZ
- elevation表示view的高度,高度越大,陰影越大,可以在xml中直接使用屬性,也可以在代碼中使用view.setEvelvation();
android:elevation="10dp"
- transtionZ屬性表示view在Z方向移動的距離,一般用於屬性動畫中,translationZ也會影響View的高度,但是對陰影沒有效,同時增加了改變translationZ的屬性動畫;
android:translationZ="10dp"
- View高度有2個因素組成:
4. View的輪廓與裁剪(在Android5.1以及以上纔有效果)
- 官網介紹:https://developer.android.com/intl/zh-tw/training/material/shadows-clipping.html
- View增加了輪廓概念,輪廓會影響陰影的效果和裁剪的形狀
- View的輪廓默認是依據於background的,有其他3個取值:bounds,none,paddingBounds,可以通過outlineProvider屬性更改:
android:outlineProvider="bounds"
- 可以通過setOutlineProvider()方法自定義輪廓:
tv_blue.setOutlineProvider(new ViewOutlineProvider() { @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void getOutline(View view, Outline outline) { outline.setOval(0,0, view.getWidth(),view.getHeight()); } });
- View的輪廓默認是依據於background的,有其他3個取值:bounds,none,paddingBounds,可以通過outlineProvider屬性更改:
- View的裁剪是指將View按照輪廓裁剪,能改變View的形狀,如圓形頭像:
- 先設置輪廓:
- 再設置根據輪廓裁剪View,目前只支持對矩形,圓形,圓角矩形的裁剪:
//設置對View進行裁剪 tv_clip.setClipToOutline(true);
5. Palette的使用
- 使用Palette可以讓我們從一張圖片中拾取顏色,將拾取到的顏色賦予ActionBar,StatusBar以及背景色可以讓界面色調實現統一
- 使用Palette需要添加以下依賴:
compile 'com.android.support:palette-v7:23.0.0+'
-
Palette提供的API
- 傳入Bitmap即可獲取Palette對象,以下是同步和異步使用方式:
//同步獲取,需要在子線程中使用 Palette palette = Palette.from(drawable.getBitmap()).generate(); //異步獲取,可以在主線程中使用 Palette.from(drawable.getBitmap()).generate(new Palette.PaletteAsyncListener() { @Override public void onGenerated(Palette palette) { //... } });
- 得到Palette對象後,獲取其中的顏色,顏色對應如下:
vibrant - 有活力的顏色 lightVibrant - 有活力的亮色 darkVibrant - 有活力的暗色 muted - 柔和暗淡的顏色 lightMuted - 柔和的亮色 darkMuted - 柔和的暗色
-
獲取指定顏色的採樣對象,獲取採樣得到的顏色:
//我們可以直接使用palette獲取指定顏色: palette.getLightMutedColor(defaultColor); //一般也可以先獲取採樣對象Swatch,從Swatch中獲取我們需要的顏色: //獲取有活力顏色的採樣對象 Palette.Swatch vibrantSwatch = palette.getVibrantSwatch();
- 採樣對象Swatch提供了以下方法來獲取顏色:
//swatch.getPopulation(): the amount of pixels which this swatch represents. //swatch.getRgb(): the RGB value of this color. //swatch.getHsl(): the HSL value of this color,即色相,飽和度,明度. //swatch.getBodyTextColor(): the RGB value of a text color which can be displayed on top of this color. //swatch.getTitleTextColor(): the RGB value of a text color which can be displayed on top of this color //一般會將getRgb設置給控件背景色,getBodyTextColor()設置給文字顏色 textView.setBackgroundColor(vibrantSwatch.getRgb()); textView.setTextColor(vibrantSwatch.getBodyTextColor());
- 運行的效果圖
- 傳入Bitmap即可獲取Palette對象,以下是同步和異步使用方式:
6. 水波紋動畫,自定義水波紋動畫以及狀態選擇器動畫
- 首先,在Android5.0以上,點擊效果默認自帶水波紋效果,並且有2種選擇:
//矩形邊框水波紋 android:background="?android:attr/selectableItemBackground" //無邊框限制水波紋 android:background="?android:attr/selectableItemBackgroundBorderless"
-
自定義水波紋動畫
- 使用ViewAnimationUtils創建圓形水波紋動畫,注意該動畫不能在Activity的onCreate方法中執行:
Animator circularReveal = ViewAnimationUtils.createCircularReveal(text, 0, text.getHeight() , 1f, text.getWidth()*2); circularReveal.setDuration(1000); circularReveal.start();
- 使用ripple標籤或者RippleDrawable可以更改控件水波紋動畫顏色:
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#00ff00"> <item android:id="@android:id/mask" ><color android:color="#0000ff" />
- 使用ViewAnimationUtils創建圓形水波紋動畫,注意該動畫不能在Activity的onCreate方法中執行:
-
定義帶有屬性動畫的狀態選擇器
- 通過stateListAnimator屬性指定狀態選擇器的動畫:
android:stateListAnimator="@drawable/selector_anim"
-
狀態選擇器文件中需要加入objectAnimator標籤:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <set> <objectAnimator android:duration="300" android:propertyName="rotationX" android:valueFrom="0" android:valueTo="60" android:valueType="floatType" /> <!--<objectAnimator android:duration="300" android:propertyName="scaleY" android:valueFrom="1" android:valueTo="0.2" android:valueType="floatType"/>--> </set> </item> <item android:state_pressed="false"> <set> <objectAnimator android:duration="300" android:propertyName="rotationX" android:valueFrom="60" android:valueTo="0" android:valueType="floatType" /> <!--<objectAnimator android:duration="300" android:propertyName="scaleY" android:valueFrom="0.2" android:valueTo="1" android:valueType="floatType"/>--> </set> </item> </selector>
- 同樣,狀態選擇器動畫可以用代碼方式加載
//加載動畫 AnimationInflater.loadStateListAnimator(); //設置動畫 View.setStateListAnimator();
- 通過stateListAnimator屬性指定狀態選擇器的動畫:
-
定義帶有幀動畫的狀態選擇器,需要設置給background屬性,不是stateListAnimator,如下所示:
<?xml version="1.0" encoding="utf-8"?> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/pressed" android:drawable="@mipmap/btn_check_15" android:state_pressed="true" /> <item android:id="@+id/normal" android:drawable="@mipmap/btn_check_0" /> <!--定義幀動畫--> <transition android:fromId="@+id/normal" android:toId="@+id/pressed"> <animation-list> <item android:drawable="@mipmap/btn_check_0" android:duration="15" /> <item android:drawable="@mipmap/btn_check_1" android:duration="15" /> <item android:drawable="@mipmap/btn_check_2" android:duration="15" /> <item android:drawable="@mipmap/btn_check_3" android:duration="15" /> </animation-list> </transition> </animated-selector>
7. CardView的使用
- CardLayout是一個擁有高度和陰影,以及輪廓裁剪,圓角的佈局
-
添加依賴:
compile 'com.android.support:cardview-v7:23.2.1'
- 各屬性說明:
1.設置圓角:card_view:cardCornerRadius="10dp" 2.設置高度:card_view:cardElevation="10dp" 3.設置內邊距:card_view:contentPadding="10dp" 4.設置背景色:card_view:cardBackgroundColor="?android:attr/colorPrimary"
8. RecyclerView的使用
- https://developer.android.com/intl/zh-tw/training/material/lists-cards.html
-
添加依賴:
compile 'com.android.support:recyclerview-v7:23.0.0+'
-
首先設置LayoutManager:控制RecyclerView如何顯示佈局,系統提供3個佈局管理器:
- LinearLayoutManager:線性佈局,有橫向和豎直方向顯示
- GridLayoutManager:網格佈局,有橫向和豎直方向顯示
- StaggeredGridLayoutManager: 瀑布流佈局,有橫向和豎直方向顯示
- 然後給RecyclerView設置Adapter<RecyclerView.ViewHolder>
- 設置點擊事件,由於RecyclerView沒有setOnItemClickListener,只能在Adapter中給View設置Click事件
9. ToolBar的使用
- 它用來代替ActionBar,但是比ActionBar更加靈活,相當於可以寫在佈局文件中的ActionBar;與DrawerLayout的使用的時候,DrawerLayout可以覆蓋在ToolBar上,並且ToolBar和ActionBar不能同時使用
- 使用ToolBar的步驟:
- 先隱藏ActionBar,可以繼承一個不帶ActionBar的Theme,如:
style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"
- 然後在Activity中設置ToolBar替代ActionBar:
setSupportActionBar(toolBar);
- 最後設置ToolBar的顯示內容:
toolBar.setTitle("ToolBar");//設置標題 toolBar.setNavigationIcon(iconRes);//設置圖標 toolBar.setOnMenuItemClickListener();//設置Menu Item點擊
- 先隱藏ActionBar,可以繼承一個不帶ActionBar的Theme,如:
Android 6.0新控件
1. TextInputLayout的使用
- 高級炫酷帶有提示的輸入框,相當於輸入框中的戰鬥框
- 使用需要依賴design類庫:
compile 'com.android.support:design:23.0.0+'
- 使用步驟:
- 先在TextInputLayout中包裹一個EditText,如:
- 然後使用以下方法設置:
//獲取EditText EditText editText = inputLayout.getEditText(); //設置錯誤提示信息 inputLayout.setError("不能超過5個"); //啓用錯誤提示 inputLayout.setErrorEnabled(true);
2. FloatingActionButton的使用
- 總是能懸浮在界面上的Button,可以設置點擊事件
- 使用需要依賴design類庫:
compile 'com.android.support:design:23.0.0+'
- 可以設置以下屬性:
app:fabSize="normal"//2個取值,normal=56dp,mini=48dp app:elevation="10dp"//高度 app:rippleColor="#0000ff"//按下水波紋顏色 app:pressedTranslationZ="20dp"//按下Z軸移動距離
3. Snackbar的使用
- 一個有趣的Toast,顯示在界面底部,並且可以設置點擊行爲,也可以滑動出去
- 需要讓CoordinatorLayout作爲父佈局才能滑動出去
4. TabLayout的使用
- 相當於ViewPagerIndicator的指示器效果,一般用來跟ViewPager結合使用
- 使用需要依賴design類庫:
compile 'com.android.support:design:23.0.0+'
- 單獨使用TabLayout的步驟:
- 先添加Tab,使用tabLayout.newTab()方法創建Tab:
//1.添加Tab tabLayout.addTab(tabLayout.newTab().setText("Tab1"));
- 給tabLayout設置tab改變的監聽器:
//2.給tabLayout添加tab改變的監聽器 tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { Log.e("TAG", "onTabSelected: "+tab.getText()); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } });
- 在xml中給TabLayout設置屬性:
app:tabIndicatorColor="#00f"//橫線顏色 app:tabSelectedTextColor="#f00"//選中字體顏色 app:tabTextColor="#0f0"//默認字體顏色 app:tabMode="fixed"//fixed:不能滑動,每個Tab平分寬度,scrollable:可以滑動tab,每個tab寬度很小,適用於tab很多的情景 app:tabGravity="fill"//fill:平分寬度,center:讓tab居中
- 先添加Tab,使用tabLayout.newTab()方法創建Tab:
- 和ViewPager關聯使用步驟:
- 先給ViewPager填充數據,然後關聯TabLayout和ViewPager:
//給ViewPager填充數據 viewpager.setAdapter(new MyAdapter()); //關聯TabLayout和ViewPager tabLayout.setupWithViewPager(viewpager);
- 需要注意的是,ViewPager的adapter的getPageTitle()方法的返回值將會設置給Tab的標題
- 先給ViewPager填充數據,然後關聯TabLayout和ViewPager:
5. CoordinatorLayout的使用
- 協調佈局,能夠協調多個佈局的位置關係,可以實現讓FAB上下滑動,展開或摺疊ToolBar,控制View擴展收縮以及放大縮小
- 使用需要依賴design類庫:
compile 'com.android.support:design:23.0.0+'
-
使用它結合AppBarLayout實現向上滑動隱藏ToolBar的效果:
- AppBarLayout會將包裹的所有子View作爲一個整體的AppBar,有着統一的界面着色;
- app:layout_scrollFlags屬性介紹:
scroll:表示該View可以被滑動出CoordinatorLayout的範圍,所有想滾動出屏幕的view都需要設置這個flag, 沒有設置這個flag的view將被固定在屏幕頂部。例如,TabLayout 沒有設置這個值,將會停留在屏幕頂部 enterAlways:表示任意向下的滾動都會導致該View可見 exitUntilCollapsed:滾動退出屏幕,最後摺疊在頂端,可配合minHeight使用,當達到minHeight的時候固定 enterAlwaysCollapsed:當你的視圖已經設置minHeight屬性又使用此標誌時,你的視圖只能以最小高度進入,只有當滾動視圖到達頂部時才擴大到完整高度
-
給想滑動出範圍的View設置屬性,比如ToolBar:
app:layout_scrollFlags=”scroll|enterAlways
-
給發出滑動行爲的View設置屬性,比如ViewPager:
app:layout_behavior="@string/appbar_scrolling_view_behavior"
Android 5.0&6.0新特性的向下兼容
- 可以通過Support Library使用的新特性可以直接向下兼容,直接使用即可。如:
- RecyclerView
- CardView
- Palette顏色識別
- 以及support design包的所有新控件
- 對於新的屬性,則定義多個layout,將使用新API的佈局放在res/layout-v21中,其他的放res/layout
- 對於代碼中使用了新特性的情況,在代碼中對系統Version做判斷,使用對應的效果,如:
if(Build.VERSION.SDK_INT> 21){ //使用新動畫 ... }