引用依赖库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,表示会根据系统语言进行判断,如果系统语言是从做往右的,哪滑动菜单就在左边,如何系统语言是从右到左的那滑动菜单就在右边。
这里的第二个子控件我直接用的是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="[email protected]"
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);
}
}
滑动菜单界面
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();
}
});
在上面的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>
这里我用往布局中添加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消失了,而向下滚动时又出现了,这里就会在一定程度上增加用户体验感。
这是谷歌自带的下拉刷新,看下布局
<?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();
}
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第一行代码