diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 4457c1d..07bb6a1 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -4,7 +4,7 @@ android:versionCode="1" android:versionName="1.0" > - + + android:background="#f0f0f0" + android:orientation="vertical" > + android:layout_height="fill_parent" + android:cacheColorHint="#00000000" + xlistview:pull_to_bottom_refresh="false" + xlistview:pull_to_top_load_more="false" > \ No newline at end of file diff --git a/res/values/attrs.xml b/res/values/attrs.xml new file mode 100644 index 0000000..8928065 --- /dev/null +++ b/res/values/attrs.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/me/maxwin/XListViewActivity.java b/src/me/maxwin/XListViewActivity.java index 8a447b6..ff7da44 100644 --- a/src/me/maxwin/XListViewActivity.java +++ b/src/me/maxwin/XListViewActivity.java @@ -7,6 +7,7 @@ import android.app.Activity; import android.os.Bundle; import android.os.Handler; +import android.text.format.DateFormat; import android.widget.ArrayAdapter; public class XListViewActivity extends Activity implements IXListViewListener { @@ -16,6 +17,7 @@ public class XListViewActivity extends Activity implements IXListViewListener { 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) { @@ -23,17 +25,16 @@ public void onCreate(Bundle savedInstanceState) { setContentView(R.layout.main); geneItems(); mListView = (XListView) findViewById(R.id.xListView); - mListView.setPullLoadEnable(true); mAdapter = new ArrayAdapter(this, R.layout.list_item, items); mListView.setAdapter(mAdapter); -// mListView.setPullLoadEnable(false); -// mListView.setPullRefreshEnable(false); + mListView.setPullLoadEnable(true); + mListView.setPullRefreshEnable(true); mListView.setXListViewListener(this); mHandler = new Handler(); } private void geneItems() { - for (int i = 0; i != 20; ++i) { + for (int i = 0; i != 5; ++i) { items.add("refresh cnt " + (++start)); } } @@ -41,9 +42,10 @@ private void geneItems() { private void onLoad() { mListView.stopRefresh(); mListView.stopLoadMore(); - mListView.setRefreshTime("刚刚"); + mListView.setRefreshTime(DateFormat.format( + XListView.DATE_FORMAT_PARTTEN, System.currentTimeMillis())); } - + @Override public void onRefresh() { mHandler.postDelayed(new Runnable() { @@ -53,7 +55,8 @@ public void run() { items.clear(); geneItems(); // mAdapter.notifyDataSetChanged(); - mAdapter = new ArrayAdapter(XListViewActivity.this, R.layout.list_item, items); + mAdapter = new ArrayAdapter(XListViewActivity.this, + R.layout.list_item, items); mListView.setAdapter(mAdapter); onLoad(); } diff --git a/src/me/maxwin/view/XListView.java b/src/me/maxwin/view/XListView.java index e3ed52e..99551d7 100755 --- a/src/me/maxwin/view/XListView.java +++ b/src/me/maxwin/view/XListView.java @@ -10,6 +10,10 @@ import me.maxwin.R; import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.TypedArray; +import android.os.SystemClock; +import android.text.format.DateFormat; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; @@ -23,8 +27,19 @@ import android.widget.Scroller; import android.widget.TextView; +/** + * @ClassName: XListView + * @Description: 1, new attrs added. For example, pull_to_bottom_refresh, + * pull_to_top_load_more. 2, set Automatically footer + * mPullLoadMore false when children isn't full of XListView + * @author SilentKnight || happychinapc@gmail.com + * @date 2015年1月20日 下午5:42:02 + * + */ public class XListView extends ListView implements OnScrollListener { - + private static final String TAG = XListView.class.getSimpleName(); + public static final String DATE_FORMAT_PARTTEN = "MM-dd kk:mm:ss"; + private SharedPreferences sharedPref; private float mLastY = -1; // save event y private Scroller mScroller; // used for scroll back private OnScrollListener mScrollListener; // user's scroll listener @@ -39,15 +54,15 @@ public class XListView extends ListView implements OnScrollListener { private RelativeLayout mHeaderViewContent; private TextView mHeaderTimeView; private int mHeaderViewHeight; // header view's height - private boolean mEnablePullRefresh = true; + private boolean mEnablePullRefresh = false; private boolean mPullRefreshing = false; // is refreashing. // -- footer view private XListViewFooter mFooterView; - private boolean mEnablePullLoad; + private boolean mEnablePullLoad = false; private boolean mPullLoading; private boolean mIsFooterReady = false; - + // total list items, used to detect is at the bottom of listview. private int mTotalItemCount; @@ -67,26 +82,24 @@ public class XListView extends ListView implements OnScrollListener { * @param context */ public XListView(Context context) { - super(context); - initWithContext(context); + this(context, null); } public XListView(Context context, AttributeSet attrs) { - super(context, attrs); - initWithContext(context); + this(context, attrs, 0); } public XListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - initWithContext(context); + initWithContext(context, attrs); } - private void initWithContext(Context context) { + private void initWithContext(Context context, AttributeSet attrs) { 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); - + sharedPref = context.getSharedPreferences(TAG, Context.MODE_PRIVATE); // init header view mHeaderView = new XListViewHeader(context); mHeaderViewContent = (RelativeLayout) mHeaderView @@ -108,6 +121,17 @@ public void onGlobalLayout() { .removeGlobalOnLayoutListener(this); } }); + if (attrs != null) { + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.XListView, 0, 0); + mEnablePullLoad = a.getBoolean( + R.styleable.XListView_pull_to_top_load_more, false); + mEnablePullRefresh = a.getBoolean( + R.styleable.XListView_pull_to_bottom_refresh, false); + } + setPullLoadEnable(mEnablePullLoad); + setPullRefreshEnable(mEnablePullRefresh); + setRefreshTime(sharedPref.getString("last_update_time", DateFormat.format(DATE_FORMAT_PARTTEN, SystemClock.currentThreadTimeMillis()).toString())); } @Override @@ -183,8 +207,15 @@ public void stopLoadMore() { * * @param time */ - public void setRefreshTime(String time) { + public void setRefreshTime(CharSequence time) { + if (time == null || "".equals(time)) { + String lastUpdateTime = DateFormat.format(DATE_FORMAT_PARTTEN, SystemClock.currentThreadTimeMillis()).toString(); + mHeaderTimeView.setText(lastUpdateTime); + sharedPref.edit().putString("last_update_time", lastUpdateTime).commit(); + return; + } mHeaderTimeView.setText(time); + sharedPref.edit().putString("last_update_time", time.toString()).commit(); } private void invokeOnScrolling() { @@ -195,10 +226,10 @@ private void invokeOnScrolling() { } private void updateHeaderHeight(float delta) { - mHeaderView.setVisiableHeight((int) delta - + mHeaderView.getVisiableHeight()); + mHeaderView.setVisibleHeight((int) delta + + mHeaderView.getVisibleHeight()); if (mEnablePullRefresh && !mPullRefreshing) { // 未处于刷新状态,更新箭头 - if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) { + if (mHeaderView.getVisibleHeight() > mHeaderViewHeight) { mHeaderView.setState(XListViewHeader.STATE_READY); } else { mHeaderView.setState(XListViewHeader.STATE_NORMAL); @@ -211,7 +242,7 @@ private void updateHeaderHeight(float delta) { * reset header view's height. */ private void resetHeaderHeight() { - int height = mHeaderView.getVisiableHeight(); + int height = mHeaderView.getVisibleHeight(); if (height == 0) // not visible. return; // refreshing and header isn't shown fully. do nothing. @@ -242,7 +273,7 @@ private void updateFooterHeight(float delta) { } mFooterView.setBottomMargin(height); -// setSelection(mTotalItemCount - 1); // scroll to bottom + // setSelection(mTotalItemCount - 1); // scroll to bottom } private void resetFooterHeight() { @@ -277,7 +308,7 @@ public boolean onTouchEvent(MotionEvent ev) { final float deltaY = ev.getRawY() - mLastY; mLastY = ev.getRawY(); if (getFirstVisiblePosition() == 0 - && (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) { + && (mHeaderView.getVisibleHeight() > 0 || deltaY > 0)) { // the first item is showing, header has shown or pull down. updateHeaderHeight(deltaY / OFFSET_RADIO); invokeOnScrolling(); @@ -292,7 +323,7 @@ public boolean onTouchEvent(MotionEvent ev) { if (getFirstVisiblePosition() == 0) { // invoke refresh if (mEnablePullRefresh - && mHeaderView.getVisiableHeight() > mHeaderViewHeight) { + && mHeaderView.getVisibleHeight() > mHeaderViewHeight) { mPullRefreshing = true; mHeaderView.setState(XListViewHeader.STATE_REFRESHING); if (mListViewListener != null) { @@ -303,8 +334,8 @@ public boolean onTouchEvent(MotionEvent ev) { } else if (getLastVisiblePosition() == mTotalItemCount - 1) { // invoke load more. if (mEnablePullLoad - && mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA - && !mPullLoading) { + && mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA + && !mPullLoading) { startLoadMore(); } resetFooterHeight(); @@ -318,7 +349,7 @@ public boolean onTouchEvent(MotionEvent ev) { public void computeScroll() { if (mScroller.computeScrollOffset()) { if (mScrollBack == SCROLLBACK_HEADER) { - mHeaderView.setVisiableHeight(mScroller.getCurrY()); + mHeaderView.setVisibleHeight(mScroller.getCurrY()); } else { mFooterView.setBottomMargin(mScroller.getCurrY()); } diff --git a/src/me/maxwin/view/XListViewFooter.java b/src/me/maxwin/view/XListViewFooter.java index 6f1970b..016a28e 100755 --- a/src/me/maxwin/view/XListViewFooter.java +++ b/src/me/maxwin/view/XListViewFooter.java @@ -24,18 +24,17 @@ public class XListViewFooter extends LinearLayout { 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); @@ -50,20 +49,22 @@ public void setState(int state) { mHintView.setText(R.string.xlistview_footer_hint_normal); } } - + public void setBottomMargin(int height) { - if (height < 0) return ; - LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams(); + 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(); + LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mContentView + .getLayoutParams(); return lp.bottomMargin; } - - + /** * normal status */ @@ -71,44 +72,47 @@ public void normal() { mHintView.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.GONE); } - - + /** - * loading status + * 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(); + 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(); + 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); + 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)); - + 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); + mHintView = (TextView) moreView + .findViewById(R.id.xlistview_footer_hint_textview); } - - + } diff --git a/src/me/maxwin/view/XListViewHeader.java b/src/me/maxwin/view/XListViewHeader.java index db80cb0..6dca603 100755 --- a/src/me/maxwin/view/XListViewHeader.java +++ b/src/me/maxwin/view/XListViewHeader.java @@ -112,7 +112,7 @@ public void setState(int state) { mState = state; } - public void setVisiableHeight(int height) { + public void setVisibleHeight(int height) { if (height < 0) height = 0; LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mContainer @@ -121,7 +121,7 @@ public void setVisiableHeight(int height) { mContainer.setLayoutParams(lp); } - public int getVisiableHeight() { + public int getVisibleHeight() { return mContainer.getHeight(); }