最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android仿微信列表滑動刪除 如何實現(xiàn)滑動列表SwipeListView

 更新時間:2016年08月31日 12:00:48   作者:ly513782705  
這篇文章主要為大家詳細介紹了Android仿微信列表滑動刪除,如何實現(xiàn)滑動列表SwipeListView,感興趣的小伙伴們可以參考一下

上一篇,本篇主要講如何實現(xiàn)滑動列表SwipeListView。

上篇完成了滑動控件SwipeItemView,這個控件是一個自定義的ViewGroup,作為列表的一個item,為列表提供一些方法讓這個SwipeItemView能滑動其視圖內容,同時滑動過程中會有順滑的動畫效果。而本篇講的SwipeListView則是這個列表的具體實現(xiàn)了。當然啦,這個SwipeListView繼承自ListView,為了實現(xiàn)我們需要的功能,重點就是重寫ListView的onTouchEvent()以及onInterceptTouchEvent()這個方法了。先說onTouchEvent():

@Override
  public boolean onTouchEvent(MotionEvent ev) {

    //if user had not set mSwipeItemViewID, not handle any touch event
    if(mSwipeItemViewID == -1)
      return super.onTouchEvent(ev);

    if(mCancelMotionEvent && ev.getAction() == MotionEvent.ACTION_DOWN) {
      //ev.setAction(MotionEvent.ACTION_CANCEL);
      LogUtil.Log("SwipeListView.onTouchEvent(), cancel ACTION_DOWN");
      hideShowingItem();

      return true;
    } else if(mCancelMotionEvent && ev.getAction() == MotionEvent.ACTION_MOVE) {
      if(mSwipeItemView.getCurrentScrollX() > 0) {
        mSwipeItemView.computeScroll();
        //mSwipeItemView.scrollBy(-1, 0);
      }

      return true;
    } else if(mCancelMotionEvent && ev.getAction() == MotionEvent.ACTION_UP) {
      mCancelMotionEvent = false;

      return true;
    }

    switch(ev.getAction()) {
      case MotionEvent.ACTION_DOWN: {
        LogUtil.Log("ACTION_DOWN");
        if(mTracker == null) {
          mTracker = VelocityTracker.obtain();
        } else {
          mTracker.clear();
        }

        mActionDownX = ev.getX();
        mActionDownY = ev.getY();
        mLastMotionX = ev.getX();
        mLastMotionY = ev.getY();
      }break;

      case MotionEvent.ACTION_MOVE: {
        //if the scroll distance at X-axis or Y-axis less than the
        //TOUCH_SLOP, do not handle the event MotionEvent.ACTION_MOVE
        if(Math.abs(ev.getX() - mActionDownX) < TOUCH_SLOP
            || Math.abs(ev.getY() - mActionDownY) < TOUCH_SLOP)
          break;

        float curX = ev.getX();
        float curY = ev.getY();
        int distanceX = (int)(mLastMotionX - curX);
        int distanceY = (int)(mLastMotionY - curY);

        if(mScrollDirection == DIRECTION_UNKNOW
            && Math.abs(distanceY) <= Math.abs(distanceX))
          mScrollDirection = DIRECTION_HORIZONTAL;
        else if(mScrollDirection == DIRECTION_UNKNOW
            && Math.abs(distanceY) > Math.abs(distanceX))
          mScrollDirection = DIRECTION_VERTICAL;

        //if ListView is scrolling vertical, do not handle the touch event
        if(mScrollDirection == DIRECTION_VERTICAL)
          break;

        int lastPos = pointToPosition((int)mActionDownX, (int)mActionDownY);
        int firstVisibleItemPos = getFirstVisiblePosition()
            - getHeaderViewsCount();
        int factPos = lastPos - firstVisibleItemPos;
        mItemView = getChildAt(factPos);
        if(mItemView != null) {
          mSwipeItemView = (SwipeItemView)mItemView.findViewById(mSwipeItemViewID);
          if(mSwipeItemView.getSlidingView() != null
              && mSwipeItemView.getScrollX()
                  <= mSwipeItemView.getSlidingView().getWidth()
              && mSwipeItemView.getScrollX() >= 0) {
            if(mSwipeItemView.getScrollX() + distanceX
                > mSwipeItemView.getSlidingView().getWidth())
              distanceX = mSwipeItemView.getSlidingView().getWidth()
                  - mSwipeItemView.getScrollX();
            else if(mSwipeItemView.getScrollX() + distanceX < 0)
              distanceX = -mSwipeItemView.getScrollX();

            mSwipeItemView.scrollBy(distanceX, 0);
          }

          mLastShowingPos = lastPos;

          ev.setAction(MotionEvent.ACTION_CANCEL);
        }

        mLastMotionX = curX;
        mLastMotionY = curY;
      }break;

      case MotionEvent.ACTION_UP: {
        LogUtil.Log("ACTION_UP");
        if(mTracker != null) {
          mTracker.clear();
          mTracker.recycle();
          mTracker = null;
        }

        //reset the mScrollDirection to DIRECTION_UNKNOW
        mScrollDirection = DIRECTION_UNKNOW;

        //reset the mCancelMotionEvent to false
        mCancelMotionEvent = false;

        //ensure if the showing item need open or hide
        if(mLastShowingPos != -1)
          ensureIfItemOpenOrHide();
      }break;

      case MotionEvent.ACTION_CANCEL: {
        hideShowingItem();
      }break;
    }

    return super.onTouchEvent(ev);
  }

上面代碼,首先分析用戶滑開一個item的操作,這個操作以ACTION_DOWN起始,一系列的ACTION_MOVE,以ACTION_UP作為結束,所以,在ACTION_DOWN事件里面,我們先記錄下最開始的事件位置mActionDownX和mActionDownY;然后再ACTION_MOVE事件里面,我們先要進行判斷,這個判斷分兩步,第一步,判斷這個ACTION_MOVE事件下,當前事件的位置curX和curY在x軸上以及y軸上和ACTION_DOWN里面記錄的位置的距離是否已經超過TOUCH_SLOP的值,這個值是android用來判斷是否應該進行一次滑動的閾值,第二步,我們要進一步判斷用戶是縱向滑動這整個列表還是左右滑動某個item,這里的邏輯判斷就簡單點處理,若是超過TOUCH_SLOP閾值的情況下,x軸方向上距離大于y軸的,我們就認為用戶是左右滑動單個item,反之則是縱向滑動整個列表,這里我們用三種狀態(tài)區(qū)分,DIRECTION_UNKNOW表示當前的滑動操作還沒有進行判斷左右滑動還是縱向滑動,DIRECTION_HORIZONTAL表示當前滑動操作判定為左右滑動,DIRECTION_VERTICAL表示判定為縱向滑動,一旦滑動操作被判定了,則在ACTION_UP處理前,我們都認為用戶是做同一方向的滑動;ACTION_UP事件里面,重置滑動操作狀態(tài)為DIRECTION_UNKNOW以便下一次的判定,以及這次ACTION_UP事件處理的時候,如果當前滑開的item的位置mLastShowingPos不為-1,則表示當前是一次滑開的操作,這次仔細想想,用戶可能在并沒有完全滑開這個item的狀態(tài)下手就離開屏幕了,這時候我們就應該要判斷此時這個被滑動的item是應該完全打開又或者是關閉,這里的邏輯判斷是item已經滑開的距離超過它本身寬度的一半的話,就完全打開它,否則就關閉它,ensureIfItemOpenOrHide()的具體代碼如下:

 private void ensureIfItemOpenOrHide() {
    if(mLastShowingPos != -1) {
      int firstVisibleItemPos = getFirstVisiblePosition()
          - getHeaderViewsCount();
      int factPos = mLastShowingPos - firstVisibleItemPos;
      mItemView = getChildAt(factPos);
      if(mItemView != null) {
        mSwipeItemView = (SwipeItemView)mItemView.findViewById(mSwipeItemViewID);
        if(mSwipeItemView.getSlidingView() != null &&
            mSwipeItemView.getScrollX() >=
                mSwipeItemView.getSlidingView().getWidth() / 2) {
          openShowingItem();
        } else if(mSwipeItemView.getSlidingView() != null) {
          hideShowingItem();
        }
      }
    }
  }

那第一次的用戶滑動操作的邏輯判定我們就算處理完了。接下來是第二次的,為什么說第二次呢,第一次用戶滑開了某單個的item,使其處于打開的狀態(tài)下,再一次觸摸屏幕,這次我們則要再一次進行判定,其一,如果ACTION_DOWN發(fā)生的位置在item滑開顯示出來的button的范圍內,表示當前用戶是點擊這個button,這樣我們就不做額外處理,直接交由列表默認的邏輯處理;其二,如果ACTION_DOWN發(fā)生的位置不在item滑開后顯示出來的button范圍內,怎表示當前用戶只是操作列表的其他范圍,這里我們就關閉當前打開了的item,并取消后續(xù)的touch事件,這里的話,我們就要截獲這個ACTIOIN_DOWN事件了,需要重寫ListView的onInterceptTouchEvent()方法,代碼如下:

public boolean onInterceptTouchEvent(MotionEvent ev) {
    //if user had not set mSwipeItemViewID, not handle any touch event
    if(mSwipeItemViewID == -1)
      return super.onInterceptTouchEvent(ev);

    if(mLastShowingPos != -1
        && ev.getAction() == MotionEvent.ACTION_DOWN
        && !isClickChildView(ev)) {
      LogUtil.Log("SwipeListView.onInterceptTouchEvent(), intercept ACTION_DOWN");
      mCancelMotionEvent = true;

      return true;
    } else if(mLastShowingPos == -1
        && ev.getAction() == MotionEvent.ACTION_DOWN) {
      return true;
    }

    return super.onInterceptTouchEvent(ev);
  }  

上面的mCancelMotionEvent是用來在onTouchEvent()里面判斷是否需要取消后續(xù)touch事件的標志,那期間,如何判斷當前的ACTION_DOWN事件是否發(fā)生在button的范圍內呢,使用如下代碼:

private boolean isClickChildView(MotionEvent event) {
    if(mLastShowingPos != -1) {
      int firstVisibleItemPos = getFirstVisiblePosition()
          - getHeaderViewsCount();
      int factPos = mLastShowingPos - firstVisibleItemPos;
      mItemView = getChildAt(factPos);
      if(mItemView != null) {
        mSwipeItemView = (SwipeItemView)mItemView.findViewById(mSwipeItemViewID);
        View slidingView = mSwipeItemView.getSlidingView();
        if(slidingView != null) {
          int[] slidingViewLocation = new int[2];
          slidingView.getLocationOnScreen(slidingViewLocation);

          int left = slidingViewLocation[0];
          int right = slidingViewLocation[0] + slidingView.getWidth();
          int top = slidingViewLocation[1];
          int bottom = slidingViewLocation[1] + slidingView.getHeight();

          return (event.getRawX() > left && event.getRawX() < right
              && event.getRawY() > top && event.getRawY() < bottom);
        }
      }
    }

    return false;
  }

剩下的,就是如何打開或者關閉一個item了,代碼如下:

private void openShowingItem() {
    if(mLastShowingPos != -1) {
      int firstVisibleItemPos = getFirstVisiblePosition()
          - getHeaderViewsCount();
      int factPos = mLastShowingPos - firstVisibleItemPos;
      mItemView = getChildAt(factPos);
      if(mItemView != null) {
        mSwipeItemView = (SwipeItemView)mItemView.findViewById(mSwipeItemViewID);
        if(mSwipeItemView.getSlidingView() != null)
          mSwipeItemView.scrollToWithAnimation(
              mSwipeItemView.getSlidingView().getWidth(), 0);
      }
    }
  }
   private void hideShowingItem() {
    if(mLastShowingPos != -1) {
      int firstVisibleItemPos = getFirstVisiblePosition()
          - getHeaderViewsCount();
      int factPos = mLastShowingPos - firstVisibleItemPos;
      mItemView = getChildAt(factPos);
      if(mItemView != null) {
        mSwipeItemView = (SwipeItemView)mItemView.findViewById(mSwipeItemViewID);
        mSwipeItemView.scrollToWithAnimation(0, 0);
      }

      mLastShowingPos = -1;
    }
  }


上面的scrollToWithAnimation()方法就是上一篇博客里面我們實現(xiàn)了的移動item并使其帶有動畫效果的方法了。 

這樣,整個仿微信滑動刪除操作的總體實現(xiàn)方案就解釋完畢了,具體一些細節(jié)的話可以查看這個工程的源碼,源碼我已經上傳到了我的Github主頁上:https://github.com/YoungLeeForeverBoy/SlidingListViewPlus。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • android module解耦組件化總體概述(推薦)

    android module解耦組件化總體概述(推薦)

    這篇文章主要介紹了android module解耦組件化總體概述(推薦),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • Android上傳文件到服務端并顯示進度條

    Android上傳文件到服務端并顯示進度條

    這篇文章主要為大家詳細介紹了Android上傳文件到服務端,并顯示進度條,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 基于Android studio3.6的JNI教程之helloworld思路詳解

    基于Android studio3.6的JNI教程之helloworld思路詳解

    這篇文章主要介紹了基于Android studio3.6的JNI教程之helloworld,本文通過圖文實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • 詳解Android原生json和fastjson的簡單使用

    詳解Android原生json和fastjson的簡單使用

    本文主要介紹了Android原生json和fastjson的簡單使用,具有一定的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • Android多媒體之VideoView視頻播放器

    Android多媒體之VideoView視頻播放器

    這篇文章主要為大家詳細介紹了Android多媒體之VideoView視頻播放器的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • Win10下Android App安裝配置開發(fā)環(huán)境

    Win10下Android App安裝配置開發(fā)環(huán)境

    這篇文章主要為大家詳細介紹了Win10下Android App安裝配置開發(fā)環(huán)境,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • Android適配底部虛擬按鍵的方法詳解

    Android適配底部虛擬按鍵的方法詳解

    今天小編就為大家分享一篇Android適配底部虛擬按鍵的方法詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • Android自定義View實現(xiàn)自動吸附功能

    Android自定義View實現(xiàn)自動吸附功能

    這篇文章主要為大家詳細介紹了Android自定義View實現(xiàn)自動吸附功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-01-01
  • Android手機鬧鐘用法實例

    Android手機鬧鐘用法實例

    這篇文章主要介紹了Android手機鬧鐘用法,以實例形式較為詳細的分析了Android實現(xiàn)鬧鐘功能的頁面布局及具體功能相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-09-09
  • Android ViewPager自定義輪播圖并解決播放沖突

    Android ViewPager自定義輪播圖并解決播放沖突

    這篇文章主要為大家詳細介紹了Android ViewPager自定義輪播圖并解決播放沖突,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09

最新評論

达孜县| 石狮市| 英山县| 濮阳市| 吐鲁番市| 永靖县| 麻城市| 紫云| 安新县| 江西省| 安陆市| 陇川县| 磐石市| 南阳市| 盖州市| 务川| 毕节市| 前郭尔| 武胜县| 柘荣县| 涞水县| 民勤县| 新化县| 德惠市| 江川县| 得荣县| 永修县| 鄯善县| 天峻县| 十堰市| 大名县| 会理县| 安达市| 大同县| 中西区| 苗栗市| 新野县| 江城| 公安县| 南开区| 博白县|