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

首頁 > 系統 > Android > 正文

android實現QQ微信側滑刪除效果

2019-10-22 18:21:39
字體:
來源:轉載
供稿:網友

最近由于項目需求,需要做一個listview中的item策劃刪除的效果,與是查找資料和參考了一些相關的博客,終于完美實現了策劃刪除的效果。

先看一下效果圖(研究了半天竟然沒研究出來真機上gif圖怎么做,大家將就看一下吧)。

android微信側滑刪除,android,qq側滑刪除,android微信側滑     

側滑效果圖

android微信側滑刪除,android,qq側滑刪除,android微信側滑

點擊刪除后的截圖

android微信側滑刪除,android,qq側滑刪除,android微信側滑

點擊刪除后,listview中的第一個“微信團隊”被刪除。

接下來看代碼部分,很多注釋都在代碼中,直接上代碼。

首先自定義個SlideView繼承LinearLayout。

import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.Scroller; import android.widget.TextView;  /**   * SlideView 繼承自LinearLayout   */  public class SlideView extends LinearLayout {      private static final String TAG = "SlideView";      private Context mContext;      // 用來放置所有view的容器    private LinearLayout mViewContent;      // 用來放置內置view的容器,比如刪除 按鈕    private RelativeLayout mHolder;      // 彈性滑動對象,提供彈性滑動效果    private Scroller mScroller;      // 滑動回調接口,用來向上層通知滑動事件    private OnSlideListener mOnSlideListener;      // 內置容器的寬度 單位:dp    private int mHolderWidth = 120;      // 分別記錄上次滑動的坐標    private int mLastX = 0;    private int mLastY = 0;      // 用來控制滑動角度,僅當角度a滿足如下條件才進行滑動:tan a = deltaX / deltaY > 2    private static final int TAN = 2;      public interface OnSlideListener {      // SlideView的三種狀態:開始滑動,打開,關閉      public static final int SLIDE_STATUS_OFF = 0;      public static final int SLIDE_STATUS_START_SCROLL = 1;      public static final int SLIDE_STATUS_ON = 2;        public void onSlide(View view, int status);    }      public SlideView(Context context) {      super(context);      initView();    }      public SlideView(Context context, AttributeSet attrs) {      super(context, attrs);      initView();    }      private void initView() {      mContext = getContext();      // 初始化彈性滑動對象      mScroller = new Scroller(mContext);      // 設置其方向為橫向      setOrientation(LinearLayout.HORIZONTAL);      // 將slide_view_merge加載進來      View.inflate(mContext, R.layout.slide_view_merge, this);      mViewContent = (LinearLayout) findViewById(R.id.view_content);      mHolderWidth = Math.round(TypedValue.applyDimension(          TypedValue.COMPLEX_UNIT_DIP, mHolderWidth, getResources()              .getDisplayMetrics()));    }      // 設置按鈕的內容,也可以設置圖標啥的,我沒寫    public void setButtonText(CharSequence text) {      ((TextView) findViewById(R.id.delete)).setText(text);    }      // 將view加入到ViewContent中    public void setContentView(View view) {      mViewContent.addView(view);    }      // 設置滑動回調    public void setOnSlideListener(OnSlideListener onSlideListener) {      mOnSlideListener = onSlideListener;    }      // 將當前狀態置為關閉    public void shrink() {      if (getScrollX() != 0) {        this.smoothScrollTo(0, 0);      }    }      // 根據MotionEvent來進行滑動,這個方法的作用相當于onTouchEvent    // 如果你不需要處理滑動沖突,可以直接重命名,照樣能正常工作    public void onRequireTouchEvent(MotionEvent event) {      int x = (int) event.getX();      int y = (int) event.getY();      int scrollX = getScrollX();      Log.d(TAG, "x=" + x + " y=" + y);        switch (event.getAction()) {      case MotionEvent.ACTION_DOWN: {        if (!mScroller.isFinished()) {          mScroller.abortAnimation();        }        if (mOnSlideListener != null) {          mOnSlideListener.onSlide(this,              OnSlideListener.SLIDE_STATUS_START_SCROLL);        }        break;      }      case MotionEvent.ACTION_MOVE: {        int deltaX = x - mLastX;        int deltaY = y - mLastY;        if (Math.abs(deltaX) < Math.abs(deltaY) * TAN) {          // 滑動不滿足條件,不做橫向滑動          break;        }          // 計算滑動終點是否合法,防止滑動越界        int newScrollX = scrollX - deltaX;        if (deltaX != 0) {          if (newScrollX < 0) {            newScrollX = 0;          } else if (newScrollX > mHolderWidth) {            newScrollX = mHolderWidth;          }          this.scrollTo(newScrollX, 0);        }        break;      }      case MotionEvent.ACTION_UP: {        int newScrollX = 0;        // 這里做了下判斷,當松開手的時候,會自動向兩邊滑動,具體向哪邊滑,要看當前所處的位置        if (scrollX - mHolderWidth * 0.75 > 0) {          newScrollX = mHolderWidth;        }        // 慢慢滑向終點        this.smoothScrollTo(newScrollX, 0);        // 通知上層滑動事件        if (mOnSlideListener != null) {          mOnSlideListener.onSlide(this,              newScrollX == 0 ? OnSlideListener.SLIDE_STATUS_OFF                  : OnSlideListener.SLIDE_STATUS_ON);        }        break;      }      default:        break;      }        mLastX = x;      mLastY = y;    }      private void smoothScrollTo(int destX, int destY) {      // 緩慢滾動到指定位置      int scrollX = getScrollX();      int delta = destX - scrollX;      // 以三倍時長滑向destX,效果就是慢慢滑動      mScroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 3);      invalidate();    }      @Override    public void computeScroll() {      if (mScroller.computeScrollOffset()) {        scrollTo(mScroller.getCurrX(), mScroller.getCurrY());        postInvalidate();      }    }    }

自定義SlideView所關聯的xml.(主要就是布局側滑顯出來的刪除按鈕)

<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android"   android:layout_width="match_parent"   android:layout_height="match_parent" >    <LinearLayout     android:id="@+id/view_content"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:orientation="horizontal" >   </LinearLayout>    <RelativeLayout     android:id="@+id/holder"     android:layout_width="120dp"     android:layout_height="match_parent"     android:clickable="true"     android:background="@drawable/holder_bg">      <TextView       android:id="@+id/delete"       android:layout_width="wrap_content"       android:layout_height="wrap_content"       android:drawableLeft="@drawable/del_icon_normal"       android:layout_centerInParent="true"       android:gravity="center"       android:textColor="@color/floralwhite"       android:text="刪除" />   </RelativeLayout>  </merge>

自定義ListViewCompat繼承Listview。

import com.ryg.slideview.MainActivity.MessageItem;  import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.ListView;  public class ListViewCompat extends ListView {    private static final String TAG = "ListViewCompat";    private SlideView mFocusedItemView;    public ListViewCompat(Context context) {     super(context);   }    public ListViewCompat(Context context, AttributeSet attrs) {     super(context, attrs);   }    public ListViewCompat(Context context, AttributeSet attrs, int defStyle) {     super(context, attrs, defStyle);   }    public void shrinkListItem(int position) {     View item = getChildAt(position);      if (item != null) {       try {         ((SlideView) item).shrink();       } catch (ClassCastException e) {         e.printStackTrace();       }     }   }    @Override    public boolean onTouchEvent(MotionEvent event) {      switch (event.getAction()) {      case MotionEvent.ACTION_DOWN: {        int x = (int) event.getX();        int y = (int) event.getY();        //根據坐標獲取item所在的行        int position = pointToPosition(x, y);        Log.e(TAG, "postion=" + position);        if (position != INVALID_POSITION) {          //得到當前點擊行的數據從而取出當前行的item。          //可能有人懷疑,為什么要這么干?為什么不用getChildAt(position)?          //因為ListView會進行緩存,如果你不這么干,有些行的view你是得不到的。          MessageItem data = (MessageItem) getItemAtPosition(position);          mFocusedItemView = data.slideView;          Log.e(TAG, "FocusedItemView=" + mFocusedItemView);        }      }      default:        break;      }          //向當前點擊的view發送滑動事件請求,其實就是向SlideView發請求      if (mFocusedItemView != null) {        mFocusedItemView.onRequireTouchEvent(event);      }          return super.onTouchEvent(event);    }   } 

接下來就是主界面的activity了

import java.util.ArrayList; import java.util.List;  import com.ryg.slideview.SlideView.OnSlideListener;  import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView;  public class MainActivity extends Activity implements OnItemClickListener,  OnClickListener, OnSlideListener {   private static final String TAG = "MainActivity";   private ListViewCompat mListView;   private List<MessageItem> mMessageItems = new ArrayList<MainActivity.MessageItem>();   private SlideAdapter mSlideAdapter;   // 上次處于打開狀態的SlideView  private SlideView mLastSlideViewWithStatusOn;   @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  initView();  }   private void initView() {  mListView = (ListViewCompat) findViewById(R.id.list);   for (int i = 0; i < 20; i++) {    MessageItem item = new MessageItem();    if (i % 2 == 0) {      item.iconRes = R.drawable.default_qq_avatar;      item.title = "騰訊新聞";      item.msg = "天津大爆炸:河北大爆炸";      item.time = "晚上18:00";    } else {      item.iconRes = R.drawable.wechat_icon;      item.title = "微信團隊";      item.msg = "歡迎你使用微信";      item.time = "10月01日";    }    mMessageItems.add(item);  }  mSlideAdapter = new SlideAdapter();  mListView.setAdapter(mSlideAdapter);  mListView.setOnItemClickListener(this);  }   //listview 的適配器 private class SlideAdapter extends BaseAdapter {   private LayoutInflater mInflater;   SlideAdapter() {    super();    mInflater = getLayoutInflater();  }   @Override  public int getCount() {    return mMessageItems.size();  }   @Override  public Object getItem(int position) {    return mMessageItems.get(position);  }   @Override  public long getItemId(int position) {    return position;  }   @Override  public View getView(int position, View convertView, ViewGroup parent) {    ViewHolder holder;    SlideView slideView = (SlideView) convertView;    if (slideView == null) {      // 這里是我們的item      View itemView = mInflater.inflate(R.layout.list_item, null);       slideView = new SlideView(MainActivity.this);      // 這里把item加入到slideView      slideView.setContentView(itemView);      // 下面是做一些數據緩存      holder = new ViewHolder(slideView);      slideView.setOnSlideListener(MainActivity.this);      slideView.setTag(holder);    } else {      holder = (ViewHolder) slideView.getTag();    }    MessageItem item = mMessageItems.get(position);    item.slideView = slideView;    item.slideView.shrink();     holder.icon.setImageResource(item.iconRes);    holder.title.setText(item.title);    holder.msg.setText(item.msg);    holder.time.setText(item.time);    holder.deleteHolder.setOnClickListener(MainActivity.this);     return slideView;  }   }   public class MessageItem {  public int iconRes;  public String title;  public String msg;  public String time;  public SlideView slideView;  }   private static class ViewHolder {  public ImageView icon;  public TextView title;  public TextView msg;  public TextView time;  public ViewGroup deleteHolder;   ViewHolder(View view) {    icon = (ImageView) view.findViewById(R.id.icon);   msg = (TextView) view.findViewById(R.id.msg);    time = (TextView) view.findViewById(R.id.time);    deleteHolder = (ViewGroup) view.findViewById(R.id.holder);  }  }   @Override  public void onItemClick(AdapterView<?> parent, View view, int position,    long id) {  // 這里處理ListItem的點擊事件  Log.e(TAG, "onItemClick position=" + position);  }   @Override  public void onSlide(View view, int status) {  // 如果當前存在已經打開的SlideView,那么將其關閉  if (mLastSlideViewWithStatusOn != null      && mLastSlideViewWithStatusOn != view) {    mLastSlideViewWithStatusOn.shrink();  }  // 記錄本次處于打開狀態的view  if (status == SLIDE_STATUS_ON) {    mLastSlideViewWithStatusOn = (SlideView) view;  }  }   @Override  public void onClick(View v) {  // 這里處理刪除按鈕的點擊事件,可以刪除對話  if (v.getId() == R.id.holder) {    int position = mListView.getPositionForView(v);    if (position != ListView.INVALID_POSITION) {      mMessageItems.remove(position);      mSlideAdapter.notifyDataSetChanged();    }    Log.e(TAG, "onClick v=" + v);  }  } 

主界面中activity用到的xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   xmlns:tools="http://schemas.android.com/tools"   android:layout_width="match_parent"   android:layout_height="match_parent" >    <com.ryg.slideview.ListViewCompat     android:id="@+id/list"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:background="#fff4f7f9"     android:cacheColorHint="#00000000"     android:divider="#dddbdb"     android:dividerHeight="1.0px"     android:drawSelectorOnTop="false"     android:listSelector="@android:color/transparent"     android:scrollbars="none" />  </LinearLayout>

listview適配器的布局。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"   xmlns:tools="http://schemas.android.com/tools"   android:layout_width="match_parent"   android:layout_height="58dp"   android:background="@drawable/list_item_bg"   android:descendantFocusability="blocksDescendants"   android:gravity="center_vertical"   android:paddingBottom="5dp"   android:paddingLeft="10dp"   android:paddingRight="10dp"   android:paddingTop="5dp" >    <ImageView     android:id="@+id/icon"     android:layout_width="50dp"     android:layout_height="50dp"     android:layout_marginRight="5dp"     android:src="@drawable/wechat_icon" />    <TextView     android:id="@+id/title"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_toRightOf="@id/icon"     android:textColor="@color/black"     android:textSize="15sp" />    <TextView     android:id="@+id/msg"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_alignBottom="@id/icon"     android:layout_alignLeft="@id/title"     android:textColor="@color/grey" />    <TextView     android:id="@+id/time"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_alignParentRight="true"     android:layout_alignTop="@id/title"     android:textColor="@color/grey" />  </RelativeLayout>

附drawable目錄下的xml文件
holder_bg.xml

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:drawable="@color/dimgrey" android:state_pressed="true"></item>   <item android:drawable="@color/dimgrey" android:state_focused="true"></item>   <item android:drawable="@color/dimgrey" android:state_selected="true"></item>   <item android:drawable="@color/gray" android:state_enabled="true"></item>   <item android:drawable="@color/gray" android:state_enabled="false"></item>  </selector> 

list_item_bg.xml.

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:drawable="@drawable/item_point_bg" android:state_pressed="true"></item>   <item android:drawable="@drawable/item_point_bg" android:state_focused="true"></item>   <item android:drawable="@drawable/item_point_bg" android:state_selected="true"></item>   <item android:drawable="@android:color/transparent" android:state_enabled="true"></item>   <item android:drawable="@android:color/transparent" android:state_enabled="false"></item>  </selector>

還有一些對color顏色的定義,這里就不貼了,大家可以直接換成顏色的代碼就可以。

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


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 永平县| 桃园市| 石狮市| 敦煌市| 宁明县| 三都| 辛集市| 繁峙县| 武隆县| 东乡| 白城市| 隆化县| 青川县| 乌什县| 车险| 资溪县| 澄迈县| 邮箱| 祁门县| 永福县| 孟州市| 鹤岗市| 集贤县| 筠连县| 泰宁县| 池州市| 福安市| 内黄县| 赣榆县| 个旧市| 宁阳县| 阿城市| 泰安市| 门源| 青龙| 晋宁县| 长丰县| 马鞍山市| 密云县| 高平市| 东莞市|