国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android自定義控件開發(fā)實(shí)戰(zhàn)之實(shí)現(xiàn)ListView下拉刷新實(shí)例代碼

2019-12-12 06:36:03
字體:
供稿:網(wǎng)友

這篇博客為大家介紹一個(gè)android常見的功能――ListView下拉刷新:

首先下拉未松手時(shí)候手機(jī)顯示這樣的界面:


下面的代碼是自定的扎樣的控件:

<span style="font-family: comic sans ms,sans-serif; font-size: 16px;">package com.dhsr.smartID.view;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;import com.example.sirelinkscanapp.R;/*** 自定義控件,完成下拉時(shí)候ListView顯示“圖標(biāo)及提示正在刷新……”的布局* * @author cyf* */public class XListViewHeader extends LinearLayout {private LinearLayout mContainer;// 圖片private ImageView mArrowImageView;// 圓形進(jìn)度條private ProgressBar mProgressBar;private TextView mHintTextView;// 狀態(tài)private int mState = STATE_NORMAL;// 動(dòng)畫private Animation mRotateUpAnim;private Animation mRotateDownAnim;private final int ROTATE_ANIM_DURATION = 180;// 正常public final static int STATE_NORMAL = 0;// 準(zhǔn)備刷新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);}/*** “ 松開即可刷新……正在刷新……”的布局* * @param context*/private void initView(Context context) {// 初始情況,設(shè)置下拉刷新view高度為0LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_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);// 設(shè)置動(dòng)畫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);}/*** 根據(jù)下拉狀態(tài)執(zhí)行相應(yīng)的功能,開始以及停止相應(yīng)的動(dòng)畫* * @param state*/public void setState(int state) {if (state == mState)return;if (state == STATE_REFRESHING) { // 顯示進(jìn)度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) {// 開始動(dòng)畫mArrowImageView.startAnimation(mRotateDownAnim);}//刷新中if (mState == STATE_REFRESHING) {// 清除動(dòng)畫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();}}</span> 

接下來需要自定義自己的ListView繼承與android本身的ListView,方便自己添加新的方法。

<span style="font-family: comic sans ms,sans-serif; font-size: 16px;">package com.dhsr.smartID.view;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;import com.example.sirelinkscanapp.R;/*** 自定義ListView* * @author cyf* */public class XListView extends ListView implements OnScrollListener {private final String TAG = "XListView";private float mLastY = -1;private Scroller mScroller;// 滑動(dòng)private OnScrollListener mScrollListener;// 為外界創(chuàng)建監(jiān)聽private IXListViewListener mListViewListener;// 剛才定義的自定義控件private XListViewHeader mHeaderView;private RelativeLayout mHeaderViewContent;private TextView mHeaderTimeView;private int mHeaderViewHeight; // header view's heightprivate boolean mEnablePullRefresh = true;private boolean mPullRefreshing = false; // is refreashing.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 durationprivate 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);}/*** 初始化控件* * @param context*/private void initWithContext(Context context) {mScroller = new Scroller(context, new DecelerateInterpolator());super.setOnScrollListener(this);mHeaderView = new XListViewHeader(context);mHeaderViewContent = (RelativeLayout) mHeaderView.findViewById(R.id.xlistview_header_content);mHeaderTimeView = (TextView) mHeaderView.findViewById(R.id.xlistview_header_time);addHeaderView(mHeaderView, null, false);mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {mHeaderViewHeight = mHeaderViewContent.getHeight();getViewTreeObserver().removeGlobalOnLayoutListener(this);}});}@Overridepublic void setAdapter(ListAdapter adapter) {// make sure XListViewFooter is the last footer view, and only add once.if (mIsFooterReady == false) {if (mEnablePullLoad) {mIsFooterReady = true;// addFooterView(mFooterView);}}super.setAdapter(adapter);}public void setPullRefreshEnable(boolean enable) {mEnablePullRefresh = enable;if (!mEnablePullRefresh) { // disable, hide the contentmHeaderViewContent.setVisibility(View.INVISIBLE);} else {mHeaderViewContent.setVisibility(View.VISIBLE);}}/*** 停止刷新*/public void stopRefresh() {if (mPullRefreshing == true) {mPullRefreshing = false;resetHeaderHeight();}}// 可使進(jìn)入Activity時(shí)便執(zhí)行下拉刷新public void startRefresh() {if (mPullRefreshing == false) {mPullRefreshing = true;mHeaderView.setState(XListViewHeader.STATE_REFRESHING);mHeaderView.setVisiableHeight(90);if (mListViewListener != null) {mListViewListener.onRefresh();}}}/*** stop load more, reset footer view.*/public void stopLoadMore() {if (mPullLoading == true) {mPullLoading = false;}}/*** 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) { // 未處于刷新狀態(tài),更新箭頭if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) {mHeaderView.setState(XListViewHeader.STATE_READY);} else {mHeaderView.setState(XListViewHeader.STATE_NORMAL);}if (mPullLoading) { // disable, hide the contentmHeaderViewContent.setVisibility(View.INVISIBLE);} else {mHeaderViewContent.setVisibility(View.VISIBLE);}}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 computeScrollinvalidate();}/*** 觸屏監(jiān)聽*/@Overridepublic 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;// DLog.i(TAG, "deltaY is " + deltaY);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) {// last item, already pulled up or want to pull up.}break;default:mLastY = -1; // resetif (getFirstVisiblePosition() == 0) {// invoke refreshif (!mPullRefreshing && mEnablePullRefresh && !mPullLoading&& mHeaderView.getVisiableHeight() > mHeaderViewHeight) {mPullRefreshing = true;mHeaderView.setState(XListViewHeader.STATE_REFRESHING);// DLog.i(TAG, "invoke refresh");if (mListViewListener != null) {// 此時(shí)執(zhí)行刷刷新的方法mListViewListener.onRefresh();}}resetHeaderHeight();} else if (getLastVisiblePosition() == mTotalItemCount - 1) {// invoke load more.if (!mPullLoading && mEnablePullLoad && !mPullRefreshing) {// DLog.i(TAG, "invoke load more");}}break;}return super.onTouchEvent(ev);}@Overridepublic void computeScroll() {if (mScroller.computeScrollOffset()) {if (mScrollBack == SCROLLBACK_HEADER) {mHeaderView.setVisiableHeight(mScroller.getCurrY());} else {}postInvalidate();invokeOnScrolling();}super.computeScroll();}@Overridepublic void setOnScrollListener(OnScrollListener l) {mScrollListener = l;}/*** 在滾動(dòng)時(shí)回調(diào),回調(diào)2-3次,手指沒拋開則回調(diào)2次,scrollState = 2的這次不回調(diào) 第1次:scrollState =* SCROLL_STATE_TOUCH_SCROLL(1) 正在滾動(dòng) 第2次:scrollState =* SCROLL_STATE_FLING(2)手指做了拋的動(dòng)作(手指離開屏幕前,用力滑了一下) 第3次:scrollState =* SCROLL_STATE_IDLE(0) 停止?jié)L動(dòng)*/@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if (mScrollListener != null) {mScrollListener.onScrollStateChanged(view, scrollState);}// 滑到底部時(shí),自動(dòng)加載更多。 也可以禁用此邏輯if (getLastVisiblePosition() == mTotalItemCount - 1&& scrollState == SCROLL_STATE_IDLE) {if (!mPullLoading && mEnablePullLoad && !mPullRefreshing) {// DLog.i(TAG, "invoke load more");}}}/*** 正在滾動(dòng)的時(shí)候回調(diào),停止?jié)L動(dòng)時(shí)才停止回調(diào),單擊時(shí)回調(diào)一次*/@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {// send to user's listenermTotalItemCount = totalItemCount;if (mScrollListener != null) {mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,totalItemCount);}}public void setXListViewListener(IXListViewListener l) {mListViewListener = l;}/*** 監(jiān)聽ListView的滑動(dòng)事件* * @author cyf* */public interface OnXScrollListener extends OnScrollListener {public void onXScrolling(View view);}/*** 自定義接口*/public interface IXListViewListener {// 下拉刷新時(shí)候執(zhí)行的方法public void onRefresh();// 上拉加載時(shí)候執(zhí)行的方法public void onLoadMore();}}</span> 

MainActivity的xml文件中的ListView就不要用android的ListView了,用上面自定義的ListView(加包名)

<span style="font-family: comic sans ms,sans-serif; font-size: 16px;">package com.test.andy;import java.util.ArrayList;import com.test.andy.view.XListView;import com.test.andy.view.XListView.IXListViewListener;import com.test.andy.R;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.widget.ArrayAdapter;/*** XListViewActivity* 實(shí)現(xiàn)IXListViewListener接口是為了實(shí)現(xiàn)其中的下拉刷新等方法* @author cyf**/public class XListViewActivity extends Activity implements IXListViewListener {//自定義的ListViewprivate XListView mListView;private ArrayAdapter<String> mAdapter;private ArrayList<String> items = new ArrayList<String>();private Handler mHandler;private int start = 0;private int refreshCnt = 0;/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);//初始化的時(shí)候加載20條數(shù)據(jù)geneItems();mListView = (XListView) findViewById(R.id.xListView);mListView.setPullLoadEnable(true);mAdapter = new ArrayAdapter<String>(this, R.layout.list_item, items);mListView.setAdapter(mAdapter);// mListView.setPullRefreshEnable(false);mListView.setXListViewListener(this);mHandler = new Handler();mListView.startRefresh();}private void geneItems() {for (int i = 0; i != 20; ++i) {items.add("refresh cnt " + (++start));}}private void onLoad() {mListView.stopRefresh();mListView.stopLoadMore();mListView.setRefreshTime("剛剛");}@Overridepublic void onRefresh() {mHandler.postDelayed(new Runnable() {@Overridepublic void run() {start = ++refreshCnt;items.clear();geneItems();// mAdapter.notifyDataSetChanged();mAdapter = new ArrayAdapter<String>(XListViewActivity.this, R.layout.list_item, items);mListView.setAdapter(mAdapter);onLoad();}}, 2000);}@Overridepublic void onLoadMore() {mHandler.postDelayed(new Runnable() {@Overridepublic void run() {geneItems();mAdapter.notifyDataSetChanged();onLoad();}}, 2000);}}</span> 

重要的代碼都總結(jié)在這了,希望給大家?guī)韼椭x謝。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 巴马| 昭通市| 平定县| 饶河县| 宁德市| 景东| 康乐县| 工布江达县| 罗田县| 镇原县| 兴业县| 桂林市| 巴塘县| 马边| 德保县| 资中县| 黔东| 汕尾市| 青神县| 宁明县| 天峨县| 大田县| 玛多县| 利津县| 平泉县| 平遥县| 广州市| 吉木乃县| 城口县| 元江| 承德县| 望奎县| 岳阳县| 仙桃市| 互助| 余江县| 渭南市| 仪陇县| 平凉市| 牙克石市| 将乐县|