您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關Android中怎么實現條目拖拽刪除功能,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
第一步效果圖
1.0自定義控件 SwipeLayout 繼承FrameLayout重寫里面三個構造方法,分別調用initView().
2.0在布局中使用自定義控件
3.0在initView()方法中,創建拖拽輔輔助工具 ViewDragHelper()
該方法需要傳入回調 MyCallBack()
4.0,創建MyCallBack()回調,繼承ViewDragHelper.Callback
在回調中 覆蓋tryCaptureView方法,返回true 允許child被拖拽,被 覆蓋clampViewPositionHorizontal 返回left系統提供拖拽位置
5.0 onInterceptTouchEvent 返回:讓ViewDragHelper判斷是否需要攔截事件
6.0 onTouchEvent 返回true 并且讓ViewDragHelper分析事件
具體代碼:
布局:
<cn.itheima.swipelayout.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="wrap_content"> <!--正文部分--> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#fff" android:orientation="horizontal"> <TextView android:id="@+id/item_tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="10dp" android:text="張三" android:textSize="20sp" /> </RelativeLayout> <!--按鈕部分--> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#888888" android:padding="10dp" android:text="呼叫" android:textSize="20sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#f00" android:padding="10dp" android:text="刪除" android:textSize="20sp" /> </LinearLayout> </cn.itheima.swipelayout.SwipeLayout>
SwipeLayout 代碼:
public class SwipeLayout extends FrameLayout { private ViewDragHelper mDragHelper; public SwipeLayout(Context context) { super(context); initView(); } public SwipeLayout(Context context, AttributeSet attrs) { super(context, attrs); initView(); } public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } private void initView() { mDragHelper = ViewDragHelper.create(this,new MyCallBack()); } // 讓ViewDragHelper就是拖拽輔助工具 返回true 則表示要攔截觸摸事件 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { //讓拖拽輔助工具判斷是否需要攔截 事件 return mDragHelper.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { //讓拖拽輔助工具分析事件 分析用戶手勢 mDragHelper.processTouchEvent(event); return true; } private class MyCallBack extends ViewDragHelper.Callback{ /** * 如果返回 true 則表示 child 允許被拖拽 */ @Override public boolean tryCaptureView(View child, int pointerId) { return true; } /** * 固定被拖拽控件的水平位置, * 參數里的 left 是系統推薦移動到的位置,可以進行修正, * 方法返回的值就是 child 將要移動到的位置 */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { return left; } } }
第二步:
1.0創建onFinishInflate方法獲取子控件,并且判斷健壯性
/* 控件初始化時執行,可以用于獲取子控件 */ @Override protected void onFinishInflate() { // 健壯性檢查 if (getChildCount()!=2){ throw new RuntimeException("SwipeLayout 必須存放兩個子控件"); } if (!(getChildAt(0) instanceof ViewGroup)||!(getChildAt(1) instanceof ViewGroup)){ throw new RuntimeException("SwipeLayout 的子控件必須是 ViewGroup"); } mContent = (ViewGroup) getChildAt(0); mDeletePanel = (ViewGroup) getChildAt(1); }
2.0創建onSizeChanged方法,在控件大小改變的時候調用,獲取控件的寬高,和刪除的面板的最大移動范圍
/** * 當控件大小改變的時候調用這個方法 */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); int mWith = w; int mHeigth = h; //界面創建過程中,不能使用 getWidth 方法 int mRang = mDeletePanel.getMeasuredWidth(); }
3.0在onLayout中指定側拉面板的位置
//指定側拉面板的位置 @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); mDeletePanel.layout(mWith,0,mWith+mRang,mHeigth); }
4.0在onViewPositionChanged方法中實現聯動效果
/** * 當被拖拽的控件已經移動過后,會調用這個方法,可以用于處理控件間的聯動效果 * @left 被拖拽控件的真實移動位置 * @dx 被拖拽控件的真實偏移大小 */ @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { if (changedView==mContent){ // 移動正文的同時也要移動側欄 mDeletePanel.offsetLeftAndRight(dx); }else{ mContent.offsetLeftAndRight(dx); } }
5.0在 clampViewPositionHorizontal方法中 固定被拖拽控件的水平位置,
/** * 固定被拖拽控件的水平位置, * 參數里的 left 是系統推薦移動到的位置,可以進行修正, * 方法返回的值就是 child 將要移動到的位置 */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { if (child==mContent){ if (left>0){ left=0; }else if (left<-mRang){ left=-mRang; } }else{ if (left>mWith){//mWith是屏幕的寬度 left=mWith; }else if (left<mWith-mRang){ left=mWith-mRang; } } return left; }
第三步:
效果圖
1.0onViewReleased中根據來開局里面,判斷是否打開還是關閉
2.0 在 moveContent中第一次滑動
3.0computeScroll中,繼續滑動,直到滑動到指定的位置
4.0注意在onViewPositionChanged中手動刷新界面,調用invalidate方法
如果不手動刷新界面,效果展示不出來
/** * 當用戶松手時執行 * @xvel 松手時在 X 方向的移動速度,如果為 正數 則說明是向右移動,如果是 負數 則說明是向左移動,如果為零,說明是靜止狀態 */ @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { if (xvel>0){ //向右移動 close(); }else if (xvel<0){ //向左移動 opend(); }else if (xvel>-mRang/2){// 靜止狀態 close();// 展開不到一半,關閉面板 }else{ opend(); } } } /** * 打開面板 */ private void opend() { int left=-mRang; moveContent(left); } /** * 關閉面板 */ private void close() { int left=0; moveContent(left); } private void moveContent(int left) { // 開啟平滑滾動,如果返回 true 則說明要繼續刷新界面,保持滾動 if(mDragHelper.smoothSlideViewTo(mContent,left,0)){ invalidate(); } } @Override public void computeScroll() { // 繼續平滑滾動,如果返回 true 則說明要繼續刷新界面,保持滾動 if (mDragHelper.continueSettling(true)){ invalidate(); } }
第四步:
1.0現給ListView賦值 在這就省略
2.0在SwipeLayout中使用枚舉記錄面板的狀態
private enum Status{ CLOSED,OPENED,DRAGING; } private Status status = Status.CLOSED; public Status getStatus() { return status; }
3.0// 記錄上一個打開的面板。注意:一定要是 靜態變量
private static SwipeLayout preSwipeLayout;
4.0在onViewPositionChanged中創建一個方法操作關閉面板
// 關閉上一個打開的面板 closePre();
5.0closePre()在這個方法中,判斷當前面板的狀態,并且根據狀態,關閉上一個打開的面板
// 判斷當前面板是否正在打開,如果正在打開則將上一個打開的面板關閉 private void closePre() { //記錄舊狀態 Status preStatus=status; if (mContent.getLeft()==-mRang){ //記錄當前面板已經打開 status=status.OPENED; }else if (mContent.getLeft()==0){ //當前面板已經關閉 status=status.CLOSED; }else { status=status.DRAGING; } // 如果當前面板舊狀態為關閉,并且新狀態為拖拽,那么此時可以關閉之前打開的面板 if (preStatus==status.CLOSED&&status==status.DRAGING){ if (preSwipeLayout!=null&&preSwipeLayout!=this){ // 關閉上一個面板 preSwipeLayout.close(); } // 將當前面板標記為 打開的面板 preSwipeLayout=this; } }
以上就是Android中怎么實現條目拖拽刪除功能,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。