本节我们继续在前面的基础上进行改进,加入下拉刷新功能,该功能的实现需要使用SwipeRefreshLayout,对谁使用呢?当然是我们的RecycleView控件啦!
修改activity_main.xml代码,在RecycleView外面嵌套一层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.v4.widget.SwipeRefreshLayout>
这样RecycleView就有了下拉刷新的功能了,这里要注意的是,现在RecycleView成了SwipeRefreshLayout的子控件,所以之前的app:layout_behavior="@string/appbar_scrolling_view_behavior
要移到SwipeRefreshLayout中。
接着在MainActivity中处理具体的刷新逻辑:
在MainActivity中加入:
private SwipeRefreshLayout swipeRefreshLayout;
...
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();
}
在onCreate()中加入代码:
swipeRefreshLayout=(SwipeRefreshLayout)findViewById(R.id.swipe_refresh);
swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener(){
@Override
public void onRefresh() {
refreshFruits();
}
});
其中setColorSchemeResources
是设置进度条的颜色,好了,做完这些后运行程序并下拉就会出现一个停留两秒钟的进度条,同时水果数据也会刷新!
这里我们需要用到的是CollapsingToolbarLayout,它是一个作用于Toolbar的布局,可以让Toolbar的效果变的更加丰富,但是它不能独立存在,只能作为AppBarLayout的直接子布局使用,而AppBarLayout又必须是CoordinatorLayout的子布局!
首先做一个用于展示水果详情信息的界面,新建一个FruitActivity,并在其布局文件activity_fruit.xml中添加以下代码:
<!--CoordinatorLayout相当于一个加强版的FrameLayout,可以监听其所有子控件的各种事件,并自动做出最优化的响应-->
<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">
<!--AppBarLayout实际上是一个垂直方向上的LinearLayout内部封装了很多滚动时间,并应用了一些Material Design的设计理念-->
<android.support.design.widget.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="250dp"
android:fitsSystemWindows="true">
<!--可折叠标题栏,能够实现更华丽的效果,必须作为AppBarLayout的直接子布局来使用-->
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/fruit_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
app:layout_collapseMode="parallax"/>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<!--和AppBarLayout是平级的,在这里用是因为它可以嵌套响应滚动事件,正好可以在CoordiatorLayout内部使用,其内部只允许存在一个直接子布局-->
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="35dp"
app:cardCornerRadius="4dp">
<TextView
android:id="@+id/fruit_content_text"
android:layout_width="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"
android:src="@drawable/ic_comment"
app:layout_anchor="@id/appBar"
app:layout_anchorGravity="bottom|end">
</android.support.design.widget.FloatingActionButton>
</android.support.design.widget.CoordinatorLayout>
这里app:contentScrim
属性用于指定CollpsingToolbarLayout在趋于折叠状态以及折叠之后的背景色
之前我们见过这个属性,它是用于指定滚动时标题栏的显示与隐藏状态 app:layout_scrollFlags="scroll|exitUntilCollapsed"
,这里exitUntilCollapsed表示当CollapsingToolbarLayout完成折叠后会保留在界面上,不移出屏幕
其中CollpsingToolbarLayout由一个ImageView和一个Toolbar组成,它们两个都有一个属性 :app:layout_collapseMode
,用于指定当前控件在CollapsingToolbarLayout折叠过程中的折叠模式,其中值为parallax的代表会在折叠过程中产生一定的错位偏移,而pin表示始终不变
至于NestedScrollView
,它和AppBarLayout是平级的,在这里用是因为它可以嵌套响应滚动事件,正好可以在CoordiatorLayout内部使用,其内部只允许存在一个直接子布局
悬浮按钮中有个属性app:layout_anchor
,用于指定一个锚点,就是放置悬浮按钮的区域
这样界面就弄好了,下面修改FruitActivity的代码:
package com.example.qw.materialtest;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
public class FruitActivity extends AppCompatActivity {
public static final String FRUIT_NAME="fruit_name";
public static final String FRUIT_IMAGE_ID="fruit_image_id";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fruit);
Intent intent=getIntent();
String fruitName=intent.getStringExtra(FRUIT_NAME);
int fruitImageId=intent.getIntExtra(FRUIT_IMAGE_ID,0);
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=generateFruitContent(fruitName);
fruitContentText.setText(fruitContext);
}
private String generateFruitContent(String fruitName){
StringBuilder fruitContent=new StringBuilder();
for(int i=0;i<500;i++){
fruitContent.append(fruitName);
}
return fruitContent.toString();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
最后修改FruitAdapter的代码,如下所示:
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
...
public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType){
if(mContext==null){
mContext=parent.getContext();
}
View view= LayoutInflater.from(mContext).inflate(R.layout.fruit_item,parent,false);
final ViewHolder holder=new ViewHolder(view);
holder.cardView.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
int position=holder.getAdapterPosition();
Fruit fruit=mFruitList.get(position);
Intent intent=new Intent(mContext,FruitActivity.class);
intent.putExtra(FruitActivity.FRUIT_NAME,fruit.getName());
intent.putExtra(FruitActivity.FRUIT_IMAGE_ID,fruit.getImagedId());
mContext.startActivity(intent);
}
});
return holder;
}
大功告成!!!
最后附上源码地址:Material Design完整源码