第一次写博文,写得不好的地方还望各位看客见谅
为了学习自定义软件开发,且定制出满足自己需求的控件(不需要将就地使用第三方源码),本人花了一周的时间开发了个横向ListView,写博客是为了记录整个开发过程及思路,也能和各位看客一起学习和探讨。
这一系列文章是针对的读者是已经了解listview缓存和工作原理的android开发人员,如果对listview缓存和工作原理还不了解的读者,可以查看以下文章:
《Android研究院之ListView原理学习与优化总结》
目前横向ListView的可替代方案有以下三种:
1.HorizontalScrollView——android官方提供
2.RecyclerView——android6.0提供的
3.第三方开源控件
尽管有众多的选择,但感觉还是自己会实现比较酷一些,还有就是,自己的东西可以随便改改改改改。
本篇文章将介绍横向ListView的实现基本思路,在接下来的一系列文章中将不断介绍整个控件的完善思路(包括:实现快速滚动、添加头/尾视图、添加滚动条、实现下拉刷新/上拉加载等)。
参考文章: 《Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现》
横向ListView的基础逻辑:
1.新建java类,类名:HorizontalListView
2.继承AdapterView
3.实现setAdapter()和getAdapter()方法(需要为adapter注册数据观察器)
4.实现onTouchEvent()方法响应事件(采用android提供的手势解析器GestureDetector解析事件)
5.实现onLayout方法,布局列表项
1).计算当前列表发生滚动的滚动“位移值”,记录已经发生有效滚动的“位移累加值”
2).根据“位移值”提取需要缓存的视图(已经滚动到可视区域外的列表项)
3).根据“位移值”设置需要显示的的列表项
4).根据整体列表“显示偏移值”整顿所有列表项位置(调用子view的列表项)
5).计算可以发生滚动的“最大位移值”
先上代码:
package com.hss.os.horizontallistview.history_version;
import android.content.Context;
import android.database.DataSetObserver;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import java.util.LinkedList;
import java.util.Queue;
/**
* 横向ListView的基础逻辑
* 1.继承AdapterView
* 2.实现setAdapter()和getAdapter()方法(需要为adapter注册数据观察器)
* 3.实现onTouchEvent()方法响应事件(采用android提供的手势解析器GestureDetector解析事件)
* 4.实现onLayout方法,布局列表项
1).计算当前列表发生滚动的滚动“位移值”,记录已经发生有效滚动的“位移累加值”
2).根据“位移值”提取需要缓存的视图(已经滚动到可视区域外的列表项)
3).根据“位移值”设置需要显示的的列表项
4).根据整体列表“显示偏移值”整顿所有列表项位置(调用子view的列表项)
5).计算可以发生滚动的“最大位移值”
*
* Created by hss on 2017/7/17.
*/
public class HorizontalListView1 extends AdapterView<ListAdapter> {
private ListAdapter adapter = null;
private GestureDetector mGesture;
private Queue<View> cacheView = new LinkedList<>();//列表项缓存视图
private int firstItemIndex = 0;//显示的第一个子项的下标
private int lastItemIndex = -1;//显示的最后的一个子项的下标
private int scrollValue=0;//列表已经发生有效滚动的位移值
private int hasToScrollValue=0;//接下来列表发生滚动所要达到的位移值
private int maxScrollValue=Integer.MAX_VALUE;//列表发生滚动所能达到的最大位移值(这个由最后显示的列表项决定)
private int displayOffset=0;//列表显示的偏移值(用于矫正列表显示的所有子项的显示位置)
public HorizontalListView1(Context context) {
super(context);
init(context);
}
public HorizontalListView1(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public HorizontalListView1(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public HorizontalListView1(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(Context context){
mGesture = new GestureDetector(getContext(), mOnGesture);
}
private void initParams(){
removeAllViewsInLayout();
if(adapter!=null&&lastItemIndex<adapter.getCount())
hasToScrollValue=scrollValue;