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

首頁 > 系統 > Android > 正文

Android自定義組合控件之自定義下拉刷新和左滑刪除實例代碼

2019-12-12 06:30:14
字體:
來源:轉載
供稿:網友

緒論

最近項目里面用到了下拉刷新和左滑刪除,網上找了找并沒有可以用的,有比較好的左滑刪除,但是并沒有和下拉刷新上拉加載結合到一起,要不就是一些比較水的結合,并不能在項目里面使用,小編一著急自己組合了一個,做完了和QQ的對比了一下,并沒有太大區別,今天分享給大家,其實并不難,但是不知道為什么網上沒有比較好的Demo,當你的項目真的很急的時候,又沒有比較好的Demo,那么“那條友誼的小船兒真是說翻就翻啊”,好了,下面先來具體看一下實現后的效果吧:

這里寫圖片描述 

代碼已經上傳到Github上了,小伙伴們記得star和follow哦

https://github.com/Hankkin/SwipeRefreshDemo

還不錯吧?比QQ多了個上拉加載,好了看看怎么實現的吧,小編在之前的游客評論中了解到,代碼注釋很重要,所以盡量把注釋寫的很清楚:

實現思路

由于時間有限,左滑菜單是在網上找的Demo

自定義下拉刷新頭、尾

手勢判斷,根據滑動距離顯示頭部下拉布局

判斷是否滑動到底部顯示尾部上拉布局

創建左滑菜單,根據手勢滑動事件彈出菜單

詳細的看一下實現過程

1.首先我們先自定義下拉頭布局:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="wrap_content"android:gravity="bottom" ><RelativeLayoutandroid:id="@+id/xlistview_header_content"android:layout_width="fill_parent"android:background="#00000000"android:layout_height="60dp" ><LinearLayoutandroid:id="@+id/xlistview_header_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:gravity="center"android:orientation="vertical" ><TextViewandroid:id="@+id/xlistview_header_hint_textview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#000"android:textSize="16sp"android:text="@string/xlistview_header_hint_normal" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="3dp" ><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#000"android:text="@string/xlistview_header_last_time"android:textSize="14sp" /><TextViewandroid:id="@+id/xlistview_header_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#000"android:textSize="14sp" /></LinearLayout></LinearLayout><ImageViewandroid:id="@+id/xlistview_header_arrow"android:layout_width="wrap_content"android:layout_height="35dp"android:layout_alignLeft="@id/xlistview_header_text"android:layout_centerVertical="true"android:layout_marginLeft="-50dp"android:src="@drawable/xlistview_arrow" /><ProgressBarandroid:id="@+id/xlistview_header_progressbar"android:layout_width="25dp"android:layout_height="25dp"android:layout_alignLeft="@id/xlistview_header_text"android:layout_centerVertical="true"android:layout_marginLeft="-55dp"android:visibility="gone"/></RelativeLayout></LinearLayout>

2.接下來我們自定義HeaderView,代碼很詳細了,不多介紹了

package com.hankkin.library;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 RefreshListHeader extends LinearLayout {//根布局private LinearLayout mContainer;//下拉箭頭圖片private ImageView mArrowImageView;//下拉進度條private ProgressBar mProgressBar;//下拉文本private TextView mHintTextView;//狀態值 0-正常 1-準備刷新 2-正在刷新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 RefreshListHeader(Context context) {super(context);initView(context);}/*** @param context* @param attrs*/public RefreshListHeader(Context context, AttributeSet attrs) {super(context, attrs);initView(context);}/*** 初始化組件* @param context*/private void initView(Context context) {LayoutParams lp = new 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;}/*** 設置頭部高度* @param height*/public void setVisiableHeight(int height) {if (height < 0)height = 0;LayoutParams lp = (LayoutParams) mContainer.getLayoutParams();lp.height = height;mContainer.setLayoutParams(lp);}public int getVisiableHeight() {return mContainer.getHeight();}3.HeaderView定義結束后,我們需要自定義一個既支持下拉刷新又支持左滑刪除的ListView,看看我是怎么做的:(左滑菜單是引用網上的Demo,代碼寫的也比較易懂,這里不詳細給大家介紹了) 然后我們在他的基礎上添加下拉上拉事件:(重點看一下onTouchEvent事件)@Overridepublic boolean onTouchEvent(MotionEvent ev) {if (mLastY == -1) { //獲取上次y軸坐標mLastY = ev.getRawY();}switch (ev.getAction()) {case MotionEvent.ACTION_DOWN: //手勢按下事件、獲取坐標、設置上次下拉時間firstTouchY = ev.getRawY();mLastY = ev.getRawY();setRefreshTime(RefreshTime.getRefreshTime(getContext()));int oldPos = mTouchPosition;mDownX = ev.getX();mDownY = ev.getY();mTouchState = TOUCH_STATE_NONE;mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());//彈出左滑菜單if (mTouchPosition == oldPos && mTouchView != null && mTouchView.isOpen()) {mTouchState = TOUCH_STATE_X;mTouchView.onSwipe(ev);//左滑菜單手勢監聽事件,根據滑動距離彈出菜單return true;}//獲取item view,此方法是因為getChildAt()傳入index值導致listview不可見的item會報空指針// 防止listview不可見的item獲取到的為空,使用下面方法View view = getChildAt(mTouchPosition - getFirstVisiblePosition());if (mTouchView != null && mTouchView.isOpen()) {//如果滑動的item不為空并且已經開啟,則關閉該菜單mTouchView.smoothCloseMenu();mTouchView = null;return super.onTouchEvent(ev);}if (mTouchView != null) {//否則打開左滑菜單mTouchView.onSwipe(ev);}if (view instanceof SwipeMenuLayout) {mTouchView = (SwipeMenuLayout) view;}break;case MotionEvent.ACTION_MOVE://手勢滑動事件final float deltaY = ev.getRawY() - mLastY;float dy = Math.abs((ev.getY() - mDownY));float dx = Math.abs((ev.getX() - mDownX));mLastY = ev.getRawY();//判斷左滑菜單是否未激活、或者x軸偏移平方小于y軸偏移平方3倍的時候if ((mTouchView == null || !mTouchView.isActive()) && Math.pow(dx, 2) / Math.pow(dy, 2) <= 3) {//判斷第一個可見位置并且頭部布局可見高度大于0時或者y軸偏移量>0if (getFirstVisiblePosition() == 0 && (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) {// 重新更新頭部高度updateHeaderHeight(deltaY / OFFSET_RADIO);invokeOnScrolling();}}if (mTouchState == TOUCH_STATE_X) {//如果x軸偏移彈出左滑菜單if (mTouchView != null) {mTouchView.onSwipe(ev);}getSelector().setState(new int[] { 0 });ev.setAction(MotionEvent.ACTION_CANCEL);super.onTouchEvent(ev);return true;} else if (mTouchState == TOUCH_STATE_NONE) {if (Math.abs(dy) > MAX_Y) { //如果y軸偏移量>指定y軸偏移量,設置y軸偏移狀態mTouchState = TOUCH_STATE_Y;} else if (dx > MAX_X) {//如果x軸偏移量>指定x軸偏移量,設置x軸偏移狀態,開始彈出左滑菜單mTouchState = TOUCH_STATE_X;if (mOnSwipeListener != null) {mOnSwipeListener.onSwipeStart(mTouchPosition);}}}break;case MotionEvent.ACTION_UP://手勢抬起事件mLastY = -1; // resetif (getFirstVisiblePosition() == 0) {// 設置下拉刷新狀態值,開啟下拉刷新狀態if (mEnablePullRefresh && mHeaderView.getVisiableHeight() > mHeaderViewHeight) {mPullRefreshing = true;mHeaderView.setState(RefreshListHeader.STATE_REFRESHING);if (onRefreshListener != null) {tag=REFRESH;onRefreshListener.onRefresh();}}resetHeaderHeight();}lastTouchY = ev.getRawY();//獲取上次y軸偏移量if (canLoadMore()) {//判斷是否滿足上拉loadData();}if (mTouchState == TOUCH_STATE_X) {//如果為x軸偏移狀態,開啟左滑if (mTouchView != null) {mTouchView.onSwipe(ev);if (!mTouchView.isOpen()) {mTouchPosition = -1;mTouchView = null;}}if (mOnSwipeListener != null) {mOnSwipeListener.onSwipeEnd(mTouchPosition);}ev.setAction(MotionEvent.ACTION_CANCEL);super.onTouchEvent(ev);return true;}break;}return super.onTouchEvent(ev);}

當然這部分也是滑動沖突解決的主要部分,看一下完整的代碼,應該能夠看的懂了,小編幾乎每一句都加上了注釋,如果有看不明白的地方可以留言,小編會及時回復的:

package com.hankkin.library;import android.content.Context;import android.os.AsyncTask;import android.util.AttributeSet;import android.util.TypedValue;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.ViewTreeObserver.OnGlobalLayoutListener;import android.view.animation.DecelerateInterpolator;import android.view.animation.Interpolator;import android.widget.AbsListView;import android.widget.AbsListView.OnScrollListener;import android.widget.LinearLayout;import android.widget.ListAdapter;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.Scroller;import android.widget.TextView;import java.util.Date;public class RefreshSwipeMenuListView extends ListView implements OnScrollListener {private static final int TOUCH_STATE_NONE = 0;private static final int TOUCH_STATE_X = 1; //x軸觸摸狀態值private static final int TOUCH_STATE_Y = 2; //y軸觸摸狀態值public static final int BOTH=2;//上拉和下拉public static final int HEADER=0;//下拉public static final int FOOTER=1;//上拉public static String tag;//ListView的動作public static final String REFRESH="refresh";public static final String LOAD="load";private int MAX_Y = 5; //Y軸最大偏移量private int MAX_X = 3; //X軸最大偏移量private float mDownX; //觸摸xprivate float mDownY; //觸摸yprivate int mTouchState; //觸摸狀態private int mTouchPosition; //觸摸位置private SwipeMenuLayout mTouchView; //滑動彈出布局private OnSwipeListener mOnSwipeListener; //彈出監聽器private float firstTouchY; //第一次觸摸y坐標private float lastTouchY; //最后一次觸摸y坐標//創建左滑菜單接口private SwipeMenuCreator mMenuCreator;//菜單點擊事件private OnMenuItemClickListener mOnMenuItemClickListener;//關閉菜單動畫修飾Interpolatorprivate Interpolator mCloseInterpolator;//開啟菜單動畫修飾Interpolatorprivate Interpolator mOpenInterpolator;private float mLastY = -1;private Scroller mScroller;private OnScrollListener mScrollListener; // 滑動監聽// 下拉上拉監聽器private OnRefreshListener onRefreshListener;//下拉頭private RefreshListHeader mHeaderView;//頭部視圖內容,用來計算頭部高度,不下拉時隱藏private RelativeLayout mHeaderViewContent;//下拉時間文本控件private TextView mHeaderTimeView;private int mHeaderViewHeight; // 頭部高度private boolean mEnablePullRefresh = true;//能否下拉刷新private boolean mPullRefreshing = false; // 是否正在刷新//上拉尾部視圖private LinearLayout mFooterView;private boolean mEnablePullLoad;//是否可以上拉加載private boolean mPullLoading; //是否正在上拉private boolean mIsFooterReady = false;private int mTotalItemCount;private int mScrollBack;private final static int SCROLLBACK_HEADER = 0;private final static int SCROLLBACK_FOOTER = 1;private final static int SCROLL_DURATION = 400;private final static int PULL_LOAD_MORE_DELTA = 50;private final static float OFFSET_RADIO = 1.8f;private boolean isFooterVisible=false;public RefreshSwipeMenuListView(Context context) {super(context);init(context);}public RefreshSwipeMenuListView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(context);}public RefreshSwipeMenuListView(Context context, AttributeSet attrs) {super(context, attrs);init(context);}/*** 初始化組件* @param context*/private void init(Context context) {mScroller = new Scroller(context, new DecelerateInterpolator());super.setOnScrollListener(this);// 初始化頭部視圖mHeaderView = new RefreshListHeader(context);mHeaderViewContent = (RelativeLayout) mHeaderView.findViewById(R.id.xlistview_header_content);mHeaderTimeView = (TextView) mHeaderView.findViewById(R.id.xlistview_header_time);addHeaderView(mHeaderView);// 初始化尾部視圖mFooterView = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.xlistview_footer, null, false);// 初始化頭部高度mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {mHeaderViewHeight = mHeaderViewContent.getHeight();//向 ViewTreeObserver 注冊方法,以獲取控件尺寸getViewTreeObserver().removeGlobalOnLayoutListener(this);}});MAX_X = dp2px(MAX_X);MAX_Y = dp2px(MAX_Y);mTouchState = TOUCH_STATE_NONE;}/*** 添加適配器* @param adapter*/@Overridepublic void setAdapter(ListAdapter adapter) {if (mIsFooterReady == false) { //添加尾部隱藏mIsFooterReady = true;addFooterView(mFooterView);mFooterView.setVisibility(GONE);}super.setAdapter(new SwipeMenuAdapter(getContext(), adapter) {@Overridepublic void createMenu(SwipeMenu menu) {//創建左滑菜單if (mMenuCreator != null) {mMenuCreator.create(menu);}}@Overridepublic void onItemClick(SwipeMenuView view, SwipeMenu menu, int index) {if (mOnMenuItemClickListener != null) {//左滑菜單點擊事件mOnMenuItemClickListener.onMenuItemClick(view.getPosition(), menu, index);}if (mTouchView != null) {mTouchView.smoothCloseMenu();}}});}public void setCloseInterpolator(Interpolator interpolator) {mCloseInterpolator = interpolator;}public void setOpenInterpolator(Interpolator interpolator) {mOpenInterpolator = interpolator;}public Interpolator getOpenInterpolator() {return mOpenInterpolator;}public Interpolator getCloseInterpolator() {return mCloseInterpolator;}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {return super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent ev) {if (mLastY == -1) { //獲取上次y軸坐標mLastY = ev.getRawY();}switch (ev.getAction()) {case MotionEvent.ACTION_DOWN: //手勢按下事件、獲取坐標、設置上次下拉時間firstTouchY = ev.getRawY();mLastY = ev.getRawY();setRefreshTime(RefreshTime.getRefreshTime(getContext()));int oldPos = mTouchPosition;mDownX = ev.getX();mDownY = ev.getY();mTouchState = TOUCH_STATE_NONE;mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());//彈出左滑菜單if (mTouchPosition == oldPos && mTouchView != null && mTouchView.isOpen()) {mTouchState = TOUCH_STATE_X;mTouchView.onSwipe(ev);//左滑菜單手勢監聽事件,根據滑動距離彈出菜單return true;}//獲取item view,此方法是因為getChildAt()傳入index值導致listview不可見的item會報空指針// 防止listview不可見的item獲取到的為空,使用下面方法View view = getChildAt(mTouchPosition - getFirstVisiblePosition());if (mTouchView != null && mTouchView.isOpen()) {//如果滑動的item不為空并且已經開啟,則關閉該菜單mTouchView.smoothCloseMenu();mTouchView = null;return super.onTouchEvent(ev);}if (mTouchView != null) {//否則打開左滑菜單mTouchView.onSwipe(ev);}if (view instanceof SwipeMenuLayout) {mTouchView = (SwipeMenuLayout) view;}break;case MotionEvent.ACTION_MOVE://手勢滑動事件final float deltaY = ev.getRawY() - mLastY;float dy = Math.abs((ev.getY() - mDownY));float dx = Math.abs((ev.getX() - mDownX));mLastY = ev.getRawY();//判斷左滑菜單是否未激活、或者x軸偏移平方小于y軸偏移平方3倍的時候if ((mTouchView == null || !mTouchView.isActive()) && Math.pow(dx, 2) / Math.pow(dy, 2) <= 3) {//判斷第一個可見位置并且頭部布局可見高度大于0時或者y軸偏移量>0if (getFirstVisiblePosition() == 0 && (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) {// 重新更新頭部高度updateHeaderHeight(deltaY / OFFSET_RADIO);invokeOnScrolling();}}if (mTouchState == TOUCH_STATE_X) {//如果x軸偏移彈出左滑菜單if (mTouchView != null) {mTouchView.onSwipe(ev);}getSelector().setState(new int[] { 0 });ev.setAction(MotionEvent.ACTION_CANCEL);super.onTouchEvent(ev);return true;} else if (mTouchState == TOUCH_STATE_NONE) {if (Math.abs(dy) > MAX_Y) { //如果y軸偏移量>指定y軸偏移量,設置y軸偏移狀態mTouchState = TOUCH_STATE_Y;} else if (dx > MAX_X) {//如果x軸偏移量>指定x軸偏移量,設置x軸偏移狀態,開始彈出左滑菜單mTouchState = TOUCH_STATE_X;if (mOnSwipeListener != null) {mOnSwipeListener.onSwipeStart(mTouchPosition);}}}break;case MotionEvent.ACTION_UP://手勢抬起事件mLastY = -1; // resetif (getFirstVisiblePosition() == 0) {// 設置下拉刷新狀態值,開啟下拉刷新狀態if (mEnablePullRefresh && mHeaderView.getVisiableHeight() > mHeaderViewHeight) {mPullRefreshing = true;mHeaderView.setState(RefreshListHeader.STATE_REFRESHING);if (onRefreshListener != null) {tag=REFRESH;onRefreshListener.onRefresh();}}resetHeaderHeight();}lastTouchY = ev.getRawY();//獲取上次y軸偏移量if (canLoadMore()) {//判斷是否滿足上拉loadData();}if (mTouchState == TOUCH_STATE_X) {//如果為x軸偏移狀態,開啟左滑if (mTouchView != null) {mTouchView.onSwipe(ev);if (!mTouchView.isOpen()) {mTouchPosition = -1;mTouchView = null;}}if (mOnSwipeListener != null) {mOnSwipeListener.onSwipeEnd(mTouchPosition);}ev.setAction(MotionEvent.ACTION_CANCEL);super.onTouchEvent(ev);return true;}break;}return super.onTouchEvent(ev);}class ResetHeaderHeightTask extends AsyncTask<Void, Void, Void> {protected Void doInBackground(Void... params) {try {Thread.sleep(400);} catch (InterruptedException e) {e.printStackTrace();}return null;}protected void onPostExecute(Void result) {mPullRefreshing = false;mHeaderView.setState(RefreshListHeader.STATE_NORMAL);resetHeaderHeight();}}public void smoothOpenMenu(int position) {if (position >= getFirstVisiblePosition() && position <= getLastVisiblePosition()) {View view = getChildAt(position - getFirstVisiblePosition());if (view instanceof SwipeMenuLayout) {mTouchPosition = position;if (mTouchView != null && mTouchView.isOpen()) {mTouchView.smoothCloseMenu();}mTouchView = (SwipeMenuLayout) view;mTouchView.smoothOpenMenu();}}}private int dp2px(int dp) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,getContext().getResources().getDisplayMetrics());}public void setMenuCreator(SwipeMenuCreator menuCreator) {this.mMenuCreator = menuCreator;}public void setOnMenuItemClickListener(OnMenuItemClickListener onMenuItemClickListener) {this.mOnMenuItemClickListener = onMenuItemClickListener;}public void setOnSwipeListener(OnSwipeListener onSwipeListener) {this.mOnSwipeListener = onSwipeListener;}public static interface OnMenuItemClickListener {void onMenuItemClick(int position, SwipeMenu menu, int index);}public static interface OnSwipeListener {void onSwipeStart(int position);void onSwipeEnd(int position);}/*** 設置刷新可用* @param enable*/private void setPullRefreshEnable(boolean enable) {mEnablePullRefresh = enable;if (!mEnablePullRefresh) { // disable, hide the contentmHeaderViewContent.setVisibility(View.INVISIBLE);} else {mHeaderViewContent.setVisibility(View.VISIBLE);}}/*** enable or disable pull up load more feature.* 設置加載可用* @param enable*/private void setPullLoadEnable(boolean enable) {mEnablePullLoad = enable;if (!mEnablePullLoad) {mFooterView.setVisibility(GONE);mFooterView.setOnClickListener(null);} else {mPullLoading = false;mFooterView.setVisibility(VISIBLE);// both "pull up" and "click" will invoke load more.mFooterView.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {startLoadMore();}});}}/*** stop refresh, reset header view.* 停止刷新,重置頭部控件*/private void stopRefresh() {if (mPullRefreshing == true) {mPullRefreshing = false;resetHeaderHeight();}}/*** stop load more, reset footer view.* 停止加載更多,重置尾部控件*/private void stopLoadMore() {if (mPullLoading == true) {mPullLoading = false;mFooterView.setVisibility(GONE);}}/*** 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);}}/*** 更新頭部高度,設置狀態值* @param delta*/private void updateHeaderHeight(float delta) {mHeaderView.setVisiableHeight((int) delta + mHeaderView.getVisiableHeight());if (mEnablePullRefresh && !mPullRefreshing) {if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) {mHeaderView.setState(RefreshListHeader.STATE_READY);} else {mHeaderView.setState(RefreshListHeader.STATE_NORMAL);}}setSelection(0); // scroll to top each time}/*** 重置頭部視圖高度*/private void resetHeaderHeight() {int height = mHeaderView.getVisiableHeight();if (height == 0) // 不可見return;// 如果正在刷新并且頭部高度沒有完全顯示不做操作if (mPullRefreshing && height <= mHeaderViewHeight) {return;}int finalHeight = 0; // 默認//如果正在刷新并且滑動高度大于頭部高度if (mPullRefreshing && height > mHeaderViewHeight) {finalHeight = mHeaderViewHeight;}mScrollBack = SCROLLBACK_HEADER;mScroller.startScroll(0, height, 0, finalHeight - height, SCROLL_DURATION);// 觸發computescrollinvalidate();}/*** 開啟上啦*/private void startLoadMore() {mPullLoading = true;mFooterView.setVisibility(VISIBLE);if (onRefreshListener != null) {tag=LOAD;onRefreshListener.onLoadMore();}}@Overridepublic void computeScroll() {if (mScroller.computeScrollOffset()) {if (mScrollBack == SCROLLBACK_HEADER) {mHeaderView.setVisiableHeight(mScroller.getCurrY());} postInvalidate();invokeOnScrolling();}super.computeScroll();}@Overridepublic void setOnScrollListener(OnScrollListener l) {mScrollListener = l;}@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if (mScrollListener != null) {mScrollListener.onScrollStateChanged(view, scrollState);}}/*** 滑動監聽* @param view* @param firstVisibleItem* @param visibleItemCount* @param totalItemCount*/@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {mTotalItemCount = totalItemCount;if (mScrollListener != null) {mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);}if(firstVisibleItem+visibleItemCount>=totalItemCount){isFooterVisible=true;}else{isFooterVisible=false;}}public void setOnRefreshListener(OnRefreshListener l) {onRefreshListener = 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 OnRefreshListener {public void onRefresh();public void onLoadMore();}/*** 上拉加載和下拉刷新請求完畢*/public void complete(){stopLoadMore();stopRefresh();if(REFRESH.equals(tag)){RefreshTime.setRefreshTime(getContext(),new Date());}}/*** 設置ListView的模式,上拉和下拉* @param mode*/public void setListViewMode(int mode){if(mode==BOTH){setPullRefreshEnable(true);setPullLoadEnable(true);}else if(mode==FOOTER){setPullLoadEnable(true);}else if(mode==HEADER){setPullRefreshEnable(true);}}/*** 判斷是否可以上蠟加載* @return*/private boolean canLoadMore() {return isBottom() && !mPullLoading && isPullingUp();}/*** 判斷是否到達底部* @return*/private boolean isBottom() {if (getCount() > 0) {if (getLastVisiblePosition() == getAdapter().getCount() - 1 &&getChildAt(getChildCount() - 1).getBottom() <= getHeight()) {return true;}}return false;}private boolean isPullingUp() {return (firstTouchY - lastTouchY) >= 200;}private void loadData() {if (onRefreshListener != null) {setLoading(true);}}/*** 設置是否上拉* @param loading*/public void setLoading(boolean loading) {if (this == null) return;mPullLoading = loading;if (loading) {mFooterView.setVisibility(VISIBLE);setSelection(getAdapter().getCount() - 1);onRefreshListener.onLoadMore();} else {mFooterView.setVisibility(GONE);firstTouchY = 0;lastTouchY = 0;}}

定義完了之后我們是這樣用的:

rsmLv.setAdapter(adapter);rsmLv.setListViewMode(RefreshSwipeMenuListView.HEADER);rsmLv.setOnRefreshListener(this);SwipeMenuCreator creator = new SwipeMenuCreator() {@Overridepublic void create(SwipeMenu menu) {// 創建滑動選項SwipeMenuItem rejectItem = new SwipeMenuItem(getApplicationContext());// 設置選項背景rejectItem.setBackground(new ColorDrawable(getResources().getColor(R.color.top)));// 設置選項寬度rejectItem.setWidth(dp2px(80,getApplicationContext()));// 設置選項標題rejectItem.setTitle("置頂");// 設置選項標題rejectItem.setTitleSize(16);// 設置選項標題顏色rejectItem.setTitleColor(Color.WHITE);// 添加選項menu.addMenuItem(rejectItem);// 創建刪除選項SwipeMenuItem argeeItem = new SwipeMenuItem(getApplicationContext());argeeItem.setBackground(new ColorDrawable(getResources().getColor(R.color.del)));argeeItem.setWidth(dp2px(80, getApplicationContext()));argeeItem.setTitle("刪除");argeeItem.setTitleSize(16);argeeItem.setTitleColor(Color.WHITE);menu.addMenuItem(argeeItem);}};rsmLv.setMenuCreator(creator);rsmLv.setOnMenuItemClickListener(new RefreshSwipeMenuListView.OnMenuItemClickListener() {@Overridepublic void onMenuItemClick(int position, SwipeMenu menu, int index) {switch (index) {case 0: //第一個選項Toast.makeText(MainActivity.this,"您點擊的是置頂",Toast.LENGTH_SHORT).show();break;case 1: //第二個選項del(position,rsmLv.getChildAt(position+1-rsmLv.getFirstVisiblePosition()));break;}}});

為了和QQ有著一樣的體驗效果,小編加了一個刪除item的動畫
看起來就不會太生硬了,用戶體驗也比較好:

/*** 刪除item動畫* @param index* @param v*/private void del(final int index, View v){final Animation animation = (Animation) AnimationUtils.loadAnimation(v.getContext(), R.anim.list_anim);animation.setAnimationListener(new Animation.AnimationListener() {public void onAnimationStart(Animation animation) {}public void onAnimationRepeat(Animation animation) {}public void onAnimationEnd(Animation animation) {data.remove(index);adapter.notifyDataSetChanged();animation.cancel();}});v.startAnimation(animation);}

好了到這里了,我們的組合控件-上拉下拉+左滑刪除的組合ListView就定義好了,分享出來小伙伴們以后遇到可以直接拿來用,”到時候小船兒也不會再翻了”,不合理的地方希望大家提出來,共同交流,進步。

以上所述是小編給大家介紹的Android自定義組合控件之自定義下拉刷新和左滑刪除實例代碼,希望對大家有所幫助!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 无极县| 芦溪县| 苏尼特右旗| 武功县| 景洪市| 密山市| 逊克县| 白银市| 柳江县| 华阴市| 台安县| 嘉善县| 安丘市| 侯马市| 车险| 山丹县| 昔阳县| 永清县| 邻水| 宜兰市| 沈阳市| 师宗县| 广灵县| 阳曲县| 门头沟区| 林芝县| 视频| 伊金霍洛旗| 会东县| 陕西省| 云浮市| 桃源县| 灵宝市| 盱眙县| 新乐市| 珠海市| 秦安县| 潞西市| 察哈| 阳高县| 洛扎县|