Material Design之可折叠标题栏

本文详细介绍CollapsingToolBarLayout的使用方法,包括如何构建丰富的标题栏效果,并演示如何利用CoordinatorLayout、AppBarLayout等组件实现随滚动变化的效果。此外,还讲解了如何使背景图片与系统状态栏无缝融合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.CollapsingToolBarLayout

它是一个作用于ToolBar基础之上的布局,可以让ToolBar更丰富,不仅仅是展示一个标题栏,而是能够实现非常华丽的效果。但是CollapsingToolBarLayout不能单独存在,它必须作为AppBarLayout的直接子布局来使用,而AppBarLayout又是CoordinatorLayout的子布局。

1.1首先新建一个布局activity_fruit.xml,它有两部分,一个是水果标题栏,一个是水果内容部分,首先实现标题栏部分,这里用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: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<!--在里面主要是定义标题栏的具体内容,下面定义了一个ImageView和ToolBae,
表示高级标题栏的内容-->
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"<!--指定CollapsingToolbarLayout趋于折叠状态以及折叠之后的背景色,其实它折叠之后就是一个
普通的ToolBae,背景色即为colorPrimary-->
            app:layout_scrollFlags="scroll|exitUntilCollapsed"><!--指定随变化的效果,scroll表示CollapsingToolbarLayout随着水果内容
详情的滚动一起滚动,exitUntilCollapsed表示CollapsingToolbarLayout随着滚动完成折叠之后就保留在界面上,不再移出屏幕。-->

            <ImageView
                android:id="@+id/fruit_image_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax" /><!--指定当前控件在CoolapsingToolBarLayout折叠过程中的折叠模式,其中ToolBar指定成
pin表示在折叠过程中位置始终保持不变;指定成为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.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView<!--在这里面编写的是水果内容详情部分,指定为NestedScrollView,注意它是和AppBarLayout平级
的,NestedScrollView和ScrollView类似,允许使用滚动的方式查看屏幕以外的内容,但它还增加了嵌套响应滚动事件的功能。由于CoordinatorLayout本身可以
响应滚动事件,因此我们需要在它的内部使用NestedScrollView和RecyclerView这样的能响应的布局,所以用能响应的NestedScrollView而不是ScrollView。

        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"><!--声明布局的行为移到内部的NestedScrollView中。-->

        <LinearLayout<!--不管是NestedScrollView还是ScrollView,它的直接子布局只可以有一个,所以先嵌套一个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="35dp"
                app:cardCornerRadius="4dp">

                <TextView
                    android:id="@+id/fruit_content_text"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp" />
            </android.support.v7.widget.CardView>
        </LinearLayout>
    </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"<!--指定了一个锚点,这样它的它的位置会相对于指定的id为appBar中-->
        app:layout_anchorGravity="bottom|end" /><!--表示其位置在id为appBar的右下方-->

</android.support.design.widget.CoordinatorLayout>
    2.编写一个活动FruitActivity.java,用于展示在MainActivity.java中点击了具体的水果之后转到的内容详情:

package com.example.wanglunhui.materialdesigntest;

import android.content.Intent;
import android.graphics.Color;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

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);
        Intent intent = getIntent();
        String fruitName = intent.getStringExtra(FRUIT_NAME);//水果名
        int fruitImageId = intent.getIntExtra(FRUIT_IMAGE_ID, 0);//水果id
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        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);//将ToolBar最为ActionBar使用,所以下面的ActionBar即为ToolBar
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);//启用HomeUpAs按钮,即显示返回上一个活动的左箭头按钮,点击时相当于Finish()操作返回
上一个活动
        }
        collapsingToolbar.setTitle(fruitName);//将水果内容设置为CollapsingToolbarLayout标题
        Glide.with(this).load(fruitImageId).into(fruitImageView);//显示图片
        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();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}
    3.最后还要修改Adapter的点击Holder的点击事件才能进入FruitActivity中:

package com.example.wanglunhui.materialdesigntest;

import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

import java.util.List;

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder>{

    private Context mContext;

    private List<Fruit> mFruitList;

    static class ViewHolder extends RecyclerView.ViewHolder {
        CardView cardView;
        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(View view) {
            super(view);
            cardView = (CardView) view;
            fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
            fruitName = (TextView) view.findViewById(R.id.fruit_name);
        }
    }

    public FruitAdapter(List<Fruit> fruitList) {
        mFruitList = fruitList;
    }

    @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 v) {
                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;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitName.setText(fruit.getName());
        Glide.with(mContext).load(fruit.getImageId()).into(holder.fruitImage);
    }

    @Override
    public int getItemCount() {
        return mFruitList.size();
    }

}



2.充分利用系统状态栏空间:

    上面的运行的时候你会发现水果的背景图片会和系统状态栏不搭配,如果我呢吧能将背景图和状态栏融合在一起就更好了。要想将二者融合,需要用到android:

fitsSystemWindows这个属性来实现,在CoordinatorLayout、AppBarLayout和CollapsingToolbarLayout中将其ndroid:fitsSystemWindows设置为true。

对应于我们的程序就是ImageView设置该属性,不过单独给它设置这个属性没用,还必须设置它的所有父布局的这个属性才行,修改activity_main.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"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/fruit_image_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                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.design.widget.CollapsingToolbarLayout>
    </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="35dp"
                app:cardCornerRadius="4dp">

                <TextView
                    android:id="@+id/fruit_content_text"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp" />
            </android.support.v7.widget.CardView>
        </LinearLayout>
    </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>
    但是设置好了这个属性后还是没用,我们还需将程序中状态栏的颜色指定成透明色才行。很简单,只需将android:statusBarColor设置成@android:color/

transparent即可,但是android:statusBarColor在API21才有,所以在res下新建一个values-v21目录,在里面新建一个styles.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <style name="FruitActivityTheme" parent="AppTheme">
        <item name="android:statusBarColor">@android:color/transparent</item><!--将其状态栏的颜色指定为透明色-->
    </style>

</resources>
    这里我们定义了一个主题,它专门给FruitActivity使用的,继承了AppTheme主题的内容。

    但是Android 5.0之前的系统无法识别FruitActivityTheme这个主题,所以还需对values/styles.xml进行修改(注意不是对values-v21下面的修改):

<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主题,而且也继承自AppTheme,但是里面没有为状态栏指定颜色,因为这是对于Andorid 5.0之前的系统,所以此处

什么都不用做。

    最后我们让FruitActivity使用这个主题:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.wanglunhui.materialdesigntest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:label="修改后的名字">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".FruitActivity"
            android:theme="@style/FruitActivityTheme"/>
    </application>

</manifest>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值