ListView需要实现一种特殊的动画效果。
1)第一次加载数据时,ListView的数据显示时,像打印机一样,一行一行的往下吐出内容;
2)ListVIew滑动到最后时,自动加载下一页数据,当前的列表位置不变化。
实现方案:
动画效果1)
列表选择到最后一个项,然后属性动画显示列表从最后一个项位置(当前列表高度位置),
滚动到第一个项的位置。
实现方法:
dataSize为列表项数据的个数
mListView.setSelection(mAdapter.getCount() - 1);
startAnimation(dataSize);
isFirstRequestData = false;
creditNumber.setNumber(creditModel.getTotalCount()).start();
其中startAnumation就是实现打印机一样的滚动效果。
// 自动动画
private void startAnimation(final int animationOffset) {
LogUtil.d(TAG, "startY: " + -mListView.getHeight() + " FirstVisiblePosition:" + mListView.getFirstVisiblePosition());
animator = ObjectAnimator.ofFloat(mListView, "translationY", -mListView.getHeight(), 0);
animator.setDuration(2000);
animator.setInterpolator(new AccelerateInterpolator()); // 加速
/**
* 添加所有监听事件
*/
animator.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator arg0) {
mListView.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationRepeat(Animator arg0) {
}
@Override
public void onAnimationEnd(Animator arg0) {
listViewSmoothScrollToPositionFromTop(mListView, 0, 0, mListView.getFirstVisiblePosition() * 150);
}
@Override
public void onAnimationCancel(Animator arg0) {
}
});
animator.start();
}
通过一个属性动画,实现ListView从底部滚动到第一个项的动画。
这个滑动动画效果,需要一个兼容,不同的SDK实现方法有些不同。
/**
* ListView 滑动动画兼容
*
* @param listView : ListView控件
* @param position : 目标项索引
* @param offset : 滚动的偏移量
* @param duration : 动画时间长度
*/
private void listViewSmoothScrollToPositionFromTop(ListView listView, int position, int offset, int duration) {
if (PhoneHelper.hasHoneyMB()) {
//大于android3.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
listView.smoothScrollToPositionFromTop(position, offset, duration);
}
} else if (PhoneHelper.hasFroyo()) {
//android2.2
int firstVisible = listView.getFirstVisiblePosition();
int lastVisible = listView.getLastVisiblePosition();
if (0 < firstVisible)
listView.smoothScrollToPosition(0);
else
listView.smoothScrollToPosition(position + lastVisible - firstVisible - 2);
} else {
listView.setSelectionFromTop(position, 0);
}
}
2)滑动到最后,自动加载下一页数据,这时新加数据怎么显示到当前列表末尾?
滑动到最后一个项,自动加载下一页数据
private void setListener() {
commonTitleBar.getLeftView().setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
mListView.setOnScrollListener(new OnScrollListener() {
private int visibleLastIndex;
private int visibleFirstIndex;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
int itemsLastIndex = mAdapter.getCount(); // 数据集最后一项的索引
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE && visibleLastIndex == itemsLastIndex + 1) {
if (isCompleteLoad && !isAllDataCompleted) { // (判断条件)当前没有正在请求数据,且还有更多数据可以加载
direct = "down";
offsetId = newCreditInfo.get(itemsLastIndex - 1).getOffsetId();
initData();
footerCreditProgress.setVisibility(View.VISIBLE);
}
}
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE && visibleFirstIndex < 2) {
startTimerTask();
isAutoRefresh = true;
} else {
stopTimerTask();
isAutoRefresh = false;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
visibleLastIndex = firstVisibleItem + visibleItemCount - 1;
visibleFirstIndex = firstVisibleItem;
}
});
}
滑动到最底部,开始一个自动加载下一页数据,自动刷新的过程。
if (requestTag == ConstantUtil.Net_Tag_Request_Today_Credit) {
isCompleteLoad = true;
footerCreditProgress.setVisibility(View.GONE);
hideLoadingErrorView();
try {
NewCreditModel creditModel = (NewCreditModel) data;
if (creditModel.isCache()) {
return;
}
int dataSize = creditModel.getList().size();
intervalTime = creditModel.getIntervalTime();
pageSize = creditModel.getPageSize();
// Log.d(TAG, "pageSize: " + pageSize);
// Log.d(TAG, "dataSize: " + dataSize);
// Log.d(TAG, "intervalTime: " + intervalTime);
if ("up".equals(direct)) {
if (dataSize == pageSize) {
newCreditInfo.clear();
}
newCreditInfo.addAll(0, creditModel.getList());
} else {
if (dataSize == 0) { // 下拉加载更多成功获取到0条数据,表示已经没有更多数据了
isAllDataCompleted = true;
}
newCreditInfo.addAll(creditModel.getList());
}
mAdapter.setData(newCreditInfo);
if (isFirstRequestData && dataSize > 0) { // 第一次请求数据则定位到底部
mListView.setSelection(mAdapter.getCount() - 1);
startAnimation(dataSize);
isFirstRequestData = false;
creditNumber.setNumber(creditModel.getTotalCount()).start();
} else if (isFirstRequestData && dataSize == 0) {
showNoDataView();
} else {
if (isAutoRefresh) {
View v = mListView.getChildAt(1);
mListView.setSelectionFromTop(mListView.getFirstVisiblePosition() + dataSize + 1, v.getTop());
listViewSmoothScrollToPositionFromTop(mListView, 0, 0, dataSize * 300);
}
}
// creditNumber.setNumber(creditModel.getTotalCount()).start();
// creditNumber.setNumber(438957).start();
} catch (Exception e) {
e.printStackTrace();
if (isFirstRequestData) {
showNoDataView();
}
}
}
拉取到新数据以后,直接刷新列表就可以了,当前ListvIew的Selection位置不会变化。