CollapsingToolbarLayout
這個是作用域Toolbar基礎之上的布局,也是Design Support庫提供的澳迫,可以讓Toolbar的效果變得更加的豐富
- CollapsingToolbarLayout是不能獨立存在的郊楣,它只能是AppBarLayout的直接子布局鸭津,而AppBarLayout又必須是CoordinatorLayout的子布局盒卸,因此這次實現(xiàn)的功能需要綜合前面所學的各種知識
- 首先需要一個額外的活動作為水果的詳情展示界面较雕,右擊包-->New-->Activity-->Empty Activity,創(chuàng)建一個FruitActivity食拜,布局為activity_fruit.xml鸵熟,然后編寫水果詳情界面布局
- 在activiyt_fruit.xml中的內(nèi)容主要分為兩個部分,第一是水果的標題欄监婶,一個是水果的內(nèi)容詳情旅赢,首先是標題欄部分,使用CoordinatorLayout作為最外層的布局
<?xml version="1.0" encoding="utf-8"?>
<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.design.widget.CoordinatorLayout>
- 要注意的就是xmlns:app
- 在CoordinatorLayout中嵌套一個AppBarLayout
<?xml version="1.0" encoding="utf-8"?>
<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.design.widget.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="250dp">
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
- 這里指定了一個AppBarLayout的id惑惶,寬度指定為250dp
- 在AppBarLayout中嵌套一個CollapsingToolbarLayout
<?xml version="1.0" encoding="utf-8"?>
<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.design.widget.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="250dp">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed"
>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
- 其中 android:theme屬性是指定主題煮盼,
- app:contentScrim屬性是用于指定CollapsingToolbarLayout在趨于折疊狀態(tài)以及折疊之后的背景色
- app:layout_scrollFlags屬性,scroll表示CollapsingToolbarLayout會隨著水果內(nèi)容詳情的滾動一起滾動带污,enterAlwaysCollapsed表示CollapsingToolbarLayout隨著滾動完成后折疊之后就保留在界面上僵控,不再移除屏幕
- 在CollapsingToolbarLayout中定義標題欄具體的內(nèi)容
<?xml version="1.0" encoding="utf-8"?>
<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.design.widget.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="250dp">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed"
>
<ImageView
android:id="@+id/fruit_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"
/>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
- 在CollapsingToolbarLayout中定義一個ImageView和Toolbar,這就意味著高級版的標題欄將是由普通的標題欄加上圖片組合
- 其中app:layout_collapseMode屬性是用于指定當前控件在CollapsingToolbarLayout折疊過程中的折疊模式鱼冀,其中的Toolbar指定pin表示在折疊過程中位置始終保持不變报破,ImageView指定parallax表示在折疊過程中產(chǎn)生一定的錯位偏移,這種模式的視覺效果會非常好
- 水果的標題欄界面完成了千绪,開始編寫水果內(nèi)容詳情部分充易,繼續(xù)在actvity_fruit.xml中修改代碼,如下
<?xml version="1.0" encoding="utf-8"?>
<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.design.widget.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="250dp">
...
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
- 這里在水果詳情的最外層布局中使用了一個NestedScrollView荸型,注意:和AppBarLayout是平級的盹靴,
- 之前學的ScrollView它允許使用滾動的方式查看屏幕以外的數(shù)據(jù),而NestedScrollView在此基礎上還增加了嵌套響應滾動事件的功能
- 注意app:layout_behavior屬性瑞妇,指定一個布局行為稿静,和之前在RecyclerView中的一樣
- 不管是ScrolView還是NestedScrollView,它的內(nèi)部都只允許存在一個直接子布局辕狰,如果想要放入更多的東西的時候改备,就要在里面先嵌套一個LinearLayout,然后在放入具體的內(nèi)容
<?xml version="1.0" encoding="utf-8"?>
<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.design.widget.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="250dp">
...
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
- 在里面嵌套一個LineatLayout蔓倍,具體的內(nèi)容在這個里面
- 使用TextView來顯示水果的內(nèi)容詳情,并將TextView放入到卡片式布局中
<?xml version="1.0" encoding="utf-8"?>
<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.design.widget.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="250dp">
...
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="30dp"
app:cardCornerRadius="4dp"
>
<TextView
android:id="@+id/fruit_content_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
/>
</android.support.v7.widget.CardView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
- 這里為了美觀悬钳,把TextView放入到了CardView中去了
- 水果的標題欄和水果內(nèi)容的詳情的界面基本就是這樣的,當然了還可以在頁面上添加一個懸浮按鈕偶翅,這樣看起來就高大上了一點他去,這里就加入一個評論的懸浮按鈕,首先準備好一張圖片倒堕,然后修改代碼
<?xml version="1.0" encoding="utf-8"?>
<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.design.widget.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="250dp">
...
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
...
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_comment"
app:layout_anchor="@id/appBar"
app:layout_anchorGravity="bottom|end"
/>
</android.support.design.widget.CoordinatorLayout>
- 這里加入了一個FloatingActionButton灾测,它和AppBarLayout、NestedScrollView是平級的
- 在FloatingActionButton中是使用了app:layout_anchor屬性指定了一個錨點垦巴,這里錨點設置為AppBarLayout媳搪,這樣懸浮按鈕就會出現(xiàn)在水果標題欄的區(qū)域內(nèi)
- 使用app:layout_anchorGravity屬性指定懸浮按鈕的定位,為右下角
- 這樣activity_fruit.xml布局都編寫完了骤宣,
- 界面寫完后秦爆,就該寫FruitActivity中的代碼了
package com.example.tool;
public class FruitActivity extends AppCompatActivity {
public static final String FRUIT_NAME = "fruit_name";
public static final String FRUIT_IMAGE_ID = "fruit_image_id";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fruit);
// 通過這個獲取到傳入的水果名稱和圖片資源id
Intent intent = getIntent();
String fruitName = intent.getStringExtra(FRUIT_NAME);
int fruitImageId = intent.getIntExtra(FRUIT_IMAGE_ID,0);
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar_1);
CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout)findViewById(R.id.collapsing_toolbar);
ImageView fruitImageVIew = (ImageView)findViewById(R.id.fruit_image_view);
TextView fruitContentText = (TextView)findViewById(R.id.fruit_content_text);
setSupportActionBar(toolbar);
// 啟用HomeAsUp按鈕
ActionBar actionBar = getSupportActionBar();
if (actionBar != null){
actionBar.setDisplayHomeAsUpEnabled(true);
}
// 將水果的名稱設置為當前的界面標題
collapsingToolbar.setTitle(fruitName);
// 傳入水果圖片,設置到標題欄上面
Glide.with(this).load(fruitImageId).into(fruitImageVIew);
// 生成一堆字符串設置到TextView上面
String fruitContent = generateFruitContent(fruitName);
fruitContentText.setText(fruitContent);
}
private String generateFruitContent(String fruitName){
StringBuilder fruitContent = new StringBuilder();
for (int i=0;i<500;i++){
fruitContent.append(fruitName);
}
return fruitContent.toString();
}
// 處理HomeAsUp按鈕的點擊事件
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
- 首先在onCreate()方法中通過Intent獲取到傳入的水果的名稱和水果圖片的id憔披,然后獲取到布局文件中的定義的各個控件的實例
- 使用了Toolbar的標準用法等限,將它作為ActionBar顯示爸吮,并啟用HomeAsUp按鈕,由于HomeAsUp默認就是一個返回的箭頭望门,這里不用修改
- 調(diào)用 collapsingToolbar.setTitle()方法設置水果名為當前界面的標題形娇,然后使用Glide加載傳入的水果圖片,并設置到標題欄的ImageView中
- 水果的內(nèi)容詳情筹误,這里使用generateFruitContent()方法獲取一堆數(shù)據(jù)桐早,傳入到 fruitContentText.setText()方法中
- 最后在 onOptionsItemSelected()方法中處理了HomeAsUp按鈕的點擊事件,點擊的時候調(diào)用finish()厨剪,從而就返回上一個活動了
- 最后哄酝,就是處理RecyclerView的點擊事件了,修改FruitAdapter中的代碼
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
...
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mContext==null){
mContext=parent.getContext();
}
View view= LayoutInflater.from(mContext).inflate(R.layout.fruit_item,parent,false);
final ViewHolder holder=new ViewHolder(view);
holder.cardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position=holder.getAdapterPosition();
Fruit fruit=mFruitList.get(position);
Intent intent=new Intent(mContext,FruitActivity.class);
intent.putExtra(FruitActivity.FRUIT_NAME,fruit.getName());
intent.putExtra(FruitActivity.FRUIT_IMAGE_ID,fruit.getImageId());
mContext.startActivity(intent);
}
});
return holder;
}
...
}
- 這里給CardView注冊了一個點擊事件監(jiān)聽器祷膳,然后在點擊事件中獲取當前點擊項的水果名和水果資源id陶衅,傳入到Intent中,最后調(diào)用startActivity()方法中啟動
-
此時運行程序直晨,點擊任何一個按鈕
-
當拖動水果內(nèi)容的時候万哪,你會發(fā)現(xiàn)水果上的背景圖片慢慢變小,一直拖得話抡秆,標題欄就會完全折疊
此時標題欄的背景完全不見了奕巍,懸浮按鈕也會自動消失,現(xiàn)在的水果標題欄就會自動的變成普通的Toolbar
充分利用系統(tǒng)狀態(tài)欄空間
你會發(fā)現(xiàn)水果的背景圖片和系統(tǒng)的狀態(tài)欄總有一些不搭的感覺儒士,如果我們能將背景圖片和狀態(tài)欄融合到一起的止,那么就會更好了
在Android5.0系統(tǒng)之前,我們無法對狀態(tài)欄的背景或顏色進行操作的着撩,那個時候也還沒有Material Design的概念诅福。但是Android5.0及之后的系統(tǒng)都是支持這個功能的,因此這里我們就實現(xiàn)一個系統(tǒng)差異型的效果拖叙,在Android5.0及之后的系統(tǒng)中氓润,使用背景圖和狀態(tài)欄融合的模式,這之前的系統(tǒng)中使用普通模式薯鳍。
- 要想讓背景圖能夠和狀態(tài)欄融合咖气,需要借助
android:fitsSystemWindows
這個屬性來實現(xiàn)。在CoordinatorLayout挖滤、AppBarLayout崩溪、CollapsingToolbarLayout這種嵌套結(jié)構(gòu)的布局中,將控件的android:fitsSystemWindows屬性指定為true斩松,就表示該控件會出現(xiàn)在系統(tǒng)狀態(tài)欄里伶唯。對應到我們的程序中,那就是水果標題欄中的ImageView應該設置這個屬性了惧盹。不過只給ImageView設置這個屬性是沒用的乳幸,我們必須將ImageView布局中的所有父布局都設置上這個屬性才可以瞪讼,修改activity_fruit.xml中的代碼,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<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:fitsSystemWindows="true"
>
<android.support.design.widget.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="250dp"
android:fitsSystemWindows="true"
>
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed"
android:fitsSystemWindows="true"
>
<ImageView
android:id="@+id/fruit_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"
android:fitsSystemWindows="true"
/>
...
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
...
</android.support.design.widget.CoordinatorLayout>
- 但是粹断,即使我們將android:fitsSystemWindows屬性都設置好了還是沒用的符欠,因為還必須在程序的主題中將狀態(tài)欄顏色指定成透明色才行。指定成透明色的方法很簡單姿染,在主題中將android:statusBarColor屬性的值指定成@android:color/transparent就可以了背亥。但問題在于秒际,android:statusBarColor這個屬性是從API21悬赏,也就是Android5.0系統(tǒng)才有的,之前的系統(tǒng)無法使用這個屬性娄徊。那么闽颇,系統(tǒng)差異型的功能實現(xiàn)就要從這里開始了
- 右擊res目錄->New->Directory,創(chuàng)建一個values-v21目錄寄锐,然后在此目錄下創(chuàng)建一個styles.xml文件兵多。接著對這個文件進行編寫,代碼如下所示:
<resources>
<style name="FruitActivityTheme" parent="AppTheme">
<item name="android:statusBarColor">
@android:color/transparent
</item>
</style>
</resources>
- 這里我們定義了一個FruitActivityTheme主題橄仆,它是專門給FruitActivity使用的剩膘。我們在FruitActivityTheme中將狀態(tài)欄的顏色指定成透明色,由于values-v21目錄是只有Android5.0及以上系統(tǒng)才會去讀取的盆顾,因此這么聲明是沒有問題的怠褐。
- 但是Android5.0之前的系統(tǒng)卻無法識別FruitActivityTheme這個主題,因此我們還需要對values/styles.xml文件進行修改您宪,如下所示:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- 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="FruitActivityTheme." parent="AppTheme">
</style>
</resources>
- 可以看到奈懒,這里也定義了一個FruitActivityTheme主題,并且parent主題也是AppTheme宪巨,但是它的內(nèi)部是空的磷杏。
- 最后,還得讓FruitActivity使用這個主題才行捏卓,修改AndroidManifest.xml中的代碼极祸,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tool">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="山丘"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
>
...
</activity>
<activity android:name=".FruitActivity"
android:theme="@style/FruitActivityTheme">
</activity>
</application>
</manifest>
-
這里使用了 android:theme="@style/FruitActivityTHeme"指定了主題,這樣就可以了
這兩種視覺絕對不是一個檔次上的