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

首頁 > 學院 > 開發設計 > 正文

ListView側滑刪除的實現,SlideDeleteListView,針對ScrollView嵌套ListView視圖和手勢沖突優化

2019-11-06 09:45:37
字體:
來源:轉載
供稿:網友

轉載:http://blog.csdn.net/ausboyue/article/details/52565237的博客

關于ListView側滑刪除這是個老話題,大多數APP都具有這樣類似的功能,對于一位Android初涉者來說,實現這樣的功能確實有一點難度,網上的實現方法也層出不窮,我仔細在網上翻了一下,居然看到了還有很多實現側滑的第三方依賴包,覺得有些無語,嘗試使用一番,大多數實現還是很好的,比我今天要說的好的多,當然也有劣質的包,這里也就不多說了。既然是老話題,那么沒有一點實現上的優勢,我也說不下去,這個優勢大概就是只要自定義一個ListView便可以實現側滑刪除功能,尤其是對ScrollView嵌套ListView視圖和手勢沖突的優化。嚴格意義上這個實現方式也是我以前在網上看到的,后來基于這個實現思想修改優化的。好了,開教程:

1.先假設一個ListView的Item子布局message_item.xml是這樣的:

[html] view plain copy<?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="match_parent"      android:layout_height="62dp"      android:background="@drawable/common_list_item_bg"      android:gravity="center_vertical"      android:minHeight="?android:attr/listPReferredItemHeight"      android:orientation="horizontal">        <RelativeLayout          android:layout_width="match_parent"          android:layout_height="match_parent">            <ImageView              android:id="@+id/iv_icon_read_status"              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:layout_centerVertical="true"              android:layout_marginLeft="15dp"              android:src="@drawable/ic_msg_unread" />            <TextView              android:id="@+id/tv_msg_content"              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:layout_centerVertical="true"              android:layout_marginLeft="15dp"              android:layout_toRightOf="@id/iv_icon_read_status"              android:text="訂單預定成功;訂單號6607967"              android:textColor="@color/common_text"              android:textSize="14sp" />              <TextView              android:id="@+id/tv_msg_time"              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:layout_alignParentRight="true"              android:layout_centerVertical="true"              android:layout_marginRight="15dp"              android:text="前天 13:21"              android:textColor="@color/text_smoke"              android:textSize="12sp" />      </RelativeLayout>        <TextView          android:id="@+id/tv_btn_delete"          android:layout_width="70dp"          android:layout_height="match_parent"          android:background="@color/red"          android:clickable="true"          android:gravity="center"          android:text="刪除"          android:textColor="@color/white"          android:textSize="17sp" />  </LinearLayout>  前面的RelativeLayout里的內容就是大家常見的ListView的Item視圖,后面的TextView就是我們主角刪除按鈕,這里把它也作為Item的子布局內容了。從布局里可以看出,刪除按鈕TextView已經被RelativeLayout擠到最右邊,而不在屏幕顯示區域內。此時該Item的長度實際長度是屏幕的長度+刪除的按鈕的長度(這里是70dp)。

2.下面我們自定義ListView----->SlideDeleteListView  這里注意一點,就是盡量不要在任何自定義View中傳入某布局,那么以后修改或用于別的項目,其要求發生了一些變化,還要針對被改變的布局修改邏輯代碼,這是我個人的一種開發思想,大家聽聽就好了。

[java] view plain copy/**  * 構造方法,實例化入口,初始化相關數據或實例  *  * @param context  * @param attrs  * @param defStyleAttr  */  public SlideDeleteListView(Context context, AttributeSet attrs, int defStyleAttr) {      super(context, attrs, defStyleAttr);      // 窗口管理器      WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);      // 新建顯示度量尺      DisplayMetrics metrics = new DisplayMetrics();      // 對度量尺進行包裝,附參      wm.getDefaultDisplay().getMetrics(metrics);      // 初始化屏幕寬度參數      mSreeenWidth = metrics.widthPixels;  }  

SlideDeleteListView構造方法中獲取屏幕寬度mSreeenWidth

[java] view plain copy/**  * 手勢操作  *   * @param ev  * @return  */  @SuppressLint("ClickableViewaccessibility")  @Override  public boolean onTouchEvent(MotionEvent ev) {      switch (ev.getAction()) {      case MotionEvent.ACTION_DOWN:// 按壓          onActionDowm(ev);          break;      case MotionEvent.ACTION_MOVE:// 移動          return onActionMove(ev);      case MotionEvent.ACTION_UP:// 釋放          onActionUp(ev);          break;      }      return super.onTouchEvent(ev);  }  重寫SlideDeleteListView手勢事件

[java] view plain copy/**      * 手指按下邏輯      */      private void onActionDowm(MotionEvent e) {          if (isBtnDelShow) {              resetItemView();          }          mDownX = (int) e.getX();          mDownY = (int) e.getY();          // 獲得被按下位置的item          Integer currentPosition = pointToPosition(mDownX, mDownY);          if (-1 == currentPosition) {              return;          }          itemViewGroup = (ViewGroup) getChildAt(currentPosition - getFirstVisiblePosition());          // 獲得刪除按鈕的寬度,刪除按鈕屬于第二個子View(上述布局中能看得出來),position為1          mBtnDelWidth = itemViewGroup.getChildAt(1).getLayoutParams().width;          /* 將第一個子View也就是我們常見的Item顯示的View的寬固定為屏幕同寬度 */          params = (LinearLayout.LayoutParams) itemViewGroup.getChildAt(0).getLayoutParams();          params.width = mSreeenWidth;          itemViewGroup.getChildAt(0).setLayoutParams(params);      }  

手指按下的時候,把剛才那個item常見顯示的視圖RelativeLayout寬度成屏幕的寬度,以及獲得刪除按鈕TextView 的寬度,isBtnDelShow為flag,用于標記刪除是否處于顯示狀態,若顯示,點擊時重置下Item顯示狀態(即不顯示刪除按鈕的視圖狀態),Integer currentPosition = pointToPosition(mDownX, mDownY),currentPosition 為-1時表示手指點擊點是在item之間的分割線上,不作邏輯處理。itemViewGroup即Item的布局,itemViewGroup.getChildAt(0)為Item子View,即上述的RelativeLayout。

[java] view plain copy/**  * 手指移動邏輯  */  private boolean onActionMove(MotionEvent e) {      int nowX = (int) e.getX();      int nowY = (int) e.getY();      // 判斷是否為偏向左右的滑動      if (Math.abs(nowX - mDownX) > Math.abs(nowY - mDownY)) {          // 左右滑動請求消費該事件,防止上下滑動以及被ScrollView嵌套的手勢沖突          requestDisallowInterceptTouchEvent(true);          // 判斷是否為向左滑動          if (nowX < mDownX) {              int srollX = mDownX - nowX;              // 判斷左滑距離是否超過刪除按鈕寬              if (srollX >= mBtnDelWidth) {                  srollX = mBtnDelWidth;              }              params.leftMargin = -srollX;              itemViewGroup.getChildAt(0).setLayoutParams(params);          }          // 消費掉該移動事件          return true;      }      return super.onTouchEvent(e);  }  這里的思路就是判定左滑時,并根據左滑的絕對距離(即手指向左邊滑動的實際水平距離),實時設定RelativeLayout視圖的MarginLeft為相應距離的負值以達到感覺item布局像是被手指劃走的效果,刪除按鈕也隨即從左邊逐漸顯示出來。注意下requestDisallowInterceptTouchEvent(true)這行代碼的注釋,手指點擊的位置是在ListView上,且是左右滑,為了避免手勢沖突,不讓父View即ScrollView攔截該手勢事件。

手指釋放時判斷向左滑動的距離,做顯示按鈕或重置最初的Item顯示狀態邏輯。[java] view plain copy/**  * 手指釋放邏輯  */  private void onActionUp(MotionEvent e) {      //判斷手指釋放后,刪除按鈕是否已顯示超過其寬度的一半      if (-params.leftMargin >= mBtnDelWidth / 2) {          params.leftMargin = -mBtnDelWidth;          isBtnDelShow = true;      } else {          //恢復滑動前的視圖狀態          resetItemView();      }      itemViewGroup.getChildAt(0).setLayoutParams(params);  }  

[java] view plain copy    /**      * 重寫該方法是用來應對ScrollView嵌套顯示不全的問題      *      * @param widthMeasureSpec      * @param heightMeasureSpec      */      @Override      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {          // 獲得ScrollView或其子類對象,這里視情況而定,可能不需要只需要一個getParent()或多次,視自己的布局層次而定          Object object = getParent().getParent();          if (object instanceof ScrollView) {// 是ScrollView或其子類              /*解決與ScrollView的布局沖突,讓ListView完全顯示*/              int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);              super.onMeasure(widthMeasureSpec, expandSpec);          } else {              // 沒有ScrollView嵌套,正常super的方法              super.onMeasure(widthMeasureSpec, heightMeasureSpec);          }      }  

[java] view plain copy/**  * 重置itemView,恢復原顯示狀態  */  public void resetItemView() {      params.leftMargin = 0;      itemViewGroup.getChildAt(0).setLayoutParams(params);      isBtnDelShow = false;  }  看注釋。

3.在適配器Adapter中獲取該ListView對象,當刪除按鈕顯示時,點擊刪除,刪除集合里對應的數據,ListView對象再調用上述的resetItemView()方法,再調用adapter的notifyDataSetChanged()方法更新界面。

[java] view plain copyholder.tv_btn_delete.setOnClickListener(new View.OnClickListener() {              @Override              public void onClick(View view) {                  items.remove(items.get(position));                  lv_messages.resetItemView();                  notifyDataSetChanged();              }          });  

效果圖:          

Demo源碼下載


上一篇:國際象棋規則

下一篇:TextView添加邊框

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 天等县| 丰原市| 上饶市| 石泉县| 顺义区| 平塘县| 太和县| 淮阳县| 北海市| 磐安县| 什邡市| 夏津县| 渭源县| 武山县| 达拉特旗| 和龙市| 深水埗区| 韶山市| 景泰县| 汤阴县| 哈巴河县| 小金县| 繁昌县| 凤庆县| 黔西县| 共和县| 潍坊市| 华亭县| 思茅市| 游戏| 潜江市| 扬中市| 鹿泉市| 淮滨县| 社会| 巫溪县| 射洪县| 招远市| 五大连池市| 屏南县| 中卫市|