实验目的
掌握SwipeRefreshLayout 布局控件使用方式;
实验要求
掌握SwipeRefreshLayout 进行刷新加载数据的方法;
实验内容
在第七个项目 中ListView 中的数据在MainActivity 初始化时从arrays.xml 文件中进行读取,其数量是固定的。实际项目开发中,通常需要通过下拉页面进行数据的刷新加载。本实验中通过使用SwipeRefreshLayout 实现页面的下拉刷新,为了简便起见,当用户下拉刷新App页面时,从arrays.xml 随机生成一条新闻加入ListView 的顶部,项目的最终运行效果如图1 SwipeRefreshLayout实现下拉刷新 所示。
步骤一,打开第七个项目或第十五个项目
打开第七个项目 或第十五个项目 ,在该项目基础上完成本次实验。
步骤二,修改activity_main.xml布局文件
打开activity_main.xml 文件,需要加入SwipeRefreshLayout 控件作为ListView 控件的父容器,具体代码如下所示。
Copy <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<ListView
android:id="@+id/lv_news_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scrollbars="none"
android:divider="@android:color/transparent"
android:dividerHeight="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.constraint.ConstraintLayout>
步骤二,修改MainActivity.java文件
1. 在MainActivity类中定义SwipeRefreshLayout控件对象
在MainActivity 类中定义私有SwipeRefreshLayout 控件对象,并在onCreate() 方法中进行控件对象绑定操作。
2. 设置SwipeRefreshLayout控件下拉刷新事件侦听器
响应SwipeRefreshLayout 控件的下拉刷新需要设置该控件的OnRefreshListener 事件侦听器,在onRefresh() 方法中调用了MainActivity 类定义的私有方法,用于刷新数据。
上述两步的代码如下所示。
Copy public class MainActivity extends AppCompatActivity {
...
private List<News> newsList = new ArrayList<>();
private NewsAdapter newsAdapter = null;
private ListView lvNewsList;
private SwipeRefreshLayout swipe;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
NewsAdapter newsAdapter = new NewsAdapter(MainActivity.this,
R.layout.list_item, newsList);
ListView lvNewsList = findViewById(R.id.lv_news_list);
lvNewsList.setAdapter(newsAdapter);
swipe = findViewById(R.id.swipe);
...
swipe.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
refreshData();
}
});
}
...
}
3. 定义refreshData()私有方法刷新数据
刷新数据主要通过实例化一个News 新闻对象,该对象数据仍然从arrays.xml 数组资源文件中得到,但是采用了Random 对象随机产生范围从 0~19 的下标,从而模拟生成新的新闻对象。
通过NewsAdapter.insert(News object, int index) 方法将随机生成的News 新闻对象插入数据源的头部(index为0)。当NewsAdapter 适配器中的数据发生变化时,需要调用NewsAdapter.notifyDataSetChanged() 方法通知与适配器绑定的ListView 列表UI控件刷新页面。
最后调用SwipeRefreshLayout.setRefreshing(false) 方法,取消刷新动作并隐藏SwipeRefreshLayout 控件。
Copy public class MainActivity extends AppCompatActivity {
...
private void refreshData() {
Random random = new Random();
int index = random.nextInt(19);
News news = new News();
news.setTitle(titles[index]);
news.setAuthor(authors[index]);
news.setContent(contents[index]);
news.setImageId(images.getResourceId(index, -1));
newsAdapter.insert(news, 0);
newsAdapter.notifyDataSetChanged();
swipe.setRefreshing(false);
}
}
步骤三,编译项目并部署APK运行
完成上述步骤后,编译项目并将其部署至虚拟机或物理机上,App运行后,在新闻列表页中下拉刷新观察新闻列表是否响应刷新动作在列表顶部新增一条新闻,App运行结果应与图1 SwipeRefreshLayout实现下拉刷新 相同。
实验小结
通过本次实验,你应该掌握了如下知识内容:
使用SwipeRefreshLayout 响应下拉刷新;
使用Adapter.notifyDataSetChanged() 等方法进行数据变更;