MaterialDesign 筆記

TabLayout和TabLayout.Tab

  1. 使用場景
    在ViewPager的上方哗讥,通常我們都會放一個標(biāo)簽指示器與ViewPager進行聯(lián)動; 以前通常使用開源的框架,或者自定義view;現(xiàn)在google提供的解決辦法

  2. 使用方法

    通常我們調(diào)用TabLayout.setupWithViewPager和ViewPager進行關(guān)聯(lián), 每個Tab的內(nèi)容從PagerAdapter.getPageTitle方法獲取;

    也可以自己設(shè)置每個Tab的內(nèi)容, 代碼如下

     TabLayout tabLayout = ...;
     TabLayout.Tab tab = tabLayout.newTab();  // 創(chuàng)建tab
     tab.setText("Tab 1");       // 設(shè)置每個tab的屬性
     tabLayout.addTab(tab);
    

    顯示的模式有2種, 一種固定寬度TabLayout.MODE_FIXED, 一種可以滾動TabLayout.MODE_SCROLLABLE; 默認(rèn)是MODE_FIXED, 可以通過代碼,也可以通過xml屬性設(shè)置

    常見屬性

     <item name="tabMaxWidth">@dimen/tab_max_width</item>
     <item name="tabIndicatorColor">?attr/colorAccent</item>
     <item name="tabIndicatorHeight">2dp</item>
     <item name="tabPaddingStart">12dp</item>
     <item name="tabPaddingEnd">12dp</item>
     <item name="tabBackground">?attr/selectableItemBackground</item>
     <item name="tabTextAppearance">@style/TextAppearance.Design.Tab</item>
     <item name="tabSelectedTextColor">?android:textColorPrimary</item>
    

    https://guides.codepath.com/android/google-play-style-tabs-using-tablayout#design-support-library
    可以參考的鏈接

CoordinatorLayout AppbarLayout CollapsingToolbarLayout

  1. CoordinatorLayout作用
    CoordinatorLayout作用可以從名稱看出,作為一個協(xié)調(diào)者; 主要用來協(xié)調(diào)調(diào)度子View; 分兩個方面來協(xié)調(diào), 協(xié)調(diào)子View的布局 和協(xié)調(diào)子View的事件分發(fā)

  2. 解決的問題

    • 子View事件分發(fā)的困境;
      在原先View的事件分發(fā)設(shè)計模型中, 事件由 dispatchTouchEvent分發(fā), 然后由 onIntercepteTouchEvent負責(zé)攔截, 最后在onTouchEvent中處理, ActionDown事件一旦被接收, 后續(xù)事件將默認(rèn)給此view處理, 其他view無法接收事件, 當(dāng)有多個view需要同時處理一個滑動事件時, 原先的事件分發(fā)無法解決; 原先一旦遇到這種情況,只有自己去自定義view, 重寫事件分發(fā)過程, 現(xiàn)在通過CoordinatorLayout可以優(yōu)雅的解決這個問題;

      NestedScroll: 解決父子view的同時處理同一事件的流程
      CoordinatorLayout: 解決并列的兄弟View處理同一事件的流程

    • 子View布局的困境
      和子view的事件分發(fā)一樣, 原先每個子View布局位置, 是在父ViewGroup的layout方法中確定; 而當(dāng)需要子view的布局位置, 跟隨另一個子view變化時,絕大部分情況, 需要自定義view; 而現(xiàn)在CoordinatorLayout也可以優(yōu)雅的解決這個問題

  3. 使用
    使用很簡單, 使用CoordinatorLayout作為父ViewGroup, 子view在xml中指定app:behavior; 指定的behavior都是繼承于CoordinatorLayout.Behavior, Behavior類提供的接口中, 可以定義該子View需要和另外哪些子view關(guān)聯(lián), 關(guān)聯(lián)的子view發(fā)生變化時, 自身怎么處理; 當(dāng)父CoordinatorLayout接收到滑動事件時, 該子view怎么處理;

    Behavior需要自己去自定義, 不過系統(tǒng)默認(rèn)提供幾種常用的behavior; 具體介紹, 下面再說

  4. 原理

    • 子view接收處理的事件如何交給父CoordinatorLayout去分發(fā)
      上面說過,父子view協(xié)同處理滑動事件, google官方很早給出了NestedScroll; 同時也在v4包中提供了NestedScrillingChild, NestedScrollingChildHelper, NestedScrollingParentNestedScrollingParentHelper, 幫助我們解決嵌套的滾動問題;

      CoordinatorLayout實現(xiàn)的NestedScrollingParent接口, 因此當(dāng)子view實現(xiàn)了NestedScrillingChild接口時,可以收到子view的滑動事件; 同時,原先系統(tǒng)的ScrollView, ListView都未實現(xiàn)NestedScrillingChild, 所以放在CoordinatorLayout中用于滾動的view一般是RecyclerView, NestedScrollView

    • 子view接收兄弟view的滑動事件并消耗掉
      上面說到子view把滑動事件交給CoordinatorLayout去處理, 子View接收消耗兄弟view的的事件,就是CoordinatorLayout接收到事件后, 調(diào)用兄弟view的behavior的方法, 由我們自定義behavior去處理

    • 子view跟隨兄弟view變化而變化
      和上面一樣, 布局原先是有l(wèi)ayout方法決定, 而在CoordinatorLayout中, 在layout的過程中, 會調(diào)用behavior中的方法,以方便自己調(diào)整布局

    從RecyclerView開始, View設(shè)計思想有所轉(zhuǎn)變; 組合優(yōu)于繼承, 約定優(yōu)于配置,體現(xiàn)的很明顯
    多組合而少繼承; 推薦擴展指定的組件實現(xiàn)功能, 而不是通過自定義view去實現(xiàn)功能; eg: 使用behavior去控制CoordinatorLayout的事件分發(fā);使用LayoutMananger去控制recyclerview的布局

和AppbarLayout, CollapsingToolbarLayout 結(jié)合使用

  1. 作用
    AppbarLayout一般放在CoordinatorLayout中使用, 可以使不具有處理滾動事件的view, 產(chǎn)生滾動效果; AppBarLayout會默認(rèn)和AppBarLayout.Behavior關(guān)聯(lián), 而該behavior中會幫我們處理滾動事件

    CollapsingToolbarLayout提供視差滾動, 和調(diào)整滾動時 狀態(tài)欄和toolbar顏色配置的功能

  2. AppbarLayout的使用
    AppBarLayout繼承與LinearLayout, 可以為每個子view設(shè)置app:layout_scrollFlags屬性, 用于去控制子view的滾動
    滾動屬性有如下幾種

    • scroll 該子view可以滾動
    • enterAlways 當(dāng)有向下滾動事件時,改view就馬上顯示
    • scrollUntilCollpse 向上滾動搜索直至最小高度, 需要和minHeight一起用
    • snap 滾動只能在開始位置或者結(jié)束位置停下
     <android.support.design.widget.CoordinatorLayout
             xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:app="http://schemas.android.com/apk/res-auto"
             android:layout_width="match_parent"
             android:layout_height="match_parent">
    
         <android.support.v4.widget.NestedScrollView
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 app:layout_behavior="@string/appbar_scrolling_view_behavior">
    
             <!-- Your scrolling content -->
    
         </android.support.v4.widget.NestedScrollView>
    
         <android.support.design.widget.AppBarLayout
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent">
    
             <android.support.v7.widget.Toolbar
                     ...
                     app:layout_scrollFlags="scroll|enterAlways"/>
    
             <android.support.design.widget.TabLayout
                     ...
                     app:layout_scrollFlags="scroll|enterAlways"/>
    
         </android.support.design.widget.AppBarLayout>
    
     </android.support.design.widget.CoordinatorLayout>

一般在布局中, 遇到三段式布局, 并且布局布局要求滾動, 就可以考慮使用了

SnakeBar FloatActionButton

SnakeBar和Toast類似, 僅用于提示信息, 代碼寫法也和toast相似

Snackbar.make(mCoordinatorLayout, "顯示snackBar", Snackbar.LENGTH_SHORT).show();

BottomSheetBehavior BottomSheetDialog

使View從底部彈出, 分兩段顯示的一個Coordinator.Behavior, 必須使用在CoordinatorLayout中;

對需要使用的的View,在布局中添加上app:layout_behavior="@string/bottom_sheet_behavior"屬性即可

常用的有3中模式狀態(tài), 展開STATE_EXPANDED, 收縮STATE_COLLAPSED, 隱藏STATE_HIDDEN, 隱藏后,一般需要通過代碼使其展開

在代碼中使用

View view = ....;
final BottomSheetBehavior behavior = BottomSheetBehavior.from(view);
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED)      // 設(shè)置狀態(tài)

常用屬性

app:behavior_hideable="true"        // 是否可以隱藏
app:behavior_peekHeight="100dp"     // 坍塌時的高度

BottomSheetDialog是BottomSheet的dialog實現(xiàn)形式; 實現(xiàn)比較巧妙, BottomSheetDialog繼承于Dialog,在構(gòu)造時,會創(chuàng)建CoordinatorLayout, 然后拿到dialog對應(yīng)的window的decorView, 將其添加到CoordinatorLayout中, 從而實現(xiàn)BottomSheetBehavior

Ripple animattion

水波紋動畫目前僅支持api>21的版本
屬于view的背景效果,放在drawable文件下, 由于只支持21之上,一般需要針對不同的版本提供2套背景, drawable-v21目錄使用水波紋悲劇, drawable目錄使用普通背景

創(chuàng)建內(nèi)容很簡單

    <ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="?android:colorControlHighlight">
        <item android:drawable="@drawable/button_normal" />
    </ripple>

有無界unbounded和有邊境之分, 如果ripple中間沒有item, 就為unbounded的, 水波紋可以擴散到其他view的背景中去

Reveal animator

揭露動畫, 目前也僅支持api>21

通過ViewAnimationUtils.createCircularReveal創(chuàng)建, 返回的是一個Animator對象;

    // 創(chuàng)建揭露動畫, 
    Animator revealAnimator = ViewAnimationUtils.createCircularReveal( animatorView, x, y, 0, animatorView.getWidth() );

stateListAnimator

View的狀態(tài)動畫, 和view的狀態(tài)背景相似
動畫文件放在animator目錄下,

參考鏈接

Transtions 轉(zhuǎn)場動畫

新的過渡動畫,仍然只兼容api>21的版本
示例demo可以參考 https://github.com/lgvalle/Material-Animations

過渡動畫

原先的過渡動畫Activity.overridePendingTransition,只有進入,退出兩種, 現(xiàn)在有了4種;

分別為以下4種;
EnterTransition <--> ReturnTransition
ExitTransition <--> ReenterTransition

假設(shè)Activity A 啟動Activity B;
A退出時,觸發(fā)ExitTransition; 跳轉(zhuǎn)到B, 進入到B時, 觸發(fā)EnterTransition;
從B點擊返回鍵,退回到A時
B觸發(fā)ReturnTransition, 返回到A時, 觸發(fā)A的ReenterTransition

目前支持的動畫, 有Explode, Fade, Slide幾種, 動畫支持在主題中配置,和使用代碼設(shè)置, 和原先的過渡動畫相似

  • 在主題中配置動畫示例

    1. 創(chuàng)建動畫文件
      <?xml version="1.0" encoding="utf-8"?>
      <slide xmlns:android="http://schemas.android.com/apk/res/"
      android:duration="1000"/>
    2. 在主題中使用屬性引用動畫文件
      <item name="android:windowEnterTransition"></item>
      <item name="android:windowExitTransition"></item>
      <item name="android:windowReenterTransition"></item>
      <item name="android:windowReturnTransition"></item>
  • 手動配置示例
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_transition);
    setupWindowAnimations();
    }

     private void setupWindowAnimations() {
         Slide slide = TransitionInflater.from(this).inflateTransition(R.transition.activity_slide);
         getWindow().setExitTransition(slide);
     }
    

如果只配置EnterTransition,沒有配置ReturnTransition, 在返回時, 將會把EnterTransition反過來運行一遍

退出時需要運行ReturnTransition和ReenterTransition試, 不能直接調(diào)用Activity.finish方法, 要改為調(diào)用Activity.finishAfterTransition, 如果各版本要保持相同的代碼, 可以調(diào)用ActivityCompactActivityCompat方法

共享元素的過渡動畫

  1. 在主題中打開該功能, 如果使用的material design主題, 會默認(rèn)打開
    <style name="MaterialAnimations" parent="@style/Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="android:windowContentTransitions">true</item
    ...
    </style>

  2. 設(shè)置共享view的transition name; 2個共享view的android:transitionName屬性必須一樣
    <ImageView
    android:id="@+id/small_blue_icon"
    style="@style/MaterialAnimations.Icon.Small"
    android:src="@drawable/circle"
    android:transitionName="@string/blue_name" />

  3. 使用新的api構(gòu)建動畫并啟動actiivity
    blueIconImageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    Intent i = new Intent(MainActivity.this, SharedElementActivity.class);

             View sharedView = blueIconImageView;
             String transitionName = getString(R.string.blue_name);
    
             ActivityOptions transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, sharedView, transitionName);
             startActivity(i, transitionActivityOptions.toBundle());
         }
     });
    

如果想要保持不同版本的代碼一致, 可以使用v4包中的ActivityCompat.startActivity方法去啟動activity

參考

https://developer.android.google.cn/training/material/index.html
http://wiki.jikexueyuan.com/project/material-design/whatis-material-design/environment.html
https://developer.android.google.cn/training/material/index.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市丽猬,隨后出現(xiàn)的幾起案子场勤,更是在濱河造成了極大的恐慌,老刑警劉巖编兄,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轩性,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機揣苏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門悯嗓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人卸察,你說我怎么就攤上這事脯厨。” “怎么了坑质?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵合武,是天一觀的道長。 經(jīng)常有香客問我涡扼,道長稼跳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任吃沪,我火速辦了婚禮汤善,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘票彪。我一直安慰自己红淡,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布降铸。 她就那樣靜靜地躺著在旱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪推掸。 梳的紋絲不亂的頭發(fā)上桶蝎,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音终佛,去河邊找鬼俊嗽。 笑死,一個胖子當(dāng)著我的面吹牛铃彰,可吹牛的內(nèi)容都是我干的绍豁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼牙捉,長吁一口氣:“原來是場噩夢啊……” “哼竹揍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起邪铲,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤芬位,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后带到,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昧碉,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了被饿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片四康。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖狭握,靈堂內(nèi)的尸體忽然破棺而出闪金,到底是詐尸還是另有隱情,我是刑警寧澤论颅,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布哎垦,位于F島的核電站,受9級特大地震影響恃疯,放射性物質(zhì)發(fā)生泄漏漏设。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一澡谭、第九天 我趴在偏房一處隱蔽的房頂上張望愿题。 院中可真熱鬧损俭,春花似錦蛙奖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至琐脏,卻和暖如春攒砖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背日裙。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工吹艇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人昂拂。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓受神,卻偏偏與公主長得像,于是被迫代替她去往敵國和親格侯。 傳聞我的和親對象是個殘疾皇子鼻听,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容