package com.iwhys.mylistview; import android.content.Context; import android.graphics.Color; import android.util.AttributeSet; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.AbsListView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import com.iwhys.mylistview.jazzy.JazzyEffect; import com.iwhys.mylistview.jazzy.JazzyHelper; /** * 带动画的ListView * Created by devil on 14/12/8. */ public class LoadMoreListView extends ListView { private int mCurrentScrollState; private OnLoadMoreListener loadMoreListener; //是否正在刷新,是否正在加载更多,是否开启加载更多 private boolean refreshing = false, loadingMore = false, enableLoadMore = true; private final JazzyHelper mHelper; private final Footer footer; public LoadMoreListView(Context context) { this(context, null); } public LoadMoreListView(Context context, AttributeSet attrs) { super(context, attrs); mHelper = getHelper(context, attrs); setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { mCurrentScrollState = scrollState; } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { boolean canLoadMore = (firstVisibleItem + visibleItemCount) >= totalItemCount; if (enableLoadMore && !refreshing && !loadingMore && canLoadMore && mCurrentScrollState != SCROLL_STATE_IDLE) { startLoadMore(); } } }); footer = new Footer(context); footer.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { startLoadMore(); } }); addFooterView(footer); } /** * 是否开启加载更多功能 * * @param enableLoadMore 是否 */ public void setEnableLoadMore(boolean enableLoadMore) { this.enableLoadMore = enableLoadMore; } public void setRefreshing(boolean refreshing) { this.refreshing = refreshing; } public boolean isLoadingMore(){ return loadingMore; } /** * loadMore listener */ public interface OnLoadMoreListener { public void onLoadMore(); } public void setOnLoadMoreListener(OnLoadMoreListener loadMoreListener) { this.loadMoreListener = loadMoreListener; } /** * 停止加载更多 * * @param isLoadMore 是否载入成功 */ public void stopLoadMore(boolean isLoadMore) { loadingMore = false; footer.setStatus(isLoadMore ? Footer.SUCCESS : Footer.FAILURE); } private JazzyHelper getHelper(Context context, AttributeSet attrs) { JazzyHelper helper = new JazzyHelper(context, attrs); super.setOnScrollListener(helper); return helper; } private void startLoadMore() { loadingMore = true; footer.setStatus(Footer.LOADING); if (loadMoreListener != null) { loadMoreListener.onLoadMore(); } } @Override public void setOnScrollListener(OnScrollListener l) { mHelper.setOnScrollListener(l); } /** * Sets the desired transition effect. * * @param transitionEffect The non-bundled transition provided by the client. */ public void setTransitionEffect(JazzyEffect transitionEffect) { mHelper.setTransitionEffect(transitionEffect); } /** * Sets whether new items or all items should be animated when they become visible. * * @param onlyAnimateNew True if only new items should be animated; false otherwise. */ public void setShouldOnlyAnimateNewItems(boolean onlyAnimateNew) { mHelper.setShouldOnlyAnimateNewItems(onlyAnimateNew); } /** * If true animation will only occur when scrolling without the users finger on the screen. * * @param onlyFling d */ public void setShouldOnlyAnimateFling(boolean onlyFling) { mHelper.setShouldOnlyAnimateFling(onlyFling); } /** * Stop animations after the list has reached a certain velocity. When the list slows down * it will start animating again. This gives a performance boost as well as preventing * the list from animating under the users finger if they suddenly stop it. * * @param itemsPerSecond, set to JazzyHelper.MAX_VELOCITY_OFF to turn off max velocity. * While 13 is a good default, it is dependent on the size of your items. */ public void setMaxAnimationVelocity(int itemsPerSecond) { mHelper.setMaxAnimationVelocity(itemsPerSecond); } /** * Enable this if you are using a list with items that should act like grid items. * * @param simulateGridWithList d */ public void setSimulateGridWithList(boolean simulateGridWithList) { mHelper.setSimulateGridWithList(simulateGridWithList); setClipChildren(!simulateGridWithList); } /** * 底部View,显示加载更多 */ class Footer extends LinearLayout { public final static int SUCCESS = 0, FAILURE = 1, LOADING = 2, IDLE = 3; private ImageView icon; private TextView text; private Animation loadingAnim; public Footer(Context context) { super(context); setOrientation(HORIZONTAL); setGravity(Gravity.CENTER); icon = new ImageView(context); icon.setImageResource(R.drawable.icon_loading_small); icon.setVisibility(INVISIBLE); addView(icon); text = new TextView(context); text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); text.setTextColor(Color.GRAY); text.setPadding(5, 8, 5, 8); addView(text); loadingAnim = AnimationUtils.loadAnimation(context, R.anim.rotate_loading); post(new Runnable() { @Override public void run() { setStatus(Footer.IDLE); } }); } /** * 设置状态 * @param status 状态 */ public void setStatus(int status) { switch (status) { case SUCCESS: canVisible(false); break; case FAILURE: icon.clearAnimation(); icon.setVisibility(GONE); text.setText(R.string.load_failure); canVisible(true); break; case LOADING: icon.setVisibility(VISIBLE); icon.startAnimation(loadingAnim); text.setText(R.string.on_loading); canVisible(true); break; default: canVisible(false); break; } } //设置是否显示,通过padding修正隐藏之后的空白问题 private void canVisible(boolean visible) { setVisibility(visible ? VISIBLE : GONE); setPadding(0, visible ? 0 : -getHeight(), 0, 0); } } }