android Material Design UI
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第一行代码
更多相关文章
- Android动画点击不运行
- Android(安卓)OptionsMenu 菜单
- Android(安卓)侧滑菜单的实现
- Android的MVC模式:
- Android获得控件在屏幕中的绝对坐标
- android statusbar隐藏的几种方式
- 【原创】android中实现底部tabhost
- Android(安卓)listview里面包含checkbox
- div+css命名规范 嫁接android xml命名