溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android中怎么利用SlideListView自定義View

發布時間:2021-06-29 14:28:35 來源:億速云 閱讀:222 作者:Leah 欄目:移動開發

Android中怎么利用SlideListView自定義View,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

主要用到了 Scroller 這個滑動類,剛開始攔截觸摸事件在 action ==MotionEvent.ACTION_DOWN的時候,根據出點獲取我們點擊的itemView 然后根據滑動模式(左滑動 or 右滑動)來自動獲取左側或者右側的寬度;

在 action == MotionEvent.ACTION_MOVE 中根據移動判斷是否可以側滑,以及側滑的方向,并使用 itemView.scrollTo(deltaX, 0); 來移動itemView ;

***在 ction == MotionEvent.ACTION_UP 中判斷模式和移動的距離完成側滑或者還原到初始狀態。
實現

***步 初始化Scroller

scroller = new Scroller(context);  mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();

第二步 action ==MotionEvent.ACTION_DOWN

case MotionEvent.ACTION_DOWN:                  if (this.mode == MOD_FORBID) {                      return super.onTouchEvent(ev);                  }                  // 如果處于側滑完成狀態,側滑回去,并直接返回                  if (isSlided) {                      scrollBack();                      return false;                  }                  // 假如scroller滾動還沒有結束,我們直接返回                  if (!scroller.isFinished()) {                      return false;                  }                     downX = (int) ev.getX();                  downY = (int) ev.getY();                     slidePosition = pointToPosition(downX, downY);                  // 無效的position, 不做任何處理                  if (slidePosition == AdapterView.INVALID_POSITION) {                      return super.onTouchEvent(ev);                  }                     // 獲取我們點擊的item view                  itemView = getChildAt(slidePosition - getFirstVisiblePosition());                  /*此處根據設置的滑動模式,自動獲取左側或右側菜單的長度*/                  if (this.mode == MOD_BOTH) {                      this.leftLength = -itemView.getPaddingLeft();                      this.rightLength = -itemView.getPaddingRight();                  } else if (this.mode == MOD_LEFT) {                      this.leftLength = -itemView.getPaddingLeft();                  } else if (this.mode == MOD_RIGHT) {                      this.rightLength = -itemView.getPaddingRight();                  }                  break;

第三步 action == MotionEvent.ACTION_MOVE

case MotionEvent.ACTION_MOVE:                  if (!canMove                          && slidePosition != AdapterView.INVALID_POSITION                          && (Math.abs(ev.getX() - downX) > mTouchSlop && Math.abs(ev                          .getY() - downY) < mTouchSlop)) {                      if (mSwipeLayout != null)                          mSwipeLayout.setEnabled(false);                      int offsetX = downX - lastX;                      if (offsetX > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)) {                          /*從右向左滑*/                          canMove = true;                      } else if (offsetX < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)) {                          /*從左向右滑*/                          canMove = true;                      } else {                          canMove = false;                      }                      /*此段代碼是為了避免我們在側向滑動時同時觸發ListView的OnItemClickListener時間*/                      MotionEvent cancelEvent = MotionEvent.obtain(ev);                      cancelEvent                              .setAction(MotionEvent.ACTION_CANCEL                                      | (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));                      onTouchEvent(cancelEvent);                  }                  if (canMove) {                      /*設置此屬性,可以在側向滑動時,保持ListView不會上下滾動*/                      requestDisallowInterceptTouchEvent(true);                      // 手指拖動itemView滾動, deltaX大于0向左滾動,小于0向右滾                      int deltaX = downX - lastX;                      if (deltaX < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)) {                          /*向左滑*/                          itemView.scrollTo(deltaX, 0);                      } else if (deltaX > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)) {                          /*向右滑*/                          itemView.scrollTo(deltaX, 0);                      } else {                          itemView.scrollTo(0, 0);                      }                      return true;                  }                  break;

第四步 action == MotionEvent.ACTION_UP

case MotionEvent.ACTION_UP:                  if (mSwipeLayout != null)                      mSwipeLayout.setEnabled(true);                  //requestDisallowInterceptTouchEvent(false);                  if (canMove){                      canMove = false;                      scrollByDistanceX();                  }                  break;

完整代碼

以下是完整代碼

package com.jwenfeng.fastdev.view;     import android.content.Context;  import android.support.v4.widget.SwipeRefreshLayout;  import android.util.AttributeSet;  import android.view.MotionEvent;  import android.view.View;  import android.view.ViewConfiguration;  import android.widget.AdapterView;  import android.widget.ListView;  import android.widget.Scroller;     /**   * 當前類注釋: ListView 側滑出菜單   * 項目名:fastdev   * 包名:com.jwenfeng.fastdev.view   * 作者:jinwenfeng on 16/4/11 10:55   * 郵箱:823546371@qq.com   * QQ: 823546371   * 公司:南京穆尊信息科技有限公司   * &copy; 2016 jinwenfeng   * &copy;版權所有,未經允許不得傳播   */  public class SlideListView extends ListView {         /**下拉刷新view*/      private SwipeRefreshLayout mSwipeLayout;      /**       * 禁止側滑模式       */      public static int MOD_FORBID = 0;      /**       * 從左向右滑出菜單模式       */      public static int MOD_LEFT = 1;      /**       * 從右向左滑出菜單模式       */      public static int MOD_RIGHT = 2;      /**       * 左右均可以滑出菜單模式       */      public static int MOD_BOTH = 3;      /**       * 當前的模式       */      private int mode = MOD_FORBID;      /**       * 左側菜單的長度       */      private int leftLength = 0;      /**       * 右側菜單的長度       */      private int rightLength = 0;         /**       * 當前滑動的ListView position       */      private int slidePosition;      /**       * 手指按下X的坐標       */      private int downY;      /**       * 手指按下Y的坐標       */      private int downX;      /**       * ListView的item       */      private View itemView;      /**       * 滑動類       */      private Scroller scroller;      /**       * 認為是用戶滑動的最小距離       */      private int mTouchSlop;         /**       * 判斷是否可以側向滑動       */      private boolean canMove = false;      /**       * 標示是否完成側滑       */      private boolean isSlided = false;         public SlideListView(Context context) {          this(context, null);      }         public SlideListView(Context context, AttributeSet attrs) {          this(context, attrs,0);      }         public SlideListView(Context context, AttributeSet attrs, int defStyleAttr) {          super(context, attrs, defStyleAttr);          scroller = new Scroller(context);          mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();      }         /**       * 初始化菜單的滑出模式       *       * @param mode       */      public void initSlideMode(int mode) {          this.mode = mode;      }         /**       * 處理我們拖動ListView item的邏輯       */      @Override      public boolean onTouchEvent(MotionEvent ev) {          final int action = ev.getAction();          int lastX = (int) ev.getX();             switch (action) {              case MotionEvent.ACTION_DOWN:                  if (this.mode == MOD_FORBID) {                      return super.onTouchEvent(ev);                  }                  // 如果處于側滑完成狀態,側滑回去,并直接返回                  if (isSlided) {                      scrollBack();                      return false;                  }                  // 假如scroller滾動還沒有結束,我們直接返回                  if (!scroller.isFinished()) {                      return false;                  }                     downX = (int) ev.getX();                  downY = (int) ev.getY();                     slidePosition = pointToPosition(downX, downY);                  // 無效的position, 不做任何處理                  if (slidePosition == AdapterView.INVALID_POSITION) {                      return super.onTouchEvent(ev);                  }                     // 獲取我們點擊的item view                  itemView = getChildAt(slidePosition - getFirstVisiblePosition());                  /*此處根據設置的滑動模式,自動獲取左側或右側菜單的長度*/                  if (this.mode == MOD_BOTH) {                      this.leftLength = -itemView.getPaddingLeft();                      this.rightLength = -itemView.getPaddingRight();                  } else if (this.mode == MOD_LEFT) {                      this.leftLength = -itemView.getPaddingLeft();                  } else if (this.mode == MOD_RIGHT) {                      this.rightLength = -itemView.getPaddingRight();                  }                  break;              case MotionEvent.ACTION_MOVE:                  if (!canMove                          && slidePosition != AdapterView.INVALID_POSITION                          && (Math.abs(ev.getX() - downX) > mTouchSlop && Math.abs(ev                          .getY() - downY) < mTouchSlop)) {                      if (mSwipeLayout != null)                          mSwipeLayout.setEnabled(false);                      int offsetX = downX - lastX;                      if (offsetX > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)) {                          /*從右向左滑*/                          canMove = true;                      } else if (offsetX < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)) {                          /*從左向右滑*/                          canMove = true;                      } else {                          canMove = false;                      }                      /*此段代碼是為了避免我們在側向滑動時同時觸發ListView的OnItemClickListener時間*/                      MotionEvent cancelEvent = MotionEvent.obtain(ev);                      cancelEvent                              .setAction(MotionEvent.ACTION_CANCEL                                      | (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));                      onTouchEvent(cancelEvent);                  }                  if (canMove) {                      /*設置此屬性,可以在側向滑動時,保持ListView不會上下滾動*/                      requestDisallowInterceptTouchEvent(true);                      // 手指拖動itemView滾動, deltaX大于0向左滾動,小于0向右滾                      int deltaX = downX - lastX;                      if (deltaX < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)) {                          /*向左滑*/                          itemView.scrollTo(deltaX, 0);                      } else if (deltaX > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)) {                          /*向右滑*/                          itemView.scrollTo(deltaX, 0);                      } else {                          itemView.scrollTo(0, 0);                      }                      return true;                  }                  break;                 case MotionEvent.ACTION_UP:                  if (mSwipeLayout != null)                      mSwipeLayout.setEnabled(true);                  //requestDisallowInterceptTouchEvent(false);                  if (canMove){                      canMove = false;                      scrollByDistanceX();                  }                  break;          }             return super.onTouchEvent(ev);      }         private void scrollByDistanceX() {          if(this.mode == MOD_FORBID){              return;          }          if(itemView.getScrollX() > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)){              /*從右向左滑*/              if (itemView.getScrollX() >= rightLength / 2) {                  scrollLeft();              }  else {                  // 滾回到原始位置                  scrollBack();              }          }else if(itemView.getScrollX() < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)){              /*從左向右滑*/              if (itemView.getScrollX() <= -leftLength / 2) {                  scrollRight();              } else {                  // 滾回到原始位置                  scrollBack();              }          }else{              // 滾回到原始位置              scrollBack();          }      }         /**       * 往右滑動,getScrollX()返回的是左邊緣的距離,就是以View左邊緣為原點到開始滑動的距離,所以向右邊滑動為負值       */      private void scrollRight() {          isSlided = true;          final int delta = (leftLength + itemView.getScrollX());          // 調用startScroll方法來設置一些滾動的參數,我們在computeScroll()方法中調用scrollTo來滾動item          scroller.startScroll(itemView.getScrollX(), 0, -delta, 0,                  Math.abs(delta));          postInvalidate(); // 刷新itemView      }         /**       * 向左滑動,根據上面我們知道向左滑動為正值       */      private void scrollLeft() {          isSlided = true;          final int delta = (rightLength - itemView.getScrollX());          // 調用startScroll方法來設置一些滾動的參數,我們在computeScroll()方法中調用scrollTo來滾動item          scroller.startScroll(itemView.getScrollX(), 0, delta, 0,                  Math.abs(delta));          postInvalidate(); // 刷新itemView         }         private void scrollBack() {          isSlided = false;          scroller.startScroll(itemView.getScrollX(), 0, -itemView.getScrollX(),                  0, Math.abs(itemView.getScrollX()));          postInvalidate(); // 刷新itemView      }         @Override      public void computeScroll() {          // 調用startScroll的時候scroller.computeScrollOffset()返回true,          if (scroller.computeScrollOffset()) {              // 讓ListView item根據當前的滾動偏移量進行滾動              itemView.scrollTo(scroller.getCurrX(), scroller.getCurrY());              postInvalidate();          }      }         /**       * 提供給外部調用,用以將側滑出來的滑回去       */      public void slideBack() {          this.scrollBack();      }         public void setSwipeLayout(SwipeRefreshLayout mSwipeLayout) {          this.mSwipeLayout = mSwipeLayout;      }  }

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女