第一行代码第二版(郭霖著)笔记之第十二章(Material Design 实战)
来源:互联网 发布:java 数据库管理工具 编辑:程序博客网 时间:2024/05/16 03:39
1. Toolbar
- Toolbar的强大之处在于:不仅继承了ActionBar的所有功能,而且灵活性很高,可以配合其他控件来完成一些Material Design的效果。
- 新建一个项目,默认显示ActionBar,是因为项目中指定的主题含有ActionBar。
android:theme="@style/AppTheme"<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
- 准备使用Toolbar替代ActionBar,指定一个不带ActionBar的主题,通常以下两种:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">Light表示淡色主题,主体颜色淡色,陪衬颜色深色。<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">默认是深色主题,主体颜色深色,陪衬颜色淡色。
- 我们需要了解几个名词colorPrimary、colorPrimaryDark、colorAccent、textColorPrimary、windowBackground和navigationBarColor所指定的位置。
2. 编写一个Toolbar
- 布局activity_main.xml:
<?xml version="1.0" encoding="utf-8"?><FrameLayout 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.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="wrap_content" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /></FrameLayout>说明:1.xmlns:android 表示可以使用android:id等。xmlns:app 表示可以使用app:attribute。2.整体是淡色主题,Toolbar上的各种要素自动使用深色系,字体颜色是黑色。为了体验更好,借助android:theme单独设置Toolbar的主题是深色主题,这样字体颜色就会是白色。3.Toolbar单独设置为深色主题,菜单按钮弹出的菜单项也会变成深色主题,太难看,所以我们使用app:popupTheme设置菜单项为淡色主题。
- 修改MainActivity:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); }}说明:外观和功能和ActionBar一致。
- 修改标题栏上显示的文字内容
android:label="Fruits"
- 添加action按钮
新建res-menu-toolbar.xml:
<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/backup" android:icon="@drawable/ic_backup" android:title="Backup" app:showAsAction="always" /> <item android:id="@+id/delete" android:icon="@drawable/ic_delete" android:title="Delete" app:showAsAction="ifRoom" /> <item android:id="@+id/settings" android:icon="@drawable/ic_settings" android:title="Settings" app:showAsAction="never" /></menu>说明:1.showAsAction指定按钮的显示位置。always:永远显示在Toolbar中,如果屏幕空间不够则不显示;ifRoom:屏幕空间足够的情况下显示在Toolbar中,不够的话显示在菜单中;never表示永远显示在菜单当中。2.Toolbar中的action按钮只会显示图标,菜单中的action按钮只会显示文字。
- 修改MainActivity:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.toolbar,menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()){ case R.id.backup: Toast.makeText(this,"Backup",Toast.LENGTH_SHORT).show(); break; case R.id.delete: Toast.makeText(this,"Delete",Toast.LENGTH_SHORT).show(); break; case R.id.settings: Toast.makeText(this,"Settings",Toast.LENGTH_SHORT).show(); break; } return true; }}说明:之前章节有讲,这里就不再赘述。
3. 显示DrawerLayout
- 修改activity_main.xml:
<?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" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> </FrameLayout> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" android:background="#FFF" android:text="This is menu" android:textColor="#FFF00000" android:textSize="30sp" /></android.support.v4.widget.DrawerLayout>说明:1.最外层是DrawerLayout,包含两个子控件,第一个控件是FrameLayout,第二个控件是TextView,前者显示主屏幕,后者显示滑动菜单内容。2.第二个控件借助layout_gravity指定滑动出现的方式,left是左边,right是右边,start根据系统语言进行判断。
4. 主屏幕Toolbar左边添加导航按钮,实现点击显示滑动菜单
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); mDrawerlayout = (DrawerLayout) findViewById(R.id.drawer_layout); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.drawable.ic_menu); } }说明:1. 获取Drawerlayout控件的实例,用于设置滑动菜单的显示方式。2. 获取ActionBar的实例,setDisplayHomeAsUpEnabled显示导航按钮,按钮显示出来,利用setHomeAsUpIndicator设置按钮图标。
case android.R.id.home: mDrawerlayout.openDrawer(GravityCompat.START); break;说明:设置滑动菜单显示方式。
5. NavigationView
我们可以任意定制我们的滑动菜单的布局,不过谷歌提供了一个一种更好的方法——使用NavigationView,让滑动菜单页面的实现变得非常简单。
- 添加依赖:
compile 'com.android.support:design:25.3.1'compile 'de.hdodenhof:circleimageview:2.1.0'
- 创建menu菜单nav_menu:
<?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_call" android:icon="@drawable/nav_call" android:title="Call"></item> <item android:id="@+id/nav_friends" android:icon="@drawable/nav_friends" android:title="Friends"></item> <item android:id="@+id/nav_location" android:icon="@drawable/nav_location" android:title="Location"></item> <item android:id="@+id/nav_mail" android:icon="@drawable/nav_mail" android:title="Mail"></item> <item android:id="@+id/nav_task" android:icon="@drawable/nav_task" android:title="Tasks"></item> </group></menu>说明:checkableBehavior表示item只可以单选。
- 定制headerLayout,它的布局命名为nav_header:
<?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:background="?attr/colorPrimary" android:padding="10dp"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/icon_image" android:layout_width="70dp" android:layout_height="70dp" android:layout_centerInParent="true" android:src="@drawable/nav_icon" /> <TextView android:id="@+id/username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:text="fkq339@gmail.com" android:textColor="#FFF" android:textSize="14sp" /> <TextView android:id="@+id/mail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/username" android:text="Tony Green" android:textColor="#FFF" android:textSize="14sp" /></RelativeLayout>
- 修改activity_main:
<?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" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> </FrameLayout> <android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/nav_header" app:menu="@menu/nav_menu"> </android.support.design.widget.NavigationView></android.support.v4.widget.DrawerLayout>说明:之前的滑动菜单为TextView,现在用NavigationView代替TextView。利用:app:headerLayout和app:menu设置我们刚才准备好的menu和headerLayout.
- 处理点击事件
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); mDrawerlayout = (DrawerLayout) findViewById(R.id.drawer_layout); NavigationView navigationview = (NavigationView) findViewById(R.id.nav_view); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.drawable.ic_menu); } navigationview.setCheckedItem(R.id.nav_call); navigationview.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { mDrawerlayout.closeDrawer(Gravity.START); return true; } }); }说明:获取NavigationView的实例,并且设置Call菜单项为默认选中,点击后回调onNavigationItemSelected方法,这个时候我们关闭滑动菜单。
6. FloatingActionButton
- 布局:
<android.support.design.widget.FloatingActionButton app:elevation="8dp" android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:src="@drawable/ic_done" />说明:1.elevation指定的是悬浮的高度。2.layout_gravity让控件位于底部,end根据系统语言决定左边或者右边。3.layout_margin表示控件周围有空隙,更加美观。4.src 可以用一张图片展示在悬浮按钮上。
- 点击事件:
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);fab.setOnClickListener(this);说明:并没有特殊之处,它和普通的button一样。
7. Snackbar
- Snackbar不是Toast的替代品。
- Toast作用是告诉用户现在发生了什么事情,用户被动接收;而Snackbar则允许在提示的过程中加入一个可交互的按钮,当用户点击按钮的时候可以执行一些额外的逻辑操作。
- 举例子:点击按钮,执行删除的操作,Snackbar的交互就可以在点击后起到反悔的功能。
@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(MainActivity.this,"Data restored",Toast.LENGTH_SHORT).show(); } }).show(); }说明:1. Snackbar.make方法接收三个参数:第一个参数接收一个View,只要是当前布局的任意一个View就可以,Snackbar会使用这个View来自动查找最外层的布局,来展示Snackbar;第二个参数是Snackbar显示的内容;第三个参数是显示的时间。2. 接着调用setAction来执行反悔的操作。
8. CoordinatorLayout
- CoordinatorLayout是一个加强版的FrameLayout,可以监听所有子控件的各种事件,然后做出最为合理的响应。
- Snackbar提示将悬浮按钮遮挡住了,而如果能让CoordinatorLayout监听到Snackbar的弹出事件,那么它自动会将内部的FloatingActionButton向上偏移,从而确保不会被Snackbar遮挡到。
- 使用非常简单:替换下FrameLayout即可。
<android.support.design.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:src="@drawable/ic_done" app:elevation="8dp" /></android.support.design.widget.CoordinatorLayout>说明:虽然Snackbar不在CoordinatorLayout里面,但是Snackbar的make方法接收的第一个参数View是FloatingActionButton,也就是说Snackbar基于FloatingActionButton触发的。FloatingActionButton是CoordinatorLayout的子控件,自然可以监听到Snackbar。
9. CardView
CardView也是一个FrameLayout,只是额外提供了圆角和阴影等效果。以下是结合RecyclerView的示例。其中的知识点我们已经在第3章详细讲解,这里不在赘述。
- 添加依赖:
compile 'com.android.support:recyclerview-v7:25.3.1' compile 'com.android.support:cardview-v7:25.3.1' compile 'com.github.bumptech.glide:glide:3.7.0'
- 整体布局:
<android.support.design.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"></android.support.v7.widget.RecyclerView> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:src="@drawable/ic_done" app:elevation="8dp" /> </android.support.design.widget.CoordinatorLayout>
- 子项布局:
<?xml version="1.0" encoding="utf-8"?><android.support.v7.widget.CardView 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="wrap_content" android:layout_margin="5dp" android:orientation="vertical" app:cardCornerRadius="4dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <ImageView android:id="@+id/fruit_image" android:layout_width="match_parent" android:layout_height="100dp" android:scaleType="centerCrop" /> <TextView android:id="@+id/fruit_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_margin="5dp" android:textSize="16sp" /> </LinearLayout></android.support.v7.widget.CardView>说明:1.CardView没有好的定位方式,所以里面包裹一个LinearLayout。2.app:cardCornerRadius设置的是圆角的大小。3.scaleType指的是图片的缩放模式。
- 实体类
public class Fruit { private String name; private int imageId; public Fruit(String name, int imageId) { this.name = name; this.imageId = imageId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getImageId() { return imageId; } public void setImageId(int imageId) { this.imageId = imageId; }}
- FruitAdapter类
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> mFruitList) { this.mFruitList = mFruitList; } @Override public FruitAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (mContext == null) { mContext = parent.getContext(); } View view = LayoutInflater.from(mContext).inflate(R.layout.fruit_item, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(FruitAdapter.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(); }}
- MainActivity:
private Fruit[] fruits = {new Fruit("Apple", R.drawable.apple), new Fruit("Banana", R.drawable.banana), new Fruit("Orange", R.drawable.orange), new Fruit("Watermelon", R.drawable.watermelon), new Fruit("Pear", R.drawable.pear), new Fruit("Grape", R.drawable.grape), new Fruit("Pineapple", R.drawable.pineapple), new Fruit("Strawberry", R.drawable.strawberry), new Fruit("Cherry", R.drawable.cherry), new Fruit("Mango", R.drawable.mango),};private List<Fruit> fruitList = new ArrayList<>();private FruitAdapter adapter;
initFruits();RecyclerView recyclerview = (RecyclerView) findViewById(R.id.recycler_view);GridLayoutManager layoutmanager = new GridLayoutManager(this, 2);recyclerview.setLayoutManager(layoutmanager);adapter = new FruitAdapter(fruitList);recyclerview.setAdapter(adapter);
private void initFruits() { fruitList.clear(); for (int i = 0; i < 50; i++) { Random random = new Random(); int index = random.nextInt(fruits.length); fruitList.add(fruits[index]); }}
10. AppBarLayout
- CardView示例中RecyclerView遮挡住了Toolbar,因为它俩都在CoordinatorLayout中,而CoordinatorLayout是一个FrameLayout,所以造成了这个bug.
- 解决方法:借助AppBarLayout:第一步将Toolbar嵌套到AppBarLayout中,第二步给RecyclerView指定一个布局行为。
- 修改activity_main:
<android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar app:layout_scrollFlags="scroll|enterAlways|snap" android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /></android.support.design.widget.AppBarLayout><android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"></android.support.v7.widget.RecyclerView>说明:1.RecyclerView借助app:layout_behavior属性指定一个布局行为,目的是建立Toolbar和RecyclerView之间的关联。2.借助app:layout_behavior,Toolbar在接收到RecyclerView滚动事件的时候,会进行相应的操作。3.scroll表示Recy向上滚动的时候,Toolbar会跟着一起向上滚动并实现隐藏;enterAlwys表示Recy向下滚动的时候,Toolbar会跟着一起向下滚动并重新显示。snap表示当Toolbar还没有完全隐藏或显示的时候,会根据当前滚动的距离,自动选择是隐藏还是显示。
11. SwipeRefreshLayout
- 把想要实现下拉刷新功能的控件放置到SwipeRefreshLayout中,就可以迅速让这个控件支持下拉刷新。app:layout_behavior要放在SwipeRefreshLayout中。
<android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipe_refresh" 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="match_parent"></android.support.v7.widget.RecyclerView> </android.support.v4.widget.SwipeRefreshLayout>
- 修改MainActiivty,处理刷新逻辑
swiperefreshlayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh); swiperefreshlayout.setColorSchemeColors(getResources().getColor(R.color.colorPrimary)); swiperefreshlayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { refreshFruits(); } });private void refreshFruits() { new Thread(new Runnable() { @Override public void run() { try{ Thread.sleep(2000); }catch (InterruptedException e){ e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { initFruits(); adapter.notifyDataSetChanged(); swiperefreshlayout.setRefreshing(false); } }); } }).start(); }说明:1. setColorSchemeColors 处理下拉刷新的颜色。2. onRefresh处理具体的刷新逻辑。3. adapter.notifyDataSetChanged()通知页面刷新。4. setRefreshing隐藏下拉刷新。
12. CollapsingToolbarLayout
- 借助CollapsingToolbarLayout可根据自己的喜好随意定制出标题栏的样式,让Toolbar更加丰富,不仅仅是展示一个标题栏,而是能够实现非常华丽的效果。
CollapsingToolbarLayout不能独立存在,它在设计的时候就被限定只能作为AppBarLayout的直接子布局来使用。而AppBarLayout又必须是CoordinatorLayout的子布局。
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:orientation="vertical"> <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|exitUntilCollapsed"> <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>说明:1. ThemeOverlay.AppCompat.Dark.ActionBar是一个深色的主题,保证字体颜色是浅色系。2. contentScrim用于指定趋于折叠状态以及折叠以后的背景色。CollapsingToolbarLayout折叠之后就是一个普通的Toolbar,背景色是colorPrimary.3. layout_scrollFlags:scroll表示CollapsingToolbarLayout会随着水果内容详情的滚动一起滚动,exitUntilCollapsed表示当CollapsingToolbarLayout随着滚动完成折叠之后就保留在界面上,不再移出屏幕。4. 高级版的标题栏是由普通的标题栏加上图片组合而成的。5. layout_collapseMode 用于指定CollapsingToolbarLayout折叠过程中的折叠模式,其中Toolbar指定成pin,表示在折叠的过程中位置始终不变,ImageView指定成parallax,表示在折叠过程中产生一定的错误偏移。
- activity_main 水果内容详情部分:
<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="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="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" /> </android.support.v7.widget.CardView> </LinearLayout> </android.support.v4.widget.NestedScrollView>说明:1. NestedScrollView除了具有ScrollView的功能之外,还具有嵌套响应滚动事件的功能,并且指定了布局行为,向CoodinatorLayout传递滚动事件。2. NestedScrollView只能有一个子布局,我们添加一个LinearLayout,里面是一个卡片式布局,布局里面是一个TextView,显示水果的内容详情。
- 添加FloatingActionButton:
<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" />说明:1. FloatingActionButton和AppBarLayout以及NestedScrollView是平级的。2. layout_anchor指定一个锚点,将锚点设置为AppBarLayout,这样悬浮按钮就会出现在水果标题栏的区域内。3. layout_anchorGravity将悬浮按钮定位在标题栏区域的右下角。
- FruitActivity:
public class FruitActivity extends AppCompatActivity { private static final String FRUIT_NAME = "fruit_name"; private static final String FRUIT_IMAGE_ID = "fruit_image_id"; @Override protected void onCreate(@Nullable 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); 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); ActionBar actionbar = getSupportActionBar(); if (actionbar != null) { actionbar.setDisplayHomeAsUpEnabled(true); } collapsingToolbar.setTitle(fruitName); Glide.with(this).load(fruitImageId).into(fruitImageView); String fruitContext = generateFruitContext(fruitName); } private String generateFruitContext(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); }}说明:1. 通过intent获取传入的水果名称和水果图片的资源id,然后通过fv拿到布局文件中各个控件的实例。显示Toolbar,启用HomeAsUp按钮。2. collapsingToolbar的setTilte设置当前页面的标题;使用Glide加载传入的水果图片。 onOptionsItemSelected方法中处理了HOMEASUP按钮的点击事件。
- 修改FruitAdapter,设置点击事件:
@Override public FruitAdapter.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(); Log.e("FruitAdapter","position:"+position); 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; }说明:通过Intent传递数据启动FruitActivity。
13. 充分利用系统状态栏空间
- 借助android:fitsSystemWindows=”true”这个属性实现背景图和状态栏的有效融合:
<?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:fitsSystemWindows="true" android:layout_height="match_parent" android:orientation="vertical"> <android.support.design.widget.AppBarLayout android:fitsSystemWindows="true" android:id="@+id/appBar" android:layout_width="match_parent" android:layout_height="250dp"> <android.support.design.widget.CollapsingToolbarLayout android:fitsSystemWindows="true" 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|exitUntilCollapsed"> <ImageView android:fitsSystemWindows="true" android:id="@+id/fruit_image_view" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" app:layout_collapseMode="parallax" />说明:1. ImageView以及父类标签都要指定属性。
指定状态栏颜色为透明色并且区分版本:
- 设置状态栏颜色为透明色是从Android 5.0系统开始才有的,之前的系统无法指定这个属性,所以需要区别对待。
- 创建values-v21目录,新建style.xml的resource file:
<resources> <style name="FruitActivityTheme" parent="AppTheme"> <item name="android:statusBarColor">@android:color/transparent</item> </style></resources>说明:1.values-v21只有5.0才可以读取。2.FruitActivityTheme专门给FruitActivity使用,parent主题是AppTheme,也就是说它继承了AppTheme的所有特性。3.指定FruitActivityTheme为透明色。
3.values-styles.xml指定FruitActivity的5.0之前的主题设置:
<style name="FruitActivityTheme" parent="AppTheme"></style>说明:5.0之前无法指定状态栏的颜色,这里什么都不做即可。
4.配置FruitActivity主题
<activity android:name=".FruitActivity" android:theme="@style/FruitActivityTheme"></activity>
阅读全文
1 0
- 第一行代码第二版(郭霖著)笔记之第十二章(Material Design 实战)
- 第一行代码读书笔记-第十二章 Material Design实战
- 第一行代码第二版(郭霖著)笔记之第二章(探究活动)
- 第二行代码学习笔记——第十二章:最佳的 UI 体验——Material Design 实战
- 第一行代码第二版(郭霖著)笔记之第五章(详解广播机制)
- 第一行代码第二版(郭霖著)笔记之第三章(UI开发的点点滴滴)
- 第一行代码第二版(郭霖著)笔记之第六章(详解持久化技术)
- 第一行代码第二版(郭霖著)笔记之第十一章(百度地图)
- 第一行代码第二版(郭霖著)笔记之第一章(你的第一行Android代码)
- Material Design 学习之Toolbar(第二行代码笔记)
- 第一行代码(第二版)读书笔记
- 第一行代码学习笔记 第二章
- 《第一行代码》第一章、第二章笔记
- Android学习笔记之Material Design实战
- 第一行代码 之 第二篇代码笔记
- 第一行代码+Android+第2版 笔记第二天
- 第一行代码,第十二章-------传感器探究
- 《第一行代码(第二版)》的学习(一)
- 数据结构课程设计实战
- retrofit详细使用
- 比特币开发专题(区块链内核密钥、地址、钱包)
- 数据导出excel
- linux 重启命令
- 第一行代码第二版(郭霖著)笔记之第十二章(Material Design 实战)
- iis部署网站(asp.net或者wcf)出现HTTP 错误 404.17
- BZOJ 3667 Rabin-Miller算法
- centos7 安装java1.8
- printf函数调用的一般形式
- JavaScript基础部分(二)
- KVC、KVO小结
- [YTU]_2637(编程题:类---矩形类)
- Java代码优化六大原则