溫馨提示×

溫馨提示×

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

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

怎么在Android應(yīng)用中實(shí)現(xiàn)一個抽屜效果

發(fā)布時間:2020-11-30 16:56:59 來源:億速云 閱讀:177 作者:Leah 欄目:移動開發(fā)

怎么在Android應(yīng)用中實(shí)現(xiàn)一個抽屜效果?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

實(shí)現(xiàn)原理

其實(shí)單就一個SwipeLayout的實(shí)現(xiàn)原理來講的話,還是很簡單的,實(shí)際上單個SwipeLayout隱藏抽屜狀態(tài)時,應(yīng)該是這樣的:

怎么在Android應(yīng)用中實(shí)現(xiàn)一個抽屜效果

也就是說,最初的隱藏狀態(tài),實(shí)際上是將hide view區(qū)域layout到conten view的右邊,達(dá)到隱藏效果,而后顯示則是根據(jù)拖拽的x值變化來動態(tài)的layout 2個view,從而達(dá)到一個滑動抽屜效果。
當(dāng)然,直接重寫view的onTouchEvent來動態(tài)的layout 2個view是可以實(shí)現(xiàn)我們需要的效果的,但是有更好的方法來實(shí)現(xiàn),就是同過ViewDragHelper。
ViewDragHelper是google官方提供的一個專門用于手勢分析處理的類,關(guān)于ViewDragHelper的基本使用,網(wǎng)上有一大堆的資源。具體的ViewDragHelper介紹以及基本使用方法,本文就不重復(fù)造輪子了,此處推薦鴻洋大神的一篇微博:Android ViewDragHelper完全解析 自定義ViewGroup神器。

具體實(shí)現(xiàn)

下面我們開始具體的實(shí)現(xiàn)。
布局比較簡單,這里就不貼代碼了,最后會貼上本demo的完整代碼地址。

首先我們實(shí)現(xiàn)一個繼承FrameLayout的自定義SwipeLauout,重寫onFinishInflate方法:
這里我們只允許SwipeLayout設(shè)置2個子View,ContentLayout是繼承LinearLayout的自定義layout,后面會講到這個,此處先略過;

 @Override
 protected void onFinishInflate() {
  super.onFinishInflate();
  if (getChildCount() != 2) {
   throw new IllegalStateException("Must 2 views in SwipeLayout");
  }
  contentView = getChildAt(0);
  hideView = getChildAt(1);
  if (contentView instanceof ContentLayout)
   ((ContentLayout) contentView).setSwipeLayout(this);
  else {
   throw new IllegalStateException("content view must be an instanceof FrontLayout");
  }
 }

接著重寫onSizeChanged,onLayout,onInterceptTouchEvent方法:

 @Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
  hideViewHeight = hideView.getMeasuredHeight();
  hideViewWidth = hideView.getMeasuredWidth();
  contentWidth = contentView.getMeasuredWidth();
 }

 @Override
 protected void onLayout(boolean changed, int left, int top, int right,
       int bottom) {
  // super.onLayout(changed, left, top, right, bottom);
  contentView.layout(0, 0, contentWidth, hideViewHeight);
  hideView.layout(contentView.getRight(), 0, contentView.getRight()
    + hideViewWidth, hideViewHeight);
 }

 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
  boolean result = viewDragHelper.shouldInterceptTouchEvent(ev);
  //  Log.e("SwipeLayout", "-----onInterceptTouchEvent-----");
  return result;
 }

然后是比較關(guān)鍵的,重寫onTouchEvent方法以及ViewDragHelper.Callback回調(diào),我們定了一個enum來判斷SwipeLayout的三種狀態(tài)。在onViewPositionChanged中,有2種方法實(shí)現(xiàn)content view和hide view的伴隨移動,一種是直接offset view的橫向變化量,還有一種就是直接通過layout的方式,兩種方式都可以。

 public enum SwipeState {
  Open, Swiping, Close;
 }
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  //  Log.e("SwipeLayout", "-----onTouchEvent-----");
  switch (event.getAction()) {
   case MotionEvent.ACTION_DOWN:
    downX = event.getX();
    downY = event.getY();
    break;
   case MotionEvent.ACTION_MOVE:
    // 1.獲取x和y方向移動的距離
    float moveX = event.getX();
    float moveY = event.getY();
    float delatX = moveX - downX;// x方向移動的距離
    float delatY = moveY - downY;// y方向移動的距離

    if (Math.abs(delatX) > Math.abs(delatY)) {
     // 表示移動是偏向于水平方向,那么應(yīng)該SwipeLayout應(yīng)該處理,請求listview不要攔截
     this.requestDisallowInterceptTouchEvent(true);
    }

    // 更新downX,downY
    downX = moveX;
    downY = moveY;
    break;
   case MotionEvent.ACTION_UP:

    break;
  }
  viewDragHelper.processTouchEvent(event);
  return true;
 }

 private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
  @Override
  public boolean tryCaptureView(View child, int pointerId) {
   return child == contentView || child == hideView;
  }

  @Override
  public int getViewHorizontalDragRange(View child) {
   return hideViewWidth;
  }

  @Override
  public int clampViewPositionHorizontal(View child, int left, int dx) {
   if (child == contentView) {
    if (left > 0)
     left = 0;
    if (left < -hideViewWidth)
     left = -hideViewWidth;
   } else if (child == hideView) {
    if (left > contentWidth)
     left = contentWidth;
    if (left < (contentWidth - hideViewWidth))
     left = contentWidth - hideViewWidth;
   }
   return left;
  }

  @Override
  public void onViewPositionChanged(View changedView, int left, int top,
           int dx, int dy) {
   super.onViewPositionChanged(changedView, left, top, dx, dy);
   if (changedView == contentView) {
    // 如果手指滑動deleteView,那么也要講橫向變化量dx設(shè)置給contentView
    hideView.offsetLeftAndRight(dx);
   } else if (changedView == hideView) {
    // 如果手指滑動contentView,那么也要講橫向變化量dx設(shè)置給deleteView
    contentView.offsetLeftAndRight(dx);
   }

   //   if (changedView == contentView) {
   //    // 手動移動deleteView
   //    hideView.layout(hideView.getLeft() + dx,
   //      hideView.getTop() + dy, hideView.getRight() + dx,
   //      hideView.getBottom() + dy);
   //   } else if (hideView == changedView) {
   //    // 手動移動contentView
   //    contentView.layout(contentView.getLeft() + dx,
   //      contentView.getTop() + dy, contentView.getRight() + dx,
   //      contentView.getBottom() + dy);
   //   }
   //實(shí)時更新當(dāng)前狀態(tài)
   updateSwipeStates();
   invalidate();
  }

  @Override
  public void onViewReleased(View releasedChild, float xvel, float yvel) {
   super.onViewReleased(releasedChild, xvel, yvel);
   //根據(jù)用戶滑動速度處理開關(guān)
   //xvel: x方向滑動速度
   //yvel: y方向滑動速度
   //   Log.e("tag", "currentState = " + currentState);
   //   Log.e("tag", "xvel = " + xvel);
   if (xvel < -200 && currentState != SwipeState.Open) {
    open();
    return;
   } else if (xvel > 200 && currentState != SwipeState.Close) {
    close();
    return;
   }

   if (contentView.getLeft() < -hideViewWidth / 2) {
    // 打開
    open();
   } else {
    // 關(guān)閉
    close();
   }
  }
 };

open(),close()實(shí)現(xiàn)

 public void open() {
  open(true);
 }

 public void close() {
  close(true);
 }

 /**
  * 打開的方法
  *
  * @param isSmooth 是否通過緩沖動畫的形式設(shè)定view的位置
  */
 public void open(boolean isSmooth) {
  if (isSmooth) {
   viewDragHelper.smoothSlideViewTo(contentView, -hideViewWidth,
     contentView.getTop());
   ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
  } else {
   contentView.offsetLeftAndRight(-hideViewWidth);//直接偏移View的位置
   hideView.offsetLeftAndRight(-hideViewWidth);//直接偏移View的位置
   //   contentView.layout(-hideViewWidth, 0, contentWidth - hideViewWidth, hideViewHeight);//直接通過坐標(biāo)擺放
   //   hideView.layout(contentView.getRight(), 0, hideViewWidth, hideViewHeight);//直接通過坐標(biāo)擺放
   invalidate();
  }
 }

 /**
  * 關(guān)閉的方法
  *
  * @param isSmooth true:通過緩沖動畫的形式設(shè)定view的位置
  *     false:直接設(shè)定view的位置
  */
 public void close(boolean isSmooth) {
  if (isSmooth) {
   viewDragHelper.smoothSlideViewTo(contentView, 0, contentView.getTop());
   ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
  } else {
   contentView.offsetLeftAndRight(hideViewWidth);
   hideView.offsetLeftAndRight(hideViewWidth);
   invalidate();
   //contentView.layout(0, 0, contentWidth, hideViewHeight);//直接通過坐標(biāo)擺放
   //hideView.layout(contentView.getRight(), 0, hideViewWidth, hideViewHeight);//直接通過坐標(biāo)擺放
  }
 }

此上基本實(shí)現(xiàn)了單個SwipeLayout的抽屜滑動效果,但是將此SwipeLayout作為一個item布局設(shè)置給一個listView的時候,還需要做許多的判斷。

由于listView的重用機(jī)制,我們這里并未針對listview做任何處理,所以一旦有一個item的SwipeLayout的狀態(tài)是打開狀態(tài),不可避免的其它也必然有幾個是打開狀態(tài),所以我們這里需要根據(jù)檢測listView的滑動,當(dāng)listView滑動時,關(guān)閉SwipeLayout。既然需要在外部控制SwipeLayout的開關(guān),我們先定義一個SwipeLayoutManager用于管理SwipeLayout的控制。

public class SwipeLayoutManager {
 //記錄打開的SwipeLayout集合
 private HashSet<SwipeLayout> mUnClosedSwipeLayouts = new HashSet<SwipeLayout>();

 private SwipeLayoutManager() {
 }

 private static SwipeLayoutManager mInstance = new SwipeLayoutManager();

 public static SwipeLayoutManager getInstance() {
  return mInstance;
 }

 /**
  * 將一個沒有關(guān)閉的SwipeLayout加入集合
  * @param layout
  */
 public void add(SwipeLayout layout) {
  mUnClosedSwipeLayouts.add(layout);
 }

 /**
  * 將一個沒有關(guān)閉的SwipeLayout移出集合
  * @param layout
  */
 public void remove(SwipeLayout layout){
  mUnClosedSwipeLayouts.remove(layout);
 }

 /**
  * 關(guān)閉已經(jīng)打開的SwipeLayout
  */
 public void closeUnCloseSwipeLayout() {
  if(mUnClosedSwipeLayouts.size() == 0){
   return;
  }

  for(SwipeLayout l : mUnClosedSwipeLayouts){
   l.close(true);
  }
  mUnClosedSwipeLayouts.clear();
 }

 /**
  * 關(guān)閉已經(jīng)打開的SwipeLayout
  */
 public void closeUnCloseSwipeLayout(boolean isSmooth) {
  if(mUnClosedSwipeLayouts.size() == 0){
   return;
  }

  for(SwipeLayout l : mUnClosedSwipeLayouts){
   l.close(isSmooth);
  }
  mUnClosedSwipeLayouts.clear();
 }
}

這樣就可以監(jiān)聽listView的滑動,然后在listView滑動的時候,關(guān)閉所有的抽屜View。

 listView.setOnScrollListener(new OnScrollListener() {
   @Override
   public void onScrollStateChanged(AbsListView view, int scrollState) {
    swipeLayoutManager.closeUnCloseSwipeLayout();
   }

   @Override
   public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
   }
  });

考慮到大多數(shù)時候,在我們打開抽屜View和關(guān)閉抽屜View的時候,外部需要知道SwipeLayout的狀態(tài)值,所以我們需要在SwipeLayout中增加幾個接口,告訴外部當(dāng)前SwipeLayout的狀態(tài)值:

SwipeLayout.java

----------------
 private void updateSwipeStates() {
  SwipeState lastSwipeState = currentState;
  SwipeState swipeState = getCurrentState();

  if (listener == null) {
   try {
    throw new Exception("please setOnSwipeStateChangeListener first!");
   } catch (Exception e) {
    e.printStackTrace();
   }
   return;
  }

  if (swipeState != currentState) {
   currentState = swipeState;
   if (currentState == SwipeState.Open) {
    listener.onOpen(this);
    // 當(dāng)前的Swipelayout已經(jīng)打開,需要讓Manager記錄
    swipeLayoutManager.add(this);
   } else if (currentState == SwipeState.Close) {
    listener.onClose(this);
    // 說明當(dāng)前的SwipeLayout已經(jīng)關(guān)閉,需要讓Manager移除
    swipeLayoutManager.remove(this);
   } else if (currentState == SwipeState.Swiping) {
    if (lastSwipeState == SwipeState.Open) {
     listener.onStartClose(this);
    } else if (lastSwipeState == SwipeState.Close) {
     listener.onStartOpen(this);
     //hideView準(zhǔn)備顯示之前,先將之前打開的的SwipeLayout全部關(guān)閉
     swipeLayoutManager.closeUnCloseSwipeLayout();
     swipeLayoutManager.add(this);
    }
   }
  } else {
   currentState = swipeState;
  }
 }

 /**
  * 獲取當(dāng)前控件狀態(tài)
  *
  * @return
  */
 public SwipeState getCurrentState() {
  int left = contentView.getLeft();
  //  Log.e("tag", "contentView.getLeft() = " + left);
  //  Log.e("tag", "hideViewWidth = " + hideViewWidth);
  if (left == 0) {
   return SwipeState.Close;
  }

  if (left == -hideViewWidth) {
   return SwipeState.Open;
  }
  return SwipeState.Swiping;
 }
 private OnSwipeStateChangeListener listener;

 public void setOnSwipeStateChangeListener(
   OnSwipeStateChangeListener listener) {
  this.listener = listener;
 }

 public View getContentView() {
  return contentView;
 }

 public interface OnSwipeStateChangeListener {
  void onOpen(SwipeLayout swipeLayout);

  void onClose(SwipeLayout swipeLayout);

  void onStartOpen(SwipeLayout swipeLayout);

  void onStartClose(SwipeLayout swipeLayout);
 }

然后接下來是寫一個為listView設(shè)置的SwipeAdapter

SwipeAdapter.java

------------
public class SwipeAdapter extends BaseAdapter implements OnSwipeStateChangeListener {
 private Context mContext;
 private List<String> list;
 private MyClickListener myClickListener;
 private SwipeLayoutManager swipeLayoutManager;

 public SwipeAdapter(Context mContext) {
  super();
  this.mContext = mContext;
  init();
 }

 private void init() {
  myClickListener = new MyClickListener();
  swipeLayoutManager = SwipeLayoutManager.getInstance();
 }

 public void setList(List<String> list){
  this.list = list;
  notifyDataSetChanged();
 }

 @Override
 public int getCount() {
  return list.size();
 }

 @Override
 public Object getItem(int position) {
  return list.get(position);
 }

 @Override
 public long getItemId(int position) {
  return position;
 }

 @Override
 public View getView(final int position, View convertView, ViewGroup parent) {
  if (convertView == null) {
   convertView = UIUtils.inflate(R.layout.list_item_swipe);
  }
  ViewHolder holder = ViewHolder.getHolder(convertView);

  holder.tv_content.setText(list.get(position));
  holder.tv_overhead.setOnClickListener(myClickListener);
  holder.tv_overhead.setTag(position);
  holder.tv_delete.setOnClickListener(myClickListener);
  holder.tv_delete.setTag(position);
  holder.sv_layout.setOnSwipeStateChangeListener(this);
  holder.sv_layout.setTag(position);

  holder.sv_layout.getContentView().setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    ToastUtils.showToast("item click : " + position);
    swipeLayoutManager.closeUnCloseSwipeLayout();
   }
  });

  return convertView;
 }

 static class ViewHolder {
  TextView tv_content, tv_overhead, tv_delete;
  SwipeLayout sv_layout;

  public ViewHolder(View convertView) {
   tv_content = (TextView) convertView.findViewById(R.id.tv_content);
   tv_overhead = (TextView) convertView.findViewById(R.id.tv_overhead);
   tv_delete = (TextView) convertView.findViewById(R.id.tv_delete);
   sv_layout = (SwipeLayout) convertView.findViewById(R.id.sv_layout);
  }

  public static ViewHolder getHolder(View convertView) {
   ViewHolder holder = (ViewHolder) convertView.getTag();
   if (holder == null) {
    holder = new ViewHolder(convertView);
    convertView.setTag(holder);
   }
   return holder;
  }
 }

 class MyClickListener implements View.OnClickListener {
  @Override
  public void onClick(View v) {
   Integer position = (Integer) v.getTag();
   switch (v.getId()) {
    case R.id.tv_overhead:
     //ToastUtils.showToast("position : " + position + " overhead is clicked.");
     }
     break;
    case R.id.tv_delete:
     //ToastUtils.showToast("position : " + position + " delete is clicked.");
     }
     break;
    default:
     break;
   }
  }
 }

 @Override
 public void onOpen(SwipeLayout swipeLayout) {
  //ToastUtils.showToast(swipeLayout.getTag() + "onOpen.");
 }

 @Override
 public void onClose(SwipeLayout swipeLayout) {
  //ToastUtils.showToast(swipeLayout.getTag() + "onClose.");
 }

 @Override
 public void onStartOpen(SwipeLayout swipeLayout) {
  //   ToastUtils.showToast("onStartOpen.");
 }

 @Override
 public void onStartClose(SwipeLayout swipeLayout) {
  //   ToastUtils.showToast("onStartClose.");
 }
}

此時已經(jīng)基本實(shí)現(xiàn)了我們需要的大部分功能了,但是當(dāng)我們滑動的時候,又發(fā)現(xiàn)新的問題,我們的SwipeLayout和listview滑動判斷有問題。由于前面我們僅僅是將touch攔截事件簡簡單單的丟給了viewDragHelper.shouldInterceptTouchEvent(ev)來處理,導(dǎo)致SwipeLayout和listview攔截touch事件時的處理存在一定的問題,這里我們要提到一個知識點(diǎn):Android view事件的傳遞。
(1)首先由Activity分發(fā),分發(fā)給根View,也就是DecorView(DecorView為整個Window界面的最頂層View)
(2)然后由根View分發(fā)到子的View

view事件攔截如下圖所示:

怎么在Android應(yīng)用中實(shí)現(xiàn)一個抽屜效果

view事件的消費(fèi)如下圖所示:

怎么在Android應(yīng)用中實(shí)現(xiàn)一個抽屜效果

注:以上2張圖借鑒網(wǎng)上總結(jié)的比較經(jīng)典的圖

所以這里我們就要談到一開始出現(xiàn)的ContentLayout,主要重寫了onInterceptTouchEvent和onTouchEvent。

public class ContentLayout extends LinearLayout {
 SwipeLayoutInterface mISwipeLayout;

 public ContentLayout(Context context) {
  super(context);
 }

 public ContentLayout(Context context, AttributeSet attrs) {
  super(context, attrs);
 }

 public ContentLayout(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
 }

 public void setSwipeLayout(SwipeLayoutInterface iSwipeLayout) {
  this.mISwipeLayout = iSwipeLayout;
 }

 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
//  Log.e("ContentLayout", "-----onInterceptTouchEvent-----");
  if (mISwipeLayout.getCurrentState() == SwipeState.Close) {
   return super.onInterceptTouchEvent(ev);
  } else {
   return true;
  }
 }

 @Override
 public boolean onTouchEvent(MotionEvent ev) {
//  Log.e("ContentLayout", "-----onTouchEvent-----");
  if (mISwipeLayout.getCurrentState() == SwipeState.Close) {
   return super.onTouchEvent(ev);
  } else {
   if (ev.getActionMasked() == MotionEvent.ACTION_UP) {
    mISwipeLayout.close();
   }
   return true;
  }
 }
}

另外由于在ContentLayout中需要拿到父View SwipeLayout的開關(guān)狀態(tài)以及控制SwipeLayout的關(guān)閉,因此在再寫一個接口,用于ContentLayout獲取SwipeLayout的開關(guān)狀態(tài)以及更新SwipeLayout。

public interface SwipeLayoutInterface {

 SwipeState getCurrentState();

 void open();

 void close();
}

然后接著的是完善SwipeLayout的onInterceptTouchEvent,我們在這里增加一個GestureDetectorCompat處理手勢識別:

 private void init(Context context) {
  viewDragHelper = ViewDragHelper.create(this, callback);
  mGestureDetector = new GestureDetectorCompat(context, mOnGestureListener);
  swipeLayoutManager = SwipeLayoutManager.getInstance();
 }

 private SimpleOnGestureListener mOnGestureListener = new SimpleOnGestureListener() {
  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
   // 當(dāng)橫向移動距離大于等于縱向時,返回true
   return Math.abs(distanceX) >= Math.abs(distanceY);
  }
 };
  @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
  boolean result = viewDragHelper.shouldInterceptTouchEvent(ev) & mGestureDetector.onTouchEvent(ev);
  //  Log.e("SwipeLayout", "-----onInterceptTouchEvent-----");
  return result;
 }

如此下來,整個View不管是上下拖動,還是SwipeLayout的開關(guān)滑動,都已經(jīng)實(shí)現(xiàn)完成了。最后增加對應(yīng)overhead,delete以及item的點(diǎn)擊事件,此處完善SwipeAdapter的代碼之后如下。

 class MyClickListener implements View.OnClickListener {
  @Override
  public void onClick(View v) {
   Integer position = (Integer) v.getTag();
   switch (v.getId()) {
    case R.id.tv_overhead:
     //ToastUtils.showToast("position : " + position + " overhead is clicked.");
     swipeLayoutManager.closeUnCloseSwipeLayout(false);
     if(onSwipeControlListener != null){
      onSwipeControlListener.onOverhead(position, list.get(position));
     }
     break;
    case R.id.tv_delete:
     //ToastUtils.showToast("position : " + position + " delete is clicked.");
     swipeLayoutManager.closeUnCloseSwipeLayout(false);
     if(onSwipeControlListener != null){
      onSwipeControlListener.onDelete(position, list.get(position));
     }
     break;
    default:
     break;
   }
  }
 }

 private OnSwipeControlListener onSwipeControlListener;

 public void setOnSwipeControlListener(OnSwipeControlListener onSwipeControlListener){
  this.onSwipeControlListener = onSwipeControlListener;
 }

 /**
  * overhead 和 delete點(diǎn)擊事件接口
  */
 public interface OnSwipeControlListener{
  void onOverhead(int position, String itemTitle);

  void onDelete(int position, String itemTitle);
 }

最后貼上MainActivity代碼,此處通過OnSwipeControlListener接口回調(diào)實(shí)現(xiàn)item的刪除和置頂:

public class MainActivity extends Activity implements OnSwipeControlListener {
 private ListView listView;
 private List<String> list = new ArrayList<String>();
 private SwipeLayoutManager swipeLayoutManager;
 private SwipeAdapter swipeAdapter;

 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  initData();
  initView();
 }

 private void initData() {
  for (int i = 0; i < 50; i++) {
   list.add("content - " + i);
  }
 }

 private void initView() {
  swipeLayoutManager = SwipeLayoutManager.getInstance();
  swipeAdapter = new SwipeAdapter(this);
  swipeAdapter.setList(list);

  listView = (ListView) findViewById(R.id.list_view);

  listView.setAdapter(swipeAdapter);
  listView.setOnScrollListener(new OnScrollListener() {
   @Override
   public void onScrollStateChanged(AbsListView view, int scrollState) {
    swipeLayoutManager.closeUnCloseSwipeLayout();
   }

   @Override
   public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
   }
  });

  swipeAdapter.setOnSwipeControlListener(this);
 }

 @Override
 public void onOverhead(int position, String itemTitle) {
  setItemOverhead(position, itemTitle);
 }

 @Override
 public void onDelete(int position, String itemTitle) {
  removeItem(position, itemTitle);
 }

 /**
  * 設(shè)置item置頂
  *
  * @param position
  * @param itemTitle
  */
 private void setItemOverhead(int position, String itemTitle) {
  // ToastUtils.showToast("position : " + position + " overhead.");
  ToastUtils.showToast("overhead ---" + itemTitle + "--- success.");
  String newTitle = itemTitle;
  list.remove(position);//刪除要置頂?shù)膇tem
  list.add(0, newTitle);//根據(jù)adapter傳來的Title數(shù)據(jù)在list 0位置插入title字符串,達(dá)到置頂效果
  swipeAdapter.setList(list);//重新給Adapter設(shè)置list數(shù)據(jù)并更新
  UIUtils.runOnUIThread(new Runnable() {
   @Override
   public void run() {
    listView.setSelection(0);//listview選中第0項(xiàng)item
   }
  });
 }

 /**
  * 刪除item
  *
  * @param position
  * @param itemTitle
  */

 private void removeItem(int position, String itemTitle) {
  //  ToastUtils.showToast("position : " + position + " delete.");
  ToastUtils.showToast("delete ---" + itemTitle + "--- success.");
  list.remove(position);
  swipeAdapter.setList(list);//重新給Adapter設(shè)置list數(shù)據(jù)并更新
 }
}

至此整個demo基本完成,本次完成的功能基本能夠直接放到項(xiàng)目中使用。其實(shí)最麻煩的地方就在于view的touch事件攔截和處理,不過將本demo的log打開看一下對比之后,也就能夠理解整個傳遞過程了。

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

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI