之前定义的刷新控件在使用的时候,基本等同于RecyclerView的使用,对于刷新操作只是增加了一个加载数据的回调罢了,因而本篇说是之前刷新控件的使用,大部分内容还是RecyclerView的使用。
旧机宝的“设备页”打算分为三种布局,从上到下依次是一个查询bar,一个轮播的banner,还有每行两列的设备列表。
第一步:在布局中使用自定义刷新控件
<wang.buxiang.wheel.widget.refresh.RefreshLayout
android:id="@+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
</wang.buxiang.wheel.widget.refresh.RefreshLayout>
第二步:继承之前的自定义Adapter,实现数据适配
首页共有三种布局,搜索框、轮播横幅、设备项,至于最后的一项“没有更多数据”则是封装的刷新控件自动添加的,并不需要我们关心。
enum class ViewType{
SEARCH,BANNER,DEVICE
}
对于搜索框可以就是一个图片,而Banner则需要通过一个ViewPager来实现,之前说过viewpager的fragment专用adapter,这次则是用到更普适的PagerAdapter。首先是保存数据的变量们
private var phoneDevices=ArrayList<PhoneDevice>()
private var banners= ArrayList<Int>()
internal var bannerViewPager: ViewPager? = null
banner中的数据是保存在本地的,直接在init中添加数据。
init {
banners.add(R.drawable.ic_banner_how_to_use)
banners.add(R.drawable.ic_banner_need)
banners.add(R.drawable.ic_banner_feedback)
}
定义更新adapter数据的方法,主要是存在变动的“设备项”,下拉刷脸的回调会用到setData方法,重置数据。而上划加载更多则用到addData方法,用于在现有数据基础之上添加数据。notifyDataSetChanged()则是要求adapter更新数据。
fun setData(phoneDeviceList: ArrayList<PhoneDevice>) {
phoneDevices = phoneDeviceList
notifyDataSetChanged()
}
fun addData(phoneDeviceList: ArrayList<PhoneDevice>) {
phoneDevices .addAll(phoneDeviceList)
notifyDataSetChanged()
}
定义三个内部类,继承ViewHolder,这是recyclerview特有的机制,用于提高性能。这三个用于hold每个item布局的控件们。
internal inner class DeviceViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var img_icon: ImageView = itemView.findViewById(R.id.img_icon)
var tv_name: TextView = itemView.findViewById(R.id.tv_name)
var bt_init: Button = itemView.findViewById(R.id.bt_choose)
}
internal inner class SearchViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var tv_serach: TextView = itemView.findViewById(R.id.tv_search)
}
internal inner class BannerViewHoler(itemView: View) : RecyclerView.ViewHolder(itemView) {
var viewPager: ViewPager = itemView.findViewById(R.id.viewPager)
}
根据位置不同,返回不同的viewtype,这里第一行是搜索框,第二行是banner,剩下的都是设备项。
override fun myGetItemViewType(position: Int): Int {
return when(position){
0-> ViewType.SEARCH.ordinal
1->ViewType.BANNER.ordinal
else ->ViewType.DEVICE.ordinal
}
}
根据viewtype的不同,用各自的布局创建各自的viewholder并返回
override fun myOnCreateViewHolder(viewGroup: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when(viewType){
ViewType.SEARCH.ordinal-> SearchViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.item_function_search, null))
ViewType.BANNER.ordinal->BannerViewHoler(LayoutInflater.from(viewGroup.context).inflate(R.layout.item_function_banner, null))
else-> DeviceViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.item_device, null))
}
}
依据viewtype的不同,使用返回的不同的viewholder来填充数据。
override fun myOnBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int, viewType: Int) {
when(viewType){
ViewType.SEARCH.ordinal->{
(viewHolder as SearchViewHolder).tv_serach.setOnClickListener {
// fragment.context?.startActivity(Intent(fragment.context, SearchActivity::class.java))
}
}
ViewType.BANNER.ordinal->{
}
else->{
val phoneDevice = phoneDevices[position-2]
(viewHolder as DeviceViewHolder).tv_name.text = phoneDevice.nickName
}
}
}
最后别忘了,返回当前adapter的总数据条目
override fun myGetItemCount(): Int {
return phoneDevices.size+2
}
设备项的数据条数,加上一条搜索框,加上一条banner,一共多加2条。
第三步:为刷新控件设置adapter,并设置数据加载回调
新建刚才自定义的adapter
val adapter=MyDeviceAdapter(this)
refreshLayout.setAdapter(adapter)
之前说过,recyclerview的显示格式是由layoutmanager来实现的,经常不需要修改,这里就需要进行修改了,根据之前的设计,整个页面包括一行搜索框、一行banner,剩下的都是每行两列的设备项数据,LinearManager只能实现单列布局显然不符合要求。这里使用GridLayoutManager来实现当前需求,我们要求数据以两列的网格布局进行排列,但是第一、二、最后一列要求每个数据对应的视图占据两列,在两列的网格中就是占据一行的效果了,从而达到我们的目的。
val layoutManager=GridLayoutManager(context,2)
layoutManager.spanSizeLookup=object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return when(position){
0,1,adapter.myGetItemCount()->2
else->1
}
}
}
refreshLayout.setLayoutManager(layoutManager)
最后要为刷新控件加上数据加载的回调,并在回调中进行adapter中数据的设置或添加
refreshLayout.onLoadDataListener=object :OnLoadDataListener{
override fun refresh(refreshLayout: RefreshLayout) {
refreshLayout.finishLoad()
}
override fun loadMore(refreshLayout: RefreshLayout) {
var devicesList= ArrayList<PhoneDevice>()
devicesList.add(PhoneDevice().apply { nickName="哈哈" })
devicesList.add(PhoneDevice().apply { nickName="测试" })
devicesList.add(PhoneDevice().apply { nickName="机器" })
devicesList.add(PhoneDevice().apply { nickName="不错" })
adapter.addData(devicesList)
}
}
运行,效果就出来了。