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

首頁 > 系統(tǒng) > Android > 正文

Android開發(fā)中模仿qq列表信息滑動刪除功能

2019-12-12 04:05:05
字體:
供稿:網(wǎng)友

這個效果的完成主要分為兩個部分

自定義view作為listview的列表項 一個view里面包括 顯示頭像,名字,消息內(nèi)容等的contentView和滑動才能顯示出來的刪除,置頂?shù)挠疫叢藛蝝enuView 在手指移動的時候同時改變這兩個視圖的位置

重寫listview 判斷item向左還是向右滑動 正常的滾動還是左右滑動等等 重寫onTouchEvent 進行事件分發(fā)

大致思路:

listview進行事件分發(fā),判斷需要滑動還是滾動等狀態(tài),如果需要滑動將事件傳遞給item進行滑動處理. 在item中控制contentView和menuView進行位置的變化完成滾動效果

重寫listview代碼

public class SlideListView extends ListView{  private SlideItem mTouchView=null;//記錄當(dāng)前點擊的item View  private float mDownX;//x軸坐標(biāo)  private float mDownY;//y軸坐標(biāo)  private int mTouchState;//記錄點擊狀態(tài)  private int mTouchPosition;//記錄點擊位置  private static final int TOUCH_STATE_NONE=0; //按下狀態(tài)  private static final int TOUCH_STATE_X=1;//橫滑狀態(tài)  private static final int TOUCH_STATE_Y=2;//豎滑狀態(tài)  //判斷橫豎滑動的最小值  private static final int MAX_Y=5;  private static final int MAX_X=3;  public SlideListView(Context context) {    super(context);  }  public SlideListView(Context context, AttributeSet attrs) {    super(context, attrs);  }  public SlideListView(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);  }  @Override  public boolean onTouchEvent(MotionEvent ev) {    if (ev.getAction() != MotionEvent.ACTION_DOWN && mTouchView == null)      return super.onTouchEvent(ev);    switch (ev.getAction()) {      case MotionEvent.ACTION_DOWN:        //按住的item的position        int oldPosition = mTouchPosition;        //記錄位置        mDownX = ev.getX();        mDownY = ev.getY();        mTouchState = TOUCH_STATE_NONE;        //根據(jù)當(dāng)前橫縱坐標(biāo)點獲取點擊的item的position        mTouchPosition = this.pointToPosition((int) ev.getX(), (int) ev.getY());        //判斷當(dāng)前點擊的是否和上次點擊的item是同一個,如果是同一個,并且狀態(tài)是打開了的就記錄狀態(tài)和坐標(biāo)        //記錄坐標(biāo)通過Item中的downX屬性        if (mTouchPosition == oldPosition && mTouchView != null && mTouchView.isOpen()) {          mTouchState = TOUCH_STATE_X;          mTouchView.onSwipe(ev);          return true;        }        //獲取當(dāng)前的item的View        View currentView = getChildAt(mTouchPosition - getFirstVisiblePosition());        //如果不是同一個item 那么點擊的話就關(guān)閉掉之前打開的item        if (mTouchView != null && mTouchView.isOpen()) {          mTouchView.smoothCloseMenu();          mTouchView = null;          return super.onTouchEvent(ev);        }        //判斷該view的類型        if (currentView instanceof SlideItem) {          mTouchView = (SlideItem) currentView;        }        if (mTouchView != null) {          mTouchView.onSwipe(ev);        }        break;      case MotionEvent.ACTION_MOVE:        float dy = Math.abs((ev.getY() - mDownY));        float dx = Math.abs((ev.getX() - mDownX));        if (mTouchState == TOUCH_STATE_X) {          if (mTouchView != null) {            //執(zhí)行滑動            mTouchView.onSwipe(ev);          }          return true;        } else if (mTouchState == TOUCH_STATE_NONE) {          //判斷滑動方向,x方向執(zhí)行滑動,Y方向執(zhí)行滾動          if (Math.abs(dy) > MAX_Y) {            mTouchState = TOUCH_STATE_Y;          } else if (dx > MAX_X) {            mTouchState = TOUCH_STATE_X;          }        }        break;      case MotionEvent.ACTION_UP:        //判斷狀態(tài)        if (mTouchState == TOUCH_STATE_X) {          if (mTouchView != null) {            mTouchView.onSwipe(ev);            //如過最后狀態(tài)是打開 那么就重新初始化            if (!mTouchView.isOpen()) {              mTouchPosition = -1;              mTouchView = null;            }          }          ev.setAction(MotionEvent.ACTION_CANCEL);          super.onTouchEvent(ev);          return true;        }        break;    }    return super.onTouchEvent(ev);  }}

重寫item項

view的滑動效果都是在里完成的 使用了Scroller類

關(guān)于Scroller的使用文章最后已經(jīng)粘出了大神的帖子 不懂的同學(xué)可以先把Scroller的使用理解了在看這個滑動效果就很好懂了 我在這里簡單講講

這個類的并沒有實際的完成滾動效果 它是一個計算控件移動軌跡的輔助類,
比如說:在1秒內(nèi)從位置0移動到位置100 這個類會計算出移動的數(shù)值,它并沒有完成滑動的效果,但是告訴了我們這個滑動的過程 實際的上的view移動操作在computeScroll()完成 這個方法是view的自帶方法 需要我們重寫

computeScroll方法又是怎么情況呢 看源碼 本身是個空的 就等著我們實現(xiàn) 我們實際改變view位置的代碼就是在此方法內(nèi)調(diào)用的

額。。。英語一般

大致意思 我們要通過Scroller實現(xiàn)一個滾動效果的時候 父布局就會調(diào)用此方法來完成子視圖的位置更新

官方的描述是:當(dāng)我們執(zhí)行ontouch或invalidate()或postInvalidate()都會導(dǎo)致這個方法的執(zhí)行

在此方法中不斷的獲取到移動的距離 通過view自帶的layout()方法更新view所在位置

 /**   * Called by a parent to request that a child update its values for mScrollX   * and mScrollY if necessary. This will typically be done if the child is   * animating a scroll using a {@link android.widget.Scroller Scroller}   * object.   */  public void computeScroll() {  }public class SlideItem extends LinearLayout {  private View contentView = null; //不滑動顯示的view  private View menuView = null; //左滑顯示的view  //計算滑動 動畫效果  private Scroller mOpenScroller;  private Scroller mCloseScroller;  private int downX; //開始按下的位置  //記錄狀態(tài)  private int state = STATE_CLOSE;  private static final int STATE_CLOSE = 0;  private static final int STATE_OPEN = 1;  private int mBaseX;//在關(guān)閉滑動的時候計算與父布局的剩余距離  public SlideItem(Context context) {    super(context);  }  public SlideItem(Context context, AttributeSet attrs) {    super(context, attrs);  }  public SlideItem(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);  }  public void setContentView(View contentView, View rightView){    this.contentView = contentView;    this.menuView = rightView;    //初始化mColoseScroller和mOpenScroller    mCloseScroller=new Scroller(getContext());    mOpenScroller = new Scroller(getContext());    initView();  }  //child view的布局參數(shù)設(shè)定好后 添加到parent view里面  private void initView() {    //這是設(shè)置寬和高    LayoutParams contentParams = new LayoutParams        (LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);    LayoutParams rightParams=new LayoutParams        (LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);    contentView.setLayoutParams(contentParams);    contentView.setPadding(10,10,10,10);    menuView.setLayoutParams(rightParams);    this.addView(contentView);    this.addView(menuView);  }  // 判斷是否滑出的狀態(tài)  public boolean isOpen() {    return state == STATE_OPEN;  }  /**   * 供listView調(diào)用 進行視圖的移動  listView判斷狀態(tài) 什么情況下左滑   * @param event   * @return   */  public boolean onSwipe(MotionEvent event) {    switch (event.getAction()) {      case MotionEvent.ACTION_DOWN:        downX = (int) event.getX();        break;      case MotionEvent.ACTION_MOVE:        //按下位置減去移動位置 獲取移動的距離        int dis = (int) (downX - event.getX());        if (state == STATE_OPEN) {          dis += menuView.getWidth();        }        //移動        move(dis);        break;      case MotionEvent.ACTION_UP:        //當(dāng)滑到右邊視圖一半的距離 自動滑進滑出        if ((downX - event.getX()) > (menuView.getWidth() / 2)) {          smoothOpenMenu();        } else {          smoothCloseMenu();          return false;        }        break;    }    //消費掉事件    return true;  }  /**   * 視圖重新繪制時調(diào)用   */  @Override  public void computeScroll() {    if (state == STATE_OPEN) {      //computeScrollOffset滑動是否結(jié)束      if (mOpenScroller.computeScrollOffset()) {        move(mOpenScroller.getCurrX());        postInvalidate();      }    } else {      if (mCloseScroller.computeScrollOffset()) {        move(mBaseX - mCloseScroller.getCurrX());        postInvalidate();      }    }  }  /**   * 移動視圖   * @param dis   */  private void move(int dis) {    //這兩個判斷是為了保證 不要把視圖移動過多 導(dǎo)致視圖偏移    if (dis > menuView.getWidth()) {      dis = menuView.getWidth();    }    if (dis < 0) {      dis = 0;    }    //view.layout()控制view相對于其父布局的位置  在觸發(fā)移動的時候調(diào)用不斷改變位置 完成實際的滑動效果    contentView.layout(-dis, contentView.getTop(), contentView.getWidth() - dis, getMeasuredHeight());    menuView.layout(contentView.getWidth() - dis, menuView.getTop(), contentView.getWidth() + menuView.getWidth() - dis, menuView.getBottom());  }  /**   * 滑動關(guān)閉   * contentView.getLeft() 與其父視圖的相對位置   */  public void smoothCloseMenu() {    state = STATE_CLOSE;    mBaseX = -contentView.getLeft();    mCloseScroller.startScroll(0, 0, mBaseX, 0, 350);    postInvalidate();  }  /**   * 滑動打開   */  public void smoothOpenMenu() {    state = STATE_OPEN;    mOpenScroller.startScroll(-contentView.getLeft(), 0, menuView.getWidth(), 0, 350);    postInvalidate();  }  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    if(menuView != null)      menuView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),          MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));  }  @Override  protected void onLayout(boolean changed, int l, int t, int r, int b) {    //確保centerView menuView的顯示位置    if(contentView != null)      contentView.layout(0, 0, getMeasuredWidth(), contentView.getMeasuredHeight());    if(menuView != null)      menuView.layout(getMeasuredWidth(), 0, getMeasuredWidth() + menuView.getMeasuredWidth(), contentView.getMeasuredHeight());  }}

適配器

public class SlideAdapter extends BaseAdapter implements View.OnClickListener{  private List<String> dataList;  private Context context;  private LayoutInflater inflater;  public SlideAdapter(Context context, List<String> dataList) {    this.context = context;    this.dataList = dataList;    this.inflater=LayoutInflater.from(context);  }  @Override  public int getCount() {    return 5;  }  @Override  public Object getItem(int position) {    return null;  }  @Override  public long getItemId(int position) {    return 0;  }  @Override  public View getView(int position, View convertView, ViewGroup parent) {    ViewHolder holder=null;    if (convertView==null){      View content=inflater.inflate(R.layout.adapter_item_content,null);      View menu=inflater.inflate(R.layout.adapter_item_menu,null);      holder=new ViewHolder(content,menu);      SlideItem slideItem=new SlideItem(context);      slideItem.setContentView(content,menu);      convertView=slideItem;      convertView.setTag(holder);    }else {      holder= (ViewHolder) convertView.getTag();    }    holder.itemTvDelete.setOnClickListener(this);    holder.itemTvNoRead.setOnClickListener(this);    holder.itemTvToTop.setOnClickListener(this);    return convertView;  }  class ViewHolder{    TextView itemTvToTop;    TextView itemTvNoRead;    TextView itemTvDelete;    public ViewHolder(View center,View menu) {      this.itemTvToTop = (TextView) menu.findViewById(R.id.item_to_top);      this.itemTvNoRead = (TextView) menu.findViewById(R.id.item_no_read);      this.itemTvDelete = (TextView) menu.findViewById(R.id.item_delete);    }  }  @Override  public void onClick(View v) {    switch (v.getId()){      case R.id.item_no_read:        Toast.makeText(context,"標(biāo)為未讀",Toast.LENGTH_SHORT).show();        break;      case R.id.item_to_top:        Toast.makeText(context,"置頂了熬",Toast.LENGTH_SHORT).show();        break;      case R.id.item_delete:        Toast.makeText(context,"刪除啦",Toast.LENGTH_SHORT).show();        break;    }  }}

參考文檔:

SwipeMenuListView github上的實現(xiàn)此效果的開源項目

以上所述是小編給大家介紹的Android開發(fā)中模仿qq列表信息滑動刪除功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對武林網(wǎng)網(wǎng)站的支持!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 离岛区| 大兴区| 休宁县| 秦安县| 双鸭山市| 杭锦后旗| 峨边| 连云港市| 梧州市| 曲松县| 曲麻莱县| 涪陵区| 普安县| 定州市| 股票| 清镇市| 潜江市| 安达市| 张掖市| SHOW| 丽水市| 肃南| 桐庐县| 天台县| 泽普县| 保德县| 凤台县| 班玛县| 广西| 乐东| 金阳县| 金湖县| 丹寨县| 威海市| 辽中县| 金川县| 呼图壁县| 南陵县| 德惠市| 瑞金市| 枣阳市|