您好,登錄后才能下訂單哦!
自定義控件學了很久了,發現學了總是忘,于是打算用博客來記錄自己學習的知識點。
今天是自定義ListView來實現下拉刷新,這些文章都是借鑒慕課網上的視頻來寫的.
自定義一個控件,先是看它繼承于那個控件,如果我們繼承View控件的話,那得讓我們寫很多關于ListView的功能,這些東西我自己覺得很麻煩,而且也沒有那個必要因為我們可以直接繼承ListView,在listView的基礎上來加一些我們需要的東西。
1.向ListView加Header布局
private void initView(Context context) { mLayoutInflater = LayoutInflater.from(context); mHeaerView = mLayoutInflater.inflate(R.layout.header_layout, null, false); addHeaderView(mHeaerView); }
2.隱藏Header布局
private void initView(Context context) { mLayoutInflater = LayoutInflater.from(context); mHeaerView = mLayoutInflater.inflate(R.layout.header_layout, null, false); measureView(mHeaerView); mHeaderViewHeight = mHeaerView.getMeasuredHeight(); setHeaderViewHeightPadding(mHeaderViewHeight); Log.i("main", mHeaderViewHeight + ""); addHeaderView(mHeaerView); } private void measureView(View view) { ViewGroup.LayoutParams lp = view.getLayoutParams(); if(lp == null) { lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } //mHeaerView.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); /** * width 和height里面包含的不僅僅有View的寬和高,還有View控件的測量模式 * 測量模式的產生方式就是如下所示 */ int width = ViewGroup.getChildMeasureSpec(0,0,lp.width); int height = 0; int tempHeight = lp.height; if(tempHeight > 0) { height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY); } view.measure(width, height); } private void setHeaderViewHeightPadding(int padding) { mHeaerView.setPadding(mHeaerView.getPaddingLeft(), -padding, mHeaerView.getPaddingRight(), mHeaerView.getPaddingBottom()); mHeaerView.invalidate(); }
3.實現ListView的下拉刷新(一)
要想實現ListView的下拉刷新,必須監聽ListView是否滑動到最頂端,因此要實現ListView的監聽接口OnScrollListener,并且要監聽ListView的OnTouch事件。根據滑動的情況來判斷刷新的情況。
首先我們在定義了一個成員變量來保存ListView的狀態--mState
其次定義了幾個靜態常量來表示不同的狀態
private final static int NONE = 0; // 無狀態 private final static int DOWN_UPDATE = 1; // 提示下拉可以刷新 private final static int UPDATE = 2; // 提示松開可以刷新 private final static int REFLASH = 3; // 更新
最后則是根據不同的滑動來更改mState的狀態
@Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: { if (mFirstVisibleItem == 0) { mIsRemark = true; // mIsRemark只是一個標記,表示當前可見的第一個Item是不是所有的Item中的第一個 mStartY = (int) ev.getY(); Log.i("main", "我進來了"); } break; } case MotionEvent.ACTION_MOVE: { onMove(ev); tempY = (int) (ev.getY() - mStartY); Log.i("main", "tempY = " + tempY); break; } case MotionEvent.ACTION_UP: { if(mState == DOWN_UPDATE) { mState = NONE; } if(mState == UPDATE) { mState = REFLASH; mListener.reFlash(); Log.i("main", "我來了"); } Log.i("main", "tempY11 = " + tempY); if(tempY <= 0 && mIsRemark) { Log.i("main", "我進來le"); mState = NONE; } change(); break; } } return super.onTouchEvent(ev); } private void onMove(MotionEvent ev) { if (mIsRemark) { if (ev.getY() - mStartY > 0) { int dy = (int) (ev.getY() - mStartY); if (dy > mHeaderViewHeight + 20) { mState = UPDATE; } else { mState = DOWN_UPDATE; } setHeaderViewHeightPadding(mHeaderViewHeight - dy); change(); } return; } return; } /** *change方法主要是用來處理不同狀態下的事件 * */ private void change() { initChildView(); RotateAnimation ani = new RotateAnimation(0, 180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); ani.setDuration(500); ani.setFillAfter(true); RotateAnimation ani1 = new RotateAnimation(180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); ani1.setDuration(500); ani1.setFillAfter(true); if (mState == UPDATE) { mProgressBar.setVisibility(View.GONE); mImageView.setVisibility(View.VISIBLE); mImageView.clearAnimation(); mImageView.setAnimation(ani); mTextViewFlash.setText("松開可以刷新!"); mTextViewTime.setVisibility(View.VISIBLE); mTextViewTime.setText("上次更新的時間:" + mUpdateTime); } if (mState == DOWN_UPDATE) { mProgressBar.setVisibility(View.GONE); mImageView.setVisibility(View.VISIBLE); mTextViewTime.setVisibility(View.VISIBLE); mImageView.clearAnimation(); mImageView.setAnimation(ani1); mTextViewFlash.setText("下拉可以刷新"); mTextViewTime.setText("上次更新的時間:" + mUpdateTime); } if (mState == REFLASH) { setHeaderViewHeightPadding(10); mProgressBar.setVisibility(View.VISIBLE); mImageView.setVisibility(View.GONE); mTextViewTime.setVisibility(View.GONE); mTextViewFlash.setText("正在刷新..."); mImageView.clearAnimation(); } if(mState == NONE) { Log.i("main", "workspace"); setHeaderViewHeightPadding(mHeaderViewHeight); mIsRemark = false; mProgressBar.setVisibility(View.GONE); mImageView.setVisibility(View.VISIBLE); mImageView.setAnimation(ani1); } } private void initChildView() { if(mTextViewFlash == null) { mTextViewFlash = (TextView) mHeaerView.findViewById(R.id.id_textView_Flash); } if(mTextViewTime == null) { mTextViewTime = (TextView) mHeaerView.findViewById(R.id.id_textView_Time); } if(mImageView == null) { mImageView = (ImageView) mHeaerView.findViewById(R.id.id_imagView); } if(mProgressBar == null) { mProgressBar = (ProgressBar) mHeaerView.findViewById(R.id.id_progressbar); } }
4.實現ListView的下拉刷新(二)
經過上面的過程,是可以下拉的,處理不同狀態下的事件。還有一個問題就是刷新,也就是加載新的數據。加載刷新的操作肯定必須在UI線程中,因此ListView中必須得有一個回調接口,用來MinaActivity來實現,并且來進行一些操作。
回調接口:
public void setOnFlashListener(FlashListener listener) { this.mListener = listener; } public interface FlashListener { void reFlash(); }
回調接口的調用:
if(mState == UPDATE) { mState = REFLASH; mListener.reFlash(); Log.i("main", "我來了"); }
MainActivity中回調接口的實現和接口方法的實現:
mListView.setOnFlashListener(new FlashListView.FlashListener() { @Override public void reFlash() { Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { addDatas(); loadDatas(); mListView.reFalshComplete(); } }, 5000); } }); private void addDatas() { int i = mDatas.size(); for(int j = i; j < i + 10; j++) { mDatas.add(new Bean("Title" + j, "Content" + j, R.mipmap.ic_launcher)); } myAdapter.dataChange(mDatas); } private void loadDatas() { mListView.setAdapter(myAdapter); }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。