ListView的使用范围非常广泛,尽管RecycleView在很多地方取代了ListView,但是ListView的地位还是难以撼动的。
那么这一章节的知识点,将通过代码的方式展示出来:
ListView的重要属性
<com.why.a4_listview.MyListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
/**
* 这两个属性控制分割线和分割线的高度,
* android:divider="null"是把分割线设置为了透明,也就是去掉了分割线
**/
android:divider="@android:color/darker_gray"
/**
* 取消进度条
**/
android:scrollbars="none"
/**
* 设置点击listview的item的点击效果,下面是使得点击效果为透明状态,也就是取消了点击效果
**/
android:listSelector="@android:color/transparent"
>
</com.why.a4_listview.MyListView>
ListView的使用
public class MainActivity extends Activity {
private List<ChatItemListViewBean> mChatData;;
private MyListView listView;
private List<String> mData;
private Toolbar mToolbar;
private int mTouchSlop;
private boolean mShow = true;
private float mFirstY;
private int direction;
private Animator mAnimator;
private View.OnTouchListener myTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.i("test", "ACTION_DOWN: ");
mFirstY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
Log.i("test", "ACTION_MOVE: ");
float currentY = event.getY();
if (currentY - mFirstY > 0){
//向下滑动
direction = 0;
}else if (mFirstY - currentY > 0){
//向上滑动
direction = 1;
}
if (direction == 1){
if (mShow){
toolbarAnim(0);//隐藏
mShow = !mShow;
}
}else if (direction == 0){
if (!mShow){
toolbarAnim(1);//显示
mShow = !mShow;
}
}
break;
case MotionEvent.ACTION_UP:
Log.i("test", "ACTION_UP: ");
break;
}
return false;
}
};
private void toolbarAnim(int flag) {
if (mAnimator != null && mAnimator.isRunning()){
mAnimator.cancel();
}
if (flag == 0){ //隐藏
//效果一样
//mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", 0, -mToolbar.getHeight());
mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", mToolbar.getTranslationY(), -mToolbar.getHeight());
}else { //显示
//mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", -mToolbar.getHeight(), 0);
mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", mToolbar.getTranslationY(), 0);
}
mAnimator.start();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initChat();
}
private void initChat() {
initToolBar();
mToolbar.setVisibility(View.GONE);
initChatData();
listView = (MyListView) findViewById(R.id.lv);
listView.setAdapter(new ChatListViewAdapter(getApplicationContext(), mChatData));
}
private void initText() {
initToolBar();
initData();
textListView();
initText();
}
private void initToolBar() {
mToolbar = findViewById(R.id.toolbar);
}
private void initData() {
mData = new ArrayList<>();
for (int i=0; i<20; i++){
mData.add(String.valueOf(i));
}
/**
* 获得系统认为的最低的滑动距离
*/
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
}
private void textListView() {
listView = (MyListView) findViewById(R.id.lv);
listView.setAdapter(new ViewHolderAdapter(getApplicationContext(), mData));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
/**
* 瞬间移动到 position 为11的item上,position 为11的item出现在第一行
*/
//listView.setSelection(11);
/**
* 平滑移动到position为20的item上,
* 但是当从上向下滑动的时候,20出现在屏幕的最后一行
* 从下向上滑动的时候,20出现在屏幕的第一行
*/
//listView.smoothScrollToPosition(20);
/**
* -25是指向上移动25个item, 25是指向下移动25个item
*/
//listView.smoothScrollByOffset(25);
/**
* 在2秒内向下移动500个px
*/
//listView.smoothScrollBy(500, 2000);
/**
* 获取第20个子view
*/
//View childView = listView.getChildAt(20);
}
});
/**
* 当listview为空数据的时候,要显示的布局
*/
if (mData.size() == 0){
listView.setEmptyView(findViewById(R.id.iv_empty));
}
listView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
/**
* 可以根据用户滑动的方向,并在不同的事件中进行相应的;逻辑处理
*/
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
}
return false;
}
});
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState){
/**
* 滑动停止
*/
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
Log.i("test", "滑动停止---SCROLL_STATE_IDLE: ");
break;
/**
* 正在滑动
*/
case SCROLL_STATE_TOUCH_SCROLL:
Log.i("test", "正在滑动---SCROLL_STATE_TOUCH_SCROLL: ");
break;
/**
* 手指用力滑动屏幕导致形成惯性的时候,此时手指离开屏幕后,listview由于惯性继续滑动的时候走这里
* 如果手指力道不能形成惯性,那么当前方法只会调用两次
* 如果足以形成惯性,会调用三次,而不是一直调用走这里
*/
case SCROLL_STATE_FLING:
Log.i("test", "惯性滑动---SCROLL_STATE_FLING: ");
break;
}
}
/**
* 滚动时一直调用该方法
* firstVisibleItem 当前能看到的第一个item的id(从0开始)
* visibleItemCount 当前能看到的item的总数(没有显示完全的item也包含在内)
* totalItemCount 整个listview的item总数
*/
int lastVisibleItem;
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
Log.i("test", "onScroll: ");
/**
* 判断是否到了最后一行
*/
if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0){
Log.i("test", "到底了: ");
}
if (firstVisibleItem > lastVisibleItem){
Log.i("test", "向上滑动: ");
}else if (firstVisibleItem < lastVisibleItem){
Log.i("test", "向下滑动: ");
}
lastVisibleItem = firstVisibleItem;
}
});
/**
* 获取可视区域内第一个item的position
* 不滑动获取到的值为0
*/
int firstVisiblePosition = listView.getFirstVisiblePosition();
Log.i("test", "firstVisiblePosition: "+firstVisiblePosition);
/**
* 获取可视区域内最后一个item的position
* 没有滑动的时候,得到的值为-1,原因getChildCount()获取到的值为0
*/
int lastVisiblePosition = listView.getLastVisiblePosition();
Log.i("test", "最后一个item: "+lastVisiblePosition);
addHeaderView();
listView.setOnTouchListener(myTouchListener);
}
/**
* 为防止第一个元素被toolbar遮挡,应该添加头部
*/
private void addHeaderView() {
View header = new View(this);
header.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT,
(int) getResources().getDimension(R.dimen.abc_action_bar_default_height_material)));
listView.addHeaderView(header);
}
}
ListView弹性效果的设置
当上滑到头或者下滑到底的时候,需要有个弹性效果,下面自定义的 ListView 能够达到一个简易的弹性效果。
public class MyListView extends ListView {
private int mMaxOverDistance = 300;
public MyListView(Context context) {
this(context, null);
}
public MyListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initData(context);
}
/**
* 满足多分辨率的要求,根据屏幕density来计算具体的值
* @param context
*/
private void initData(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float density = displayMetrics.density;
mMaxOverDistance = (int) (density*mMaxOverDistance);
}
/**
* 重写该方法,在listview中maxOverScrollY的值默认为0;
* 我将修改为mMaxOverDistance。使得listview滑动到边界的时候,能够有mMaxOverDistance长的弹性效果
*
* 这是比较简单的一种增加弹性效果的方式
*/
@Override
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, mMaxOverDistance, isTouchEvent);
}
}