android Material Design UI

1.DrawerLayout的用法

引用依赖库com.github.bumptech.glide:glide是一个超级强大的图片加载库,它不仅用于本地加载,还可以用于加载网络图片、GIF图片、甚至本地视频。这里我用来加载本地图片

 implementation 'com.android.support:design:28.0.0' implementation 'com.android.support:recyclerview-v7:28.0.0' implementation 'com.android.support:cardview-v7:28.0.0' implementation 'com.github.bumptech.glide:glide:4.9.0'

首先DrawerLayout是个布局,在布局中允许放入两个直接控件,第一个子控件是主屏幕中显示的内容,
第二个子控件是滑动菜单中显示的内容。

<?xml version="1.0" encoding="utf-8"?><android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/drawer_layout"    android:layout_width="match_parent"    android:layout_height="match_parent">     <FrameLayout        android:layout_width="match_parent"        android:layout_height="match_parent">        <android.support.v7.widget.Toolbar                android:id="@+id/toolbar"                style="@style/baseToolbar"                android:background="?attr/colorPrimary"                android:theme="@style/toolbarTheme"                app:layout_scrollFlags="scroll|enterAlways|snap"                app:navigationIcon="@drawable/ic_arrow_back_white_24dp"                app:popupTheme="@style/popupTheme"                app:title="滑动菜单"                app:titleTextAppearance="@style/Toolbar.TitleText">    </FrameLayout>     <android.support.design.widget.NavigationView        android:id="@+id/navigation"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_gravity="start"        android:elevation="8dp"        app:headerLayout="@layout/nav_layout"        app:menu="@menu/nav_menu" /></android.support.v4.widget.DrawerLayout>

别忘了给布局中添加xmlns:app="http://schemas.android.com/apk/res-auto"命名空间
关于第二个子控件我们需要注意一点layout_gravity这个属性是必须定义的,因为我们需要告诉DrawerLayout滑动菜单时在屏幕的左边还是右边,指定left表示滑动菜单在左边,指定right表示滑动菜单在右边,我这里用了start,表示会根据系统语言进行判断,如果系统语言是从做往右的,哪滑动菜单就在左边,如何系统语言是从右到左的那滑动菜单就在右边。

1.2 NavigationView

这里的第二个子控件我直接用的是NavigationView用于滑动菜单,其中app:headerLayout和app:menu属性指向了是头部布局和menu文件下的item

滑动菜单的头部nav_layout

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="180dp"    android:padding="10dp"    android:background="?attr/colorPrimary">    <de.hdodenhof.circleimageview.CircleImageView        android:id="@+id/icon_image"        android:layout_width="70dp"        android:layout_height="70dp"        android:src="@mipmap/timg"        android:layout_centerInParent="true"/>    <LinearLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:orientation="vertical"        android:layout_alignParentBottom="true"        >        <TextView            android:id="@+id/tv_mail"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="tongygreendev@gall.com"            android:textColor="#fff"            android:textSize="14sp"/>        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="Tony Green"            android:layout_below="@+id/tv_mail"            android:textColor="#fff"            android:textSize="14sp"            />    </LinearLayout></RelativeLayout>

menu文件下nav_menu,用户滑动菜单下的item

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android"><group android:checkableBehavior="single">    <item        android:id="@+id/nav_all"        android:icon="@mipmap/call"        android:title="Call" />    <item        android:id="@+id/nav_friends"        android:icon="@mipmap/friends"        android:title="friends" />    <item        android:id="@+id/nav_location"        android:icon="@mipmap/location"        android:title="location" />    <item        android:id="@+id/nav_mail"        android:icon="@mipmap/mail"        android:title="mail" />    <item        android:id="@+id/nav_task"        android:icon="@mipmap/task"        android:title="task" /></group></menu>

下面是实现滑动菜单的代码,代码都做了注释,这样就实现了一个简单的滑动菜单

public class DrawerLayoutDemo extends AppCompatActivity {    private DrawerLayout drawer_layout;    private Toolbar toolbar;    private NavigationView navigationView;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.drawerlayout_demo);        initView(); //绑定控件        setSupportActionBar(toolbar);//将toolbar实列传入setSupportActionBar方法中        toolbar.setNavigationOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                drawer_layout.openDrawer(GravityCompat.START);//openDrawer方法中传入一个Gravity参数,为了保证这里的行为和xml的一致,我传入了GravityCompat.START            }        });        navigationView.setCheckedItem(R.id.nav_all);//默认选中的item        //对滑动菜单中的Item进行监听        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {            @Override            public boolean onNavigationItemSelected(@NonNull MenuItem item) {                drawer_layout.closeDrawers();//将滑动菜单关闭                switch (item.getItemId()){                    case R.id.nav_task:                        Toast.makeText(DrawerLayoutDemo.this,"Data deleted",Toast.LENGTH_SHORT).show();                        break;                }                return true;            }        });    }    //绑定控件    private void initView() {        drawer_layout=findViewById(R.id.drawer_layout);        toolbar=findViewById(R.id.toolbar);        navigationView=findViewById(R.id.navigation);    }}

滑动菜单界面

1.3 FloatingActionButton悬浮按钮和可交互提示

3.1FloatingActionButton

<?xml version="1.0" encoding="utf-8"?><android.support.v4.widget.DrawerLayout 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:id="@+id/drawer_layout">    <FrameLayout        android:layout_width="match_parent"        android:layout_height="match_parent">        <android.support.v7.widget.Toolbar            android:id="@+id/toolbar"            style="@style/baseToolbar"            android:background="?attr/colorPrimary"            android:theme="@style/toolbarTheme"            app:layout_scrollFlags="scroll|enterAlways|snap"            app:navigationIcon="@mipmap/more_z"            app:popupTheme="@style/popupTheme"            app:title="滑动菜单"            app:titleTextAppearance="@style/Toolbar.TitleText">        </android.support.v7.widget.Toolbar>        <android.support.design.widget.FloatingActionButton            android:id="@+id/floating"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_margin="16dp"            android:layout_gravity="bottom|end"/>    </FrameLayout>    <android.support.design.widget.NavigationView        android:id="@+id/navigation"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_gravity="start"        android:elevation="8dp"        app:headerLayout="@layout/nav_layout"        app:menu="@menu/nav_menu" /></android.support.v4.widget.DrawerLayout>

app:elevation属性是给FloatingActionButton指定一个高度值,高度越大,投影范围也越大,但是投影效果越淡,高度值越小,投影范围越小,但投影效果越浓,推荐使用默认效果就够了
floatingActionButton.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#F0625E")))//设置颜色
FloatingActionButton点击使事件,其实FloatingActionButton的点击事件和普通的button没什么两样,都是调用setOnClickListener()方法来注册一个监听器当点击按钮时,就会执行监听器中的onClick()方法

    floating.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Snackbar.make(v,"Data deleted",Snackbar.LENGTH_SHORT)                        .setAction("Undo", new View.OnClickListener() {                            @Override                            public void onClick(View v) {                                Toast.makeText(DrawerLayoutActivity.this,"Data deleted",Toast.LENGTH_SHORT).show();                            }                        }).show();            }        });

1.4 CoordinatorLayout

在上面的FloatingActionButton监听器中监听Snackbar,可以看到这里调用了Snackbar.make()方法来创建一个Snackbar对象,make()方法的第一个参数需要一个view,只要是当前布局的任意一个view都可以,Snackbar会使用这个view来自动查找最外层的布局,用于展示Snackbar。第二个参数就是Snackbar中显示的内容,第三个参数是Snackbar显示的时长,和Toast类似。
当允许是我们发现Snackbar从屏幕底部出现,但这里我们发现Snackbar竟然将FloatingActionButton的悬浮按钮遮掩注了,这里我借助于CoordinatorLayout布局就可以轻松解决,把FrameLayout换成CoordinatorLayout我们在运行就会发现FloatingActionButton跟随向上移动了

CoordinatorLayout可以说是一个FrameLayout的加强版,CoordinatorLayout可以监听其所有的子控件各种事件,然后自动做出最为合理的响应,就像刚才Snackbar提示,而如果使用CoordinatorLayout监听CoordinatorLayout的弹出事件,那么他会自动将内部的FloatingActionButton向上偏移,从而不会被Snackbar遮挡

  <?xml version="1.0" encoding="utf-8"?><android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/drawer_layout"    android:layout_width="match_parent"    android:layout_height="match_parent">    <android.support.design.widget.CoordinatorLayout        android:layout_width="match_parent"        android:layout_height="match_parent">        <android.support.design.widget.AppBarLayout            android:layout_width="match_parent"            android:layout_height="wrap_content">        </android.support.design.widget.AppBarLayout>        <android.support.v4.widget.SwipeRefreshLayout            android:id="@+id/swipeRefreshLayout"            android:layout_width="match_parent"            android:layout_height="match_parent"            app:layout_behavior="@string/appbar_scrolling_view_behavior">            <android.support.v7.widget.RecyclerView                android:id="@+id/recycler_view"                android:layout_width="match_parent"                android:layout_height="wrap_content">            </android.support.v7.widget.RecyclerView>        </android.support.v4.widget.SwipeRefreshLayout>        <android.support.design.widget.FloatingActionButton            android:id="@+id/floating"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="bottom|end"            android:layout_margin="16dp"            android:src="@mipmap/floating" />    </android.support.design.widget.CoordinatorLayout>    <android.support.design.widget.NavigationView        android:id="@+id/navigation"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_gravity="start"        android:elevation="8dp"        app:headerLayout="@layout/nav_layout"        app:menu="@menu/nav_menu" /></android.support.v4.widget.DrawerLayout>

2.卡片式布局

这里我用往布局中添加RecyclerView,用于展示卡片式布局的效果

<?xml version="1.0" encoding="utf-8"?><android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/drawer_layout"    android:layout_width="match_parent"    android:layout_height="match_parent">    <android.support.design.widget.CoordinatorLayout        android:layout_width="match_parent"        android:layout_height="match_parent">            <android.support.v7.widget.Toolbar                android:id="@+id/toolbar"                style="@style/baseToolbar"                android:background="?attr/colorPrimary"                android:theme="@style/toolbarTheme"                app:layout_scrollFlags="scroll|enterAlways|snap"                app:navigationIcon="@drawable/ic_arrow_back_white_24dp"                app:popupTheme="@style/popupTheme"                app:title="滑动菜单"                app:titleTextAppearance="@style/Toolbar.TitleText">            </android.support.v7.widget.Toolbar>                        <android.support.v7.widget.RecyclerView                android:id="@+id/recycler_view"                android:layout_width="match_parent"                android:layout_height="wrap_content">            </android.support.v7.widget.RecyclerView>        <android.support.design.widget.FloatingActionButton            android:id="@+id/floating"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="bottom|end"            android:layout_margin="16dp"            android:src="@mipmap/floating" />    </android.support.design.widget.CoordinatorLayout>    <android.support.design.widget.NavigationView        android:id="@+id/navigation"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_gravity="start"        android:elevation="8dp"        app:headerLayout="@layout/nav_layout"        app:menu="@menu/nav_menu" /></android.support.v4.widget.DrawerLayout>

创建一个用于android.support.v7.widget.RecyclerView的item.xml

<?xml version="1.0" encoding="utf-8"?><android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/carView"    android:layout_width="match_parent"    android:layout_height="wrap_content"    xmlns:app="http://schemas.android.com/apk/res-auto"    app:cardCornerRadius="4dp"    android:layout_margin="5dp">    <LinearLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center_horizontal"        android:padding="5dp"        android:orientation="vertical">        <ImageView            android:id="@+id/image"            android:layout_width="wrap_content"            android:layout_height="100dp" />        <TextView            android:id="@+id/tv_name"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center_horizontal"            />    </LinearLayout></android.support.v7.widget.CardView>

这里的item布局我的父级控件直接就式android.support.v7.widget.CardView,用于卡片式布局,放了ImageView和TextView,之后我们来写RecyclerView的适配器

public class GardBean implements Serializable {    private int image;//图片ID    private String name;//图片名字    public GardBean() {    }    public GardBean(int image, String name) {        this.image = image;        this.name = name;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getImage() {        return image;    }    public void setImage(int image) {        this.image = image;    }}
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.Hanlder> {    private List<GardBean> gardBeans;    private Context context;    public RecyclerAdapter(List<GardBean> gardBeans, Context context) {        this.gardBeans = gardBeans;        this.context = context;    }    @NonNull    @Override    public Hanlder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {        if (context==null){            context=parent.getContext();        }        View view = LayoutInflater.from(context).inflate(R.layout.item_gardview, parent, false);        final Hanlder hanlder = new Hanlder(view);        //这里式对RecyclerView的点击事件监听,跳转到折叠式标题栏        hanlder.gardView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                int position=hanlder.getAdapterPosition();//获取position                GardBean gardBean=gardBeans.get(position);                Intent intent=new Intent(context,GardDateActivity.class);                intent.putExtra(GardDateActivity.FRUIT_NAME,gardBean.getName());                intent.putExtra(GardDateActivity.FRUIT_IMAGE_ID,gardBean.getImage());                context.startActivity(intent);            }        });        return hanlder;    }    @Override    public void onBindViewHolder(@NonNull Hanlder holder, int position) {        GardBean gardBean = gardBeans.get(position);        holder.imageView.setImageResource(gardBean.getImage());        holder.name.setText(gardBean.getName());        Glide.with(context).load(gardBean.getImage()).into(holder.imageView);    }    @Override    public int getItemCount() {        return gardBeans.size();    }    public class Hanlder extends RecyclerView.ViewHolder {        private ImageView imageView;        private TextView name;        private CardView gardView;        public Hanlder(View itemView) {            super(itemView);            imageView = itemView.findViewById(R.id.image);            name = itemView.findViewById(R.id.tv_name);            gardView=itemView.findViewById(R.id.carView);        }    }}

添加适配器

private RecyclerAdapter adapter;private GardBean[] gardBeans={new GardBean(R.mipmap.timg,"timg"),new GardBean(R.mipmap.timg_e,"timg_e")    ,new GardBean(R.mipmap.timg_b,"timg_b"),new GardBean(R.mipmap.timg_c,"timg_c"),     new GardBean(R.mipmap.timg_f,"timg_f")};//以数组的形式添加实例private List<GardBean> gardBeanList=new ArrayList<>();private RecyclerView recycler_view; @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {      recycler_view= findViewById(R.id.recycler_view);      initGardBean();      adapter=new RecyclerAdapter(gardBeanList,DrawerLayoutActivity.this);      GridLayoutManager gridLayoutManager=new GridLayoutManager(DrawerLayoutActivity.this,2);      recycler_view.setLayoutManager(gridLayoutManager);//添加布局形式      recycler_view.setAdapter(adapter);//添加适配器    }//由于图片少不好看,这里就做了个循环50次,随机出现图片 private void initGardBean(){        gardBeanList.clear();//清空list        for (int i=0;i<50;i++){            Random random=new Random();//随机出现图片            int index=random.nextInt(gardBeans.length);            gardBeanList.add(gardBeans[index]);//添加到list中        }    }

这里注意一下可以看到我们的布局Toolbar被RecyclerView遮挡了,一般我们是使用偏移,即让RecyclerView向下偏移一个Toolbar的高度,从而保证不会遮挡注标题栏,不过我们使用的是CoordinatorLayout,因此有一些更加巧妙的解决方式,这里我们引用android.support.design.widget.AppBarLayout,这是Design Support库提供的另一个工具,AppBarLayout实际上是一个垂直方向的LinearLayout,内部做了很多滚动事件的封装,并应用了一些Material Design设计理念

<?xml version="1.0" encoding="utf-8"?><android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/drawer_layout"    android:layout_width="match_parent"    android:layout_height="match_parent">    <android.support.design.widget.CoordinatorLayout        android:layout_width="match_parent"        android:layout_height="match_parent">        <android.support.design.widget.AppBarLayout            android:layout_width="match_parent"            android:layout_height="wrap_content">            <android.support.v7.widget.Toolbar                android:id="@+id/toolbar"                style="@style/baseToolbar"                android:background="?attr/colorPrimary"                android:theme="@style/toolbarTheme"                app:layout_scrollFlags="scroll|enterAlways|snap"                app:navigationIcon="@drawable/ic_arrow_back_white_24dp"                app:popupTheme="@style/popupTheme"                app:title="滑动菜单"                app:titleTextAppearance="@style/Toolbar.TitleText">            </android.support.v7.widget.Toolbar>        </android.support.design.widget.AppBarLayout>            <android.support.v7.widget.RecyclerView                android:id="@+id/recycler_view"                android:layout_width="match_parent"                android:layout_height="wrap_content"                app:layout_behavior="@string/appbar_scrolling_view_behavior">            </android.support.v7.widget.RecyclerView>        <android.support.design.widget.FloatingActionButton            android:id="@+id/floating"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="bottom|end"            android:layout_margin="16dp"            android:src="@mipmap/floating" />    </android.support.design.widget.CoordinatorLayout>    <android.support.design.widget.NavigationView        android:id="@+id/navigation"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_gravity="start"        android:elevation="8dp"        app:headerLayout="@layout/nav_layout"        app:menu="@menu/nav_menu" /></android.support.v4.widget.DrawerLayout>

可以看到上面的xml布局中给Toolbar添加父级控件,把Toolbar嵌套在AppBarLayout中,然后在RecyclerView使用app:layout_behavior属性指定一个布局行为。app:layout_behavior="@string/appbar_scrolling_view_behavior"字符串是Design Support库提供的,之后运行就会发现RecyclerView没用遮挡标题栏了,而我们向上滚动的时候发现Toolbar消失了,而向下滚动时又出现了,这里就会在一定程度上增加用户体验感。

2.1 SwipeRefreshLayout谷歌自带的刷新

这是谷歌自带的下拉刷新,看下布局

<?xml version="1.0" encoding="utf-8"?><android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/drawer_layout"    android:layout_width="match_parent"    android:layout_height="match_parent">    <android.support.design.widget.CoordinatorLayout        android:layout_width="match_parent"        android:layout_height="match_parent">        <android.support.design.widget.AppBarLayout            android:layout_width="match_parent"            android:layout_height="wrap_content">            <android.support.v7.widget.Toolbar                android:id="@+id/toolbar"                style="@style/baseToolbar"                android:background="?attr/colorPrimary"                android:theme="@style/toolbarTheme"                app:layout_scrollFlags="scroll|enterAlways|snap"                app:navigationIcon="@drawable/ic_arrow_back_white_24dp"                app:popupTheme="@style/popupTheme"                app:title="滑动菜单"                app:titleTextAppearance="@style/Toolbar.TitleText">            </android.support.v7.widget.Toolbar>        </android.support.design.widget.AppBarLayout>        <android.support.v4.widget.SwipeRefreshLayout            android:id="@+id/swipeRefreshLayout"            android:layout_width="match_parent"            android:layout_height="match_parent"            app:layout_behavior="@string/appbar_scrolling_view_behavior">            <android.support.v7.widget.RecyclerView                android:id="@+id/recycler_view"                android:layout_width="match_parent"                android:layout_height="wrap_content">            </android.support.v7.widget.RecyclerView>        </android.support.v4.widget.SwipeRefreshLayout>        <android.support.design.widget.FloatingActionButton            android:id="@+id/floating"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="bottom|end"            android:layout_margin="16dp"            android:src="@mipmap/floating" />    </android.support.design.widget.CoordinatorLayout>    <android.support.design.widget.NavigationView        android:id="@+id/navigation"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_gravity="start"        android:elevation="8dp"        app:headerLayout="@layout/nav_layout"        app:menu="@menu/nav_menu" /></android.support.v4.widget.DrawerLayout>

可以看到 这里的RecyclerView外面嵌套了一层SwipeRefreshLayout,这样RecyclerView就自动拥有了下拉刷新的功能了,另注意,由于RecyclerView现在变成了SwipeRefreshLayout的子控件,因此app:layout_behavior属性的生命布局的行为也要移动到SwipeRefreshLayout中才行

//swipeRefreshLayout调用刷新的方法setOnRefreshListener()swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {            @Override            public void onRefresh() {                refreshGardBean();            }        });        //由于是本地图片加载太快,可能看不见刷新效果,这就做了个延迟2秒的效果 private void refreshGardBean(){        new Thread(new Runnable() {            @Override            public void run() {                try {                    Thread.sleep(2000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                runOnUiThread(new Runnable() {                    @Override                    public void run() {                        initGardBean();                        adapter.notifyDataSetChanged();//通知适配器刷新                        swipeRefreshLayout.setRefreshing(false);                    }                });            }        }).start();    }

3 可折叠式标题栏

3.1 CollapsingToolbarLayout

CollapsingToolbarLayout是一个作用于Toolbar基础之上的布局,由Design Support库提供,CollapsingToolbarLayout可以让Toolbar的效果变得更加丰富。
CollapsingToolbarLayout是不能独立存在的,他在设计的时候就被限定只能作为AppBarLayout的直接子布局在使用,而AppBarLayout又必须是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:fitsSystemWindows="true"        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"            android:fitsSystemWindows="true"            app:layout_scrollFlags="scroll|exitUntilCollapsed">            <ImageView                android:id="@+id/icon_image"                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:layout_width="match_parent"                android:layout_height="?attr/actionBarSize"                android:id="@+id/toolbar"                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布局中 android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"设置指定主题,app:layout_scrollFlags=“scroll|exitUntilCollapsed”,scroll表示CollapsingToolbarLayout会随着内容详情一起滚动,exitUntilCollapsed表示当CollapsingToolbarLayout随着滚动完成折叠之后就保持在界面上,不在移除屏幕。
CollapsingToolbarLayout中定义了一个ImageView和Toolbar,也就是标题栏将是由普通的标题栏加上图片组合而成,app:layout_collapseMode属性,指定当前控件在CollapsingToolbarLayout折叠过程中的折叠模式,Toolbar指定成pin,表示在折叠的过程中位置始终保持不变,ImageView指定成parallax,表示在折叠的过程中产生一定的错位偏移。

设置内容详情布局

<?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:fitsSystemWindows="true"        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"            android:fitsSystemWindows="true"            app:layout_scrollFlags="scroll|exitUntilCollapsed">            <ImageView                android:id="@+id/icon_image"                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:layout_width="match_parent"                android:layout_height="?attr/actionBarSize"                android:id="@+id/toolbar"                app:layout_collapseMode="pin">            </android.support.v7.widget.Toolbar>        </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:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="vertical">            <android.support.v7.widget.CardView                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_marginBottom="150dp"                android:layout_marginLeft="15dp"                android:layout_marginRight="15dp"                android:layout_marginTop="35dp"                app:cardCornerRadius="4dp">                <TextView                    android:id="@+id/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>

最外层布局使用NestedScrollView,注意它和AppBarLayout是平级的,app:layout_behavior属性指定布局行为,
不管ScrollView还是NestedScrollView,它的内部都只允许存在一个直接子布局,这里的子布局是LinearLayout。而在其中把TextView存放在卡片式布局中显示。

下面这里在添加一个FloatingActionButton悬浮按钮表示评论按钮,他和NestedScrollView、AppBarLayout是平级,FloatingActionButton中使用app:layout_anchor属性指定一个锚点,描点指向AppBarLayout,这样悬浮按钮就会出现在标题栏区域内,app:layout_anchorGravity属性将悬浮按钮定位在标题栏区域右下角

<?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:fitsSystemWindows="true"        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"            android:fitsSystemWindows="true"            app:layout_scrollFlags="scroll|exitUntilCollapsed">            <ImageView                android:id="@+id/icon_image"                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:layout_width="match_parent"                android:layout_height="?attr/actionBarSize"                android:id="@+id/toolbar"                app:layout_collapseMode="pin">            </android.support.v7.widget.Toolbar>        </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:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="vertical">            <android.support.v7.widget.CardView                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_marginBottom="150dp"                android:layout_marginLeft="15dp"                android:layout_marginRight="15dp"                android:layout_marginTop="35dp"                app:cardCornerRadius="4dp">                <TextView                    android:id="@+id/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.FloatingActionButton        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_margin="16dp"        app:layout_anchor="@id/appBar"        app:layout_anchorGravity="bottom|end">    </android.support.design.widget.FloatingActionButton></android.support.design.widget.CoordinatorLayout>

代码块

public class GardDateActivity extends AppCompatActivity {    public static final String FRUIT_NAME = "fruit_name";    public static final String FRUIT_IMAGE_ID = "fruit_image_id";    private Toolbar toolbar;    private CollapsingToolbarLayout collapsing_toolbar;    private ImageView icon_image;    private TextView content_text;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.gardview_layout_date);        Intent intent = getIntent();        String fruitName = intent.getStringExtra(FRUIT_NAME);        int fruitImageId = intent.getIntExtra(FRUIT_IMAGE_ID,0);        toolbar = findViewById(R.id.toolbar);        collapsing_toolbar = findViewById(R.id.collapsing_toolbar);        icon_image = findViewById(R.id.icon_image);        content_text = findViewById(R.id.content_text);        setSupportActionBar(toolbar);        ActionBar actionBar = getSupportActionBar();        if (actionBar != null) {            actionBar.setDisplayHomeAsUpEnabled(true);        }        collapsing_toolbar.setTitle(fruitName);        Glide.with(this).load(fruitImageId).into(icon_image);        String fruitContent = generateFruitContent(fruitName);        content_text.setText(fruitContent);    }    private String generateFruitContent(String fruitName) {        StringBuffer stringBuffer = new StringBuffer();        //循环名字500次由于简介内容        for (int i = 0; i < 500; i++) {            stringBuffer.append(fruitName);        }        return stringBuffer.toString();    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {        switch (item.getItemId()) {            case android.R.id.home://点击事件监听返回                finish();                return true;        }        return super.onOptionsItemSelected(item);    }}

这里FRUIT_NAME 和 FRUIT_IMAGE_ID是用来定义为图片id和名字的,在之前的适配器中用Intent传值过来


Demo链接
https://github.com/only95/TemoDemo
注:参考书籍Android第一行代码

更多相关文章

  1. Android动画点击不运行
  2. Android(安卓)OptionsMenu 菜单
  3. Android(安卓)侧滑菜单的实现
  4. Android的MVC模式:
  5. Android获得控件在屏幕中的绝对坐标
  6. android statusbar隐藏的几种方式
  7. 【原创】android中实现底部tabhost
  8. Android(安卓)listview里面包含checkbox
  9. div+css命名规范 嫁接android xml命名

随机推荐

  1. Android Studio对话框登录。。。
  2. 来往 android客户端发布
  3. android属性android:stateNotNeeded
  4. [Android JNI] JNI Types and Data Struc
  5. android启动模式
  6. Android 计算器界面的实现
  7. Android clipChildren用法
  8. AndroidStudio开发flutter之环境配置
  9. 搭建android的开发环境
  10. Android 用网络图片做帧动画