android--常用的开源框架ListView

来源:互联网 发布:淘宝网有卖退币王的吗 编辑:程序博客网 时间:2024/06/06 00:21
在android中最重要的常用组件之一ListView,几乎任何应用都有他们的影子。但我们每次在使用的时候总是忙于配置各种事件监听,特别是他的下拉刷新和加载更多。
前几天在github网站上看到一个比较好的开源框架。使用也是非常简单,我们只需要在onRefresh()和onLoadMore() 去加载我们的数据,他就会自动加到ListView中,
package me.maxwin;    import java.util.ArrayList;  import java.util.Random;    import me.maxwin.view.XListView;  import me.maxwin.view.XListView.IXListViewListener;  import android.app.Activity;  import android.os.Bundle;  import android.os.Handler;  import android.widget.ArrayAdapter;    public class XListViewActivity extends Activity implements IXListViewListener {      private XListView mListView;      private MyAdapter mAdapter;      private ArrayList<Person> items = new ArrayList<Person>();      private Handler mHandler;      private int start = 0;      private static int refreshCnt = 0;      /** Called when the activity is first created. */      @Override      public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.main);          geneItems();          mListView = (XListView) findViewById(R.id.xListView);          mListView.setPullLoadEnable(true);          mAdapter = new MyAdapter(this, items);          mListView.setAdapter(mAdapter);  //      mListView.setPullLoadEnable(false);  //      mListView.setPullRefreshEnable(false);          mListView.setXListViewListener(this);          mHandler = new Handler();      }        private void geneItems() {          Random r = new Random();          for (int i = 0; i != 20; ++i) {              items.add(new Person("qingxue " + (++start),"1358888"+r.nextInt(10)+r.nextInt(10)+r.nextInt(10)+r.nextInt(10)));          }      }        private void onLoad() {          mListView.stopRefresh();          mListView.stopLoadMore();          mListView.setRefreshTime("刚刚");      }      //下拉刷新      @Override      public void onRefresh() {          mHandler.postDelayed(new Runnable() {              @Override              public void run() {                  start = ++refreshCnt;                  items.clear();                  geneItems();                  // mAdapter.notifyDataSetChanged();                  //mAdapter = new ArrayAdapter<String>(XListViewActivity.this, R.layout.list_item, items);                  //mListView.setAdapter(mAdapter);                  mAdapter.notifyDataSetChanged();                  onLoad();              }          }, 2000);      }      //加载更多      @Override      public void onLoadMore() {          mHandler.postDelayed(new Runnable() {              @Override              public void run() {                  geneItems();                  mAdapter.notifyDataSetChanged();                  onLoad();              }          }, 2000);      }    } 
另外还有适配器,这个必须自己写的,要看你生成什么样的条目了,我只是为了演示一个简单的实现

package me.maxwin;    import java.util.ArrayList;  import java.util.List;    import android.content.Context;  import android.view.LayoutInflater;  import android.view.View;  import android.view.ViewGroup;  import android.widget.BaseAdapter;  import android.widget.TextView;    public class MyAdapter extends BaseAdapter {      private LayoutInflater inflater;      private List<Person> list;      public MyAdapter(Context context){          this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);          this.list = new ArrayList<Person>();      }      public MyAdapter(Context context,List<Person> list){          this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);          this.list = list;      }      @Override      public int getCount() {          return list.size();      }        @Override      public Object getItem(int position) {          return list.get(position);      }        @Override      public long getItemId(int position) {          return position;      }        @Override      public View getView(int position, View convertView, ViewGroup parent) {          TextView nameView = null;          TextView phoneView = null;          if(convertView==null){              convertView = inflater.inflate(R.layout.list_item, null);//生成条目界面对象              nameView = (TextView) convertView.findViewById(R.id.list_item_username);              phoneView = (TextView) convertView.findViewById(R.id.list_item_phone);              ViewCache cache = new ViewCache();              cache.nameView = nameView;              cache.phoneView = phoneView;              convertView.setTag(cache);          }else{              ViewCache cache = (ViewCache) convertView.getTag();              nameView = cache.nameView;              phoneView = cache.phoneView;          }          Person person = list.get(position);          //下面代码实现数据绑定          nameView.setText(person.getUsername());          phoneView.setText(person.getNumber());          return convertView;      }            private final class ViewCache{          public TextView nameView;          public TextView phoneView;            }      }


下面的是框架中的源代码,一般不需要修改,直接导入就行了
/**  * @file XListView.java  * @package me.maxwin.view  * @create Mar 18, 2012 6:28:41 PM  * @author Maxwin  * @description An ListView support (a) Pull down to refresh, (b) Pull up to load more.  *      Implement IXListViewListener, and see stopRefresh() / stopLoadMore().  */  package me.maxwin.view;    import me.maxwin.R;  import android.content.Context;  import android.util.AttributeSet;  import android.view.MotionEvent;  import android.view.View;  import android.view.ViewTreeObserver.OnGlobalLayoutListener;  import android.view.animation.DecelerateInterpolator;  import android.widget.AbsListView;  import android.widget.AbsListView.OnScrollListener;  import android.widget.ListAdapter;  import android.widget.ListView;  import android.widget.RelativeLayout;  import android.widget.Scroller;  import android.widget.TextView;    public class XListView extends ListView implements OnScrollListener {        private float mLastY = -1; // save event y      private Scroller mScroller; // used for scroll back      private OnScrollListener mScrollListener; // user's scroll listener        // the interface to trigger refresh and load more.      private IXListViewListener mListViewListener;        // -- header view      private XListViewHeader mHeaderView;      // header view content, use it to calculate the Header's height. And hide it      // when disable pull refresh.      private RelativeLayout mHeaderViewContent;      private TextView mHeaderTimeView;      private int mHeaderViewHeight; // header view's height      private boolean mEnablePullRefresh = true;      private boolean mPullRefreshing = false; // is refreashing.        // -- footer view      private XListViewFooter mFooterView;      private boolean mEnablePullLoad;      private boolean mPullLoading;      private boolean mIsFooterReady = false;            // total list items, used to detect is at the bottom of listview.      private int mTotalItemCount;        // for mScroller, scroll back from header or footer.      private int mScrollBack;      private final static int SCROLLBACK_HEADER = 0;      private final static int SCROLLBACK_FOOTER = 1;        private final static int SCROLL_DURATION = 400; // scroll back duration      private final static int PULL_LOAD_MORE_DELTA = 50; // when pull up >= 50px                                                          // at bottom, trigger                                                          // load more.      private final static float OFFSET_RADIO = 1.8f; // support iOS like pull                                                      // feature.        /**      * @param context      */      public XListView(Context context) {          super(context);          initWithContext(context);      }        public XListView(Context context, AttributeSet attrs) {          super(context, attrs);          initWithContext(context);      }        public XListView(Context context, AttributeSet attrs, int defStyle) {          super(context, attrs, defStyle);          initWithContext(context);      }        private void initWithContext(Context context) {          mScroller = new Scroller(context, new DecelerateInterpolator());          // XListView need the scroll event, and it will dispatch the event to          // user's listener (as a proxy).          super.setOnScrollListener(this);            // init header view          mHeaderView = new XListViewHeader(context);          mHeaderViewContent = (RelativeLayout) mHeaderView                  .findViewById(R.id.xlistview_header_content);          mHeaderTimeView = (TextView) mHeaderView                  .findViewById(R.id.xlistview_header_time);          addHeaderView(mHeaderView);            // init footer view          mFooterView = new XListViewFooter(context);            // init header height          mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(                  new OnGlobalLayoutListener() {                      @Override                      public void onGlobalLayout() {                          mHeaderViewHeight = mHeaderViewContent.getHeight();                          getViewTreeObserver()                                  .removeGlobalOnLayoutListener(this);                      }                  });      }        @Override      public void setAdapter(ListAdapter adapter) {          // make sure XListViewFooter is the last footer view, and only add once.          if (mIsFooterReady == false) {              mIsFooterReady = true;              addFooterView(mFooterView);          }          super.setAdapter(adapter);      }        /**      * enable or disable pull down refresh feature.      *       * @param enable      */      public void setPullRefreshEnable(boolean enable) {          mEnablePullRefresh = enable;          if (!mEnablePullRefresh) { // disable, hide the content              mHeaderViewContent.setVisibility(View.INVISIBLE);          } else {              mHeaderViewContent.setVisibility(View.VISIBLE);          }      }        /**      * enable or disable pull up load more feature.      *       * @param enable      */      public void setPullLoadEnable(boolean enable) {          mEnablePullLoad = enable;          if (!mEnablePullLoad) {              mFooterView.hide();              mFooterView.setOnClickListener(null);          } else {              mPullLoading = false;              mFooterView.show();              mFooterView.setState(XListViewFooter.STATE_NORMAL);              // both "pull up" and "click" will invoke load more.              mFooterView.setOnClickListener(new OnClickListener() {                  @Override                  public void onClick(View v) {                      startLoadMore();                  }              });          }      }        /**      * stop refresh, reset header view.      */      public void stopRefresh() {          if (mPullRefreshing == true) {              mPullRefreshing = false;              resetHeaderHeight();          }      }        /**      * stop load more, reset footer view.      */      public void stopLoadMore() {          if (mPullLoading == true) {              mPullLoading = false;              mFooterView.setState(XListViewFooter.STATE_NORMAL);          }      }        /**      * set last refresh time      *       * @param time      */      public void setRefreshTime(String time) {          mHeaderTimeView.setText(time);      }        private void invokeOnScrolling() {          if (mScrollListener instanceof OnXScrollListener) {              OnXScrollListener l = (OnXScrollListener) mScrollListener;              l.onXScrolling(this);          }      }        private void updateHeaderHeight(float delta) {          mHeaderView.setVisiableHeight((int) delta                  + mHeaderView.getVisiableHeight());          if (mEnablePullRefresh && !mPullRefreshing) { // 未处于刷新状态,更新箭头              if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) {                  mHeaderView.setState(XListViewHeader.STATE_READY);              } else {                  mHeaderView.setState(XListViewHeader.STATE_NORMAL);              }          }          setSelection(0); // scroll to top each time      }        /**      * reset header view's height.      */      private void resetHeaderHeight() {          int height = mHeaderView.getVisiableHeight();          if (height == 0) // not visible.              return;          // refreshing and header isn't shown fully. do nothing.          if (mPullRefreshing && height <= mHeaderViewHeight) {              return;          }          int finalHeight = 0; // default: scroll back to dismiss header.          // is refreshing, just scroll back to show all the header.          if (mPullRefreshing && height > mHeaderViewHeight) {              finalHeight = mHeaderViewHeight;          }          mScrollBack = SCROLLBACK_HEADER;          mScroller.startScroll(0, height, 0, finalHeight - height,                  SCROLL_DURATION);          // trigger computeScroll          invalidate();      }        private void updateFooterHeight(float delta) {          int height = mFooterView.getBottomMargin() + (int) delta;          if (mEnablePullLoad && !mPullLoading) {              if (height > PULL_LOAD_MORE_DELTA) { // height enough to invoke load                                                      // more.                  mFooterView.setState(XListViewFooter.STATE_READY);              } else {                  mFooterView.setState(XListViewFooter.STATE_NORMAL);              }          }          mFooterView.setBottomMargin(height);    //      setSelection(mTotalItemCount - 1); // scroll to bottom      }        private void resetFooterHeight() {          int bottomMargin = mFooterView.getBottomMargin();          if (bottomMargin > 0) {              mScrollBack = SCROLLBACK_FOOTER;              mScroller.startScroll(0, bottomMargin, 0, -bottomMargin,                      SCROLL_DURATION);              invalidate();          }      }        private void startLoadMore() {          mPullLoading = true;          mFooterView.setState(XListViewFooter.STATE_LOADING);          if (mListViewListener != null) {              mListViewListener.onLoadMore();          }      }        @Override      public boolean onTouchEvent(MotionEvent ev) {          if (mLastY == -1) {              mLastY = ev.getRawY();          }            switch (ev.getAction()) {          case MotionEvent.ACTION_DOWN:              mLastY = ev.getRawY();              break;          case MotionEvent.ACTION_MOVE:              final float deltaY = ev.getRawY() - mLastY;              mLastY = ev.getRawY();              if (getFirstVisiblePosition() == 0                      && (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) {                  // the first item is showing, header has shown or pull down.                  updateHeaderHeight(deltaY / OFFSET_RADIO);                  invokeOnScrolling();              } else if (getLastVisiblePosition() == mTotalItemCount - 1                      && (mFooterView.getBottomMargin() > 0 || deltaY < 0)) {                  // last item, already pulled up or want to pull up.                  updateFooterHeight(-deltaY / OFFSET_RADIO);              }              break;          default:              mLastY = -1; // reset              if (getFirstVisiblePosition() == 0) {                  // invoke refresh                  if (mEnablePullRefresh                          && mHeaderView.getVisiableHeight() > mHeaderViewHeight) {                      mPullRefreshing = true;                      mHeaderView.setState(XListViewHeader.STATE_REFRESHING);                      if (mListViewListener != null) {                          mListViewListener.onRefresh();                      }                  }                  resetHeaderHeight();              } else if (getLastVisiblePosition() == mTotalItemCount - 1) {                  // invoke load more.                  if (mEnablePullLoad                          && mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA) {                      startLoadMore();                  }                  resetFooterHeight();              }              break;          }          return super.onTouchEvent(ev);      }        @Override      public void computeScroll() {          if (mScroller.computeScrollOffset()) {              if (mScrollBack == SCROLLBACK_HEADER) {                  mHeaderView.setVisiableHeight(mScroller.getCurrY());              } else {                  mFooterView.setBottomMargin(mScroller.getCurrY());              }              postInvalidate();              invokeOnScrolling();          }          super.computeScroll();      }        @Override      public void setOnScrollListener(OnScrollListener l) {          mScrollListener = l;      }        @Override      public void onScrollStateChanged(AbsListView view, int scrollState) {          if (mScrollListener != null) {              mScrollListener.onScrollStateChanged(view, scrollState);          }      }        @Override      public void onScroll(AbsListView view, int firstVisibleItem,              int visibleItemCount, int totalItemCount) {          // send to user's listener          mTotalItemCount = totalItemCount;          if (mScrollListener != null) {              mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,                      totalItemCount);          }      }        public void setXListViewListener(IXListViewListener l) {          mListViewListener = l;      }        /**      * you can listen ListView.OnScrollListener or this one. it will invoke      * onXScrolling when header/footer scroll back.      */      public interface OnXScrollListener extends OnScrollListener {          public void onXScrolling(View view);      }        /**      * implements this interface to get refresh/load more event.      */      public interface IXListViewListener {          public void onRefresh();            public void onLoadMore();      }  } 

/**  * @file XFooterView.java  * @create Mar 31, 2012 9:33:43 PM  * @author Maxwin  * @description XListView's footer  */  package me.maxwin.view;    import me.maxwin.R;  import android.content.Context;  import android.util.AttributeSet;  import android.view.LayoutInflater;  import android.view.View;  import android.widget.LinearLayout;  import android.widget.TextView;    public class XListViewFooter extends LinearLayout {      public final static int STATE_NORMAL = 0;      public final static int STATE_READY = 1;      public final static int STATE_LOADING = 2;        private Context mContext;        private View mContentView;      private View mProgressBar;      private TextView mHintView;            public XListViewFooter(Context context) {          super(context);          initView(context);      }            public XListViewFooter(Context context, AttributeSet attrs) {          super(context, attrs);          initView(context);      }              public void setState(int state) {          mHintView.setVisibility(View.INVISIBLE);          mProgressBar.setVisibility(View.INVISIBLE);          mHintView.setVisibility(View.INVISIBLE);          if (state == STATE_READY) {              mHintView.setVisibility(View.VISIBLE);              mHintView.setText(R.string.xlistview_footer_hint_ready);          } else if (state == STATE_LOADING) {              mProgressBar.setVisibility(View.VISIBLE);          } else {              mHintView.setVisibility(View.VISIBLE);              mHintView.setText(R.string.xlistview_footer_hint_normal);          }      }            public void setBottomMargin(int height) {          if (height < 0) return ;          LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();          lp.bottomMargin = height;          mContentView.setLayoutParams(lp);      }            public int getBottomMargin() {          LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();          return lp.bottomMargin;      }                  /**      * normal status      */      public void normal() {          mHintView.setVisibility(View.VISIBLE);          mProgressBar.setVisibility(View.GONE);      }                  /**      * loading status       */      public void loading() {          mHintView.setVisibility(View.GONE);          mProgressBar.setVisibility(View.VISIBLE);      }            /**      * hide footer when disable pull load more      */      public void hide() {          LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();          lp.height = 0;          mContentView.setLayoutParams(lp);      }            /**      * show footer      */      public void show() {          LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();          lp.height = LayoutParams.WRAP_CONTENT;          mContentView.setLayoutParams(lp);      }            private void initView(Context context) {          mContext = context;          LinearLayout moreView = (LinearLayout)LayoutInflater.from(mContext).inflate(R.layout.xlistview_footer, null);          addView(moreView);          moreView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));                    mContentView = moreView.findViewById(R.id.xlistview_footer_content);          mProgressBar = moreView.findViewById(R.id.xlistview_footer_progressbar);          mHintView = (TextView)moreView.findViewById(R.id.xlistview_footer_hint_textview);      }              }  
/**  * @file XListViewHeader.java  * @create Apr 18, 2012 5:22:27 PM  * @author Maxwin  * @description XListView's header  */  package me.maxwin.view;    import me.maxwin.R;  import android.content.Context;  import android.util.AttributeSet;  import android.view.Gravity;  import android.view.LayoutInflater;  import android.view.View;  import android.view.animation.Animation;  import android.view.animation.RotateAnimation;  import android.widget.ImageView;  import android.widget.LinearLayout;  import android.widget.ProgressBar;  import android.widget.TextView;    public class XListViewHeader extends LinearLayout {      private LinearLayout mContainer;      private ImageView mArrowImageView;      private ProgressBar mProgressBar;      private TextView mHintTextView;      private int mState = STATE_NORMAL;        private Animation mRotateUpAnim;      private Animation mRotateDownAnim;            private final int ROTATE_ANIM_DURATION = 180;            public final static int STATE_NORMAL = 0;      public final static int STATE_READY = 1;      public final static int STATE_REFRESHING = 2;        public XListViewHeader(Context context) {          super(context);          initView(context);      }        /**      * @param context      * @param attrs      */      public XListViewHeader(Context context, AttributeSet attrs) {          super(context, attrs);          initView(context);      }        private void initView(Context context) {          // 初始情况,设置下拉刷新view高度为0          LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(                  LayoutParams.FILL_PARENT, 0);          mContainer = (LinearLayout) LayoutInflater.from(context).inflate(                  R.layout.xlistview_header, null);          addView(mContainer, lp);          setGravity(Gravity.BOTTOM);            mArrowImageView = (ImageView)findViewById(R.id.xlistview_header_arrow);          mHintTextView = (TextView)findViewById(R.id.xlistview_header_hint_textview);          mProgressBar = (ProgressBar)findViewById(R.id.xlistview_header_progressbar);                    mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,                  Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,                  0.5f);          mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);          mRotateUpAnim.setFillAfter(true);          mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,                  Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,                  0.5f);          mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);          mRotateDownAnim.setFillAfter(true);      }        public void setState(int state) {          if (state == mState) return ;                    if (state == STATE_REFRESHING) {    // 显示进度              mArrowImageView.clearAnimation();              mArrowImageView.setVisibility(View.INVISIBLE);              mProgressBar.setVisibility(View.VISIBLE);          } else {    // 显示箭头图片              mArrowImageView.setVisibility(View.VISIBLE);              mProgressBar.setVisibility(View.INVISIBLE);          }                    switch(state){          case STATE_NORMAL:              if (mState == STATE_READY) {                  mArrowImageView.startAnimation(mRotateDownAnim);              }              if (mState == STATE_REFRESHING) {                  mArrowImageView.clearAnimation();              }              mHintTextView.setText(R.string.xlistview_header_hint_normal);              break;          case STATE_READY:              if (mState != STATE_READY) {                  mArrowImageView.clearAnimation();                  mArrowImageView.startAnimation(mRotateUpAnim);                  mHintTextView.setText(R.string.xlistview_header_hint_ready);              }              break;          case STATE_REFRESHING:              mHintTextView.setText(R.string.xlistview_header_hint_loading);              break;              default:          }                    mState = state;      }            public void setVisiableHeight(int height) {          if (height < 0)              height = 0;          LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mContainer                  .getLayoutParams();          lp.height = height;          mContainer.setLayoutParams(lp);      }        public int getVisiableHeight() {          return mContainer.getHeight();      }    }  



1 0
原创粉丝点击