亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

 更新時(shí)間:2017年01月09日 10:24:25   作者:S丶black  
這篇文章主要介紹了Android開發(fā)中模仿qq列表信息滑動刪除功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下

這個(gè)效果的完成主要分為兩個(gè)部分

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

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

大致思路:

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

重寫listview代碼

public class SlideListView extends ListView{
  private SlideItem mTouchView=null;//記錄當(dāng)前點(diǎn)擊的item View
  private float mDownX;//x軸坐標(biāo)
  private float mDownY;//y軸坐標(biāo)
  private int mTouchState;//記錄點(diǎn)擊狀態(tài)
  private int mTouchPosition;//記錄點(diǎn)擊位置
  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)點(diǎn)獲取點(diǎn)擊的item的position
        mTouchPosition = this.pointToPosition((int) ev.getX(), (int) ev.getY());
        //判斷當(dāng)前點(diǎn)擊的是否和上次點(diǎn)擊的item是同一個(gè),如果是同一個(gè),并且狀態(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());
        //如果不是同一個(gè)item 那么點(diǎn)擊的話就關(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項(xiàng)

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

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

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

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

額。。。英語一般

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

官方的描述是:當(dāng)我們執(zhí)行ontouch或invalidate()或postInvalidate()都會導(dǎo)致這個(gè)方法的執(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
  //計(jì)算滑動 動畫效果
  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)閉滑動的時(shí)候計(jì)算與父布局的剩余距離
  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)用 進(jìn)行視圖的移動  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)滑到右邊視圖一半的距離 自動滑進(jìn)滑出
        if ((downX - event.getX()) > (menuView.getWidth() / 2)) {
          smoothOpenMenu();
        } else {
          smoothCloseMenu();
          return false;
        }
        break;
    }
    //消費(fèi)掉事件
    return true;
  }
  /**
   * 視圖重新繪制時(shí)調(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) {
    //這兩個(gè)判斷是為了保證 不要把視圖移動過多 導(dǎo)致視圖偏移
    if (dis > menuView.getWidth()) {
      dis = menuView.getWidth();
    }
    if (dis < 0) {
      dis = 0;
    }
    //view.layout()控制view相對于其父布局的位置  在觸發(fā)移動的時(shí)候調(diào)用不斷改變位置 完成實(shí)際的滑動效果
    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上的實(shí)現(xiàn)此效果的開源項(xiàng)目

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

相關(guān)文章

最新評論