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

Android中自定義view實(shí)現(xiàn)側(cè)滑效果

 更新時(shí)間:2016年11月23日 11:17:20   作者:_solary  
這篇文章主要介紹了Android中自定義view實(shí)現(xiàn)側(cè)滑效果的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下

效果圖:

看網(wǎng)上的都是兩個(gè)view拼接,默認(rèn)右側(cè)的不顯示,水平移動的時(shí)候把右側(cè)的view顯示出來。但是看最新版QQ上的效果不是這樣的,但給人的感覺卻很好,所以獻(xiàn)丑來一發(fā)比較高仿的。

知識點(diǎn):

1、ViewDragHelper 的用法;
2、滑動沖突的解決;
3、自定義viewgroup。

ViewDragHelper 出來已經(jīng)比較久了 相信大家都比較熟悉,不熟悉的話google一大把這里主要簡單用一下它的幾個(gè)方法

1、tryCaptureView(View child, int pointerId) :確定那個(gè)子view可以滑動

2、 getViewHorizontalDragRange(View child):用我蹩腳的英語翻譯一下是‘返回的是子view在水平方向上可移動的大小,以像素為單位,返回0的時(shí)候表示水平方向上不能拖動'

3、clampViewPositionHorizontal(View child, int left, int dx):在這里可以對邊界進(jìn)行檢查,left和dx分別代表即將移動到的位置

4、onViewPositionChanged(View changedView, int left, int top,
int dx, int dy):當(dāng)要捕獲view,由于拖曳或者設(shè)定而發(fā)生位置變更時(shí)回調(diào)

它的基本用法是:

public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
  }
  private void init() {
    viewDragHelper = ViewDragHelper.create(this, callback);
  }
   public boolean onInterceptTouchEvent(MotionEvent ev) {
    boolean result = viewDragHelper.shouldInterceptTouchEvent(ev);
   }
   public boolean onTouchEvent(MotionEvent event) {
    viewDragHelper.processTouchEvent(event);
    return true;
  }

1)、在構(gòu)造方法中創(chuàng)建

2)、在onInterceptTouchEvent 中判斷是否攔截

3 )、 在 onTouchEvent出來事件

好了 最不好理解的已經(jīng)搞定了。接下來看看具體實(shí)現(xiàn):

首先看布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical" >
  <scrollviewgroup.lly.com.swiplayout.SwipeLayout
    android:id="@+id/swipeLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
    <!-- delete區(qū)域的布局 -->
    <include layout="@layout/layout_delete" />
    <!-- item內(nèi)容的布局 -->
    <include layout="@layout/layout_content" />
  </scrollviewgroup.lly.com.swiplayout.SwipeLayout>
</LinearLayout>

這個(gè)沒什么好說的,一個(gè)自定義viewgroup包含兩個(gè)子控件。

接著看看SwipeLayout是怎么實(shí)現(xiàn)的:

@Override
  protected void onFinishInflate() {
    super.onFinishInflate();
    deleteView = getChildAt(0);
    contentView = getChildAt(1);
  }
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    deleteHeight = deleteView.getMeasuredHeight();
    deleteWidth = deleteView.getMeasuredWidth();
    contentWidth = contentView.getMeasuredWidth();
    screenWidth = getWidth();
  }
  @Override
  protected void onLayout(boolean changed, int left, int top, int right,
              int bottom) {
    // super.onLayout(changed, left, top, right, bottom);
    deleteView.layout(screenWidth - deleteWidth, 0, (screenWidth - deleteWidth)
        + deleteWidth, deleteHeight);
    contentView.layout(0, 0, contentWidth, deleteHeight);
  }

上面代碼進(jìn)行了一些初始化的操作,重點(diǎn)看看onlayout里面的,我們繼承的是framelayout 這里先畫出來 deleteView并讓他在右邊,然后在上面改了一層contentView,這樣顯示的時(shí)候只會顯示contentView。

接下來看ontouch方法

public boolean onTouchEvent(MotionEvent event) {
    //如果當(dāng)前有打開的,則下面的邏輯不能執(zhí)行
    if(!SwipeLayoutManager.getInstance().isShouldSwipe(this)){
      requestDisallowInterceptTouchEvent(true);
      return true;
    }
    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)該處理,請求父view不要攔截
          requestDisallowInterceptTouchEvent(true);
        }
        //更新downX,downY
        downX = moveX;
        downY = moveY;
        break;
      case MotionEvent.ACTION_UP:
        break;
    }
    viewDragHelper.processTouchEvent(event);
    return true;
  }

上面主要就是對事件沖突的處理,當(dāng)是水平移動的時(shí)候就請求父視圖不要攔截。

接下來來重點(diǎn)就來了

private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
    @Override
    public boolean tryCaptureView(View child, int pointerId) {
      return child==contentView;
    }
    @Override
    public int getViewHorizontalDragRange(View child) {
      return deleteWidth;
    }
    @Override
    public int clampViewPositionHorizontal(View child, int left, int dx) {
      if(child==contentView){
        if(left>0)left = 0;
        if(left<-deleteWidth)left = -deleteWidth;
      }
      return left;
    }
    @Override
    public void onViewPositionChanged(View changedView, int left, int top,
                     int dx, int dy) {
      super.onViewPositionChanged(changedView, left, top, dx, dy);
      //判斷開和關(guān)閉的邏輯
      if(contentView.getLeft()==0 && currentState!=SwipeState.Close){
        //說明應(yīng)該將state更改為關(guān)閉
        currentState = SwipeState.Close;
        //回調(diào)接口關(guān)閉的方法
        if(listener!=null){
          listener.onClose(getTag());
        }
        //說明當(dāng)前的SwipeLayout已經(jīng)關(guān)閉,需要讓Manager清空一下
        SwipeLayoutManager.getInstance().clearCurrentLayout();
      }else if (contentView.getLeft()==-deleteWidth && currentState!=SwipeState.Open) {
        //說明應(yīng)該將state更改為開
        currentState = SwipeState.Open;
        //回調(diào)接口打開的方法
        if(listener!=null){
          listener.onOpen(getTag());
        }
        //當(dāng)前的Swipelayout已經(jīng)打開,需要讓Manager記錄一下下
        SwipeLayoutManager.getInstance().setSwipeLayout(SwipeLayout.this);
      }
    }
    @Override
    public void onViewReleased(View releasedChild, float xvel, float yvel) {
      super.onViewReleased(releasedChild, xvel, yvel);
      if(contentView.getLeft()<-deleteWidth/2){
        //應(yīng)該打開
        open();
      }else {
        //應(yīng)該關(guān)閉
        close();
      }
    }
  };

上面這段代碼里面的方法一開始我們都說過了,在來看下在tryCaptureView中我們讓 contentView可以滑動,在getViewHorizontalDragRange中卻東滑動范圍是deleteWidth,在clampViewPositionHorizontal中對邊界進(jìn)行了下限制,在onViewPositionChanged中進(jìn)行狀態(tài)的更新, 最后在手指抬起的時(shí)候讓view自動回滾,

 /**
   * 打開的方法
   */
  public void open() {
    viewDragHelper.smoothSlideViewTo(contentView,-deleteWidth,contentView.getTop());
    ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
  }
  /**
   * 關(guān)閉的方法
   */
  public void close() {
    viewDragHelper.smoothSlideViewTo(contentView,0,contentView.getTop());
    ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
  };
  public void computeScroll() {
    if(viewDragHelper.continueSettling(true)){
      ViewCompat.postInvalidateOnAnimation(this);
    }
  }

這里注意一定要重寫computeScroll方法,不然滑動效果動一下就不動了。

至此這個(gè)自定義framelayout就完成了

但是發(fā)現(xiàn)一個(gè)問題,我們在已經(jīng)滑動出來的view中上下滑動時(shí),這個(gè)view的deleteView還是顯示狀態(tài),所以還要在activity中處理一下:

 recyView.setOnScrollListener(new RecyclerView.OnScrollListener() {
      @Override
      public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
      }
      @Override
      public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        if(dy>0 || dy<0){
          SwipeLayoutManager.getInstance().closeCurrentLayout();
        }
      }
    });

當(dāng)這個(gè)RecyclerView是上下滑動時(shí),讓子view復(fù)位。
收工。

ps:本來是在eclipse中l(wèi)istview中實(shí)現(xiàn)的,但是想想google都已經(jīng)不支持eclipse了,而listview也快被RecyclerView代替了,所以最后還是切換到Android studio,用RecyclerView實(shí)現(xiàn)了一套。

源碼地址

以上所述是小編給大家介紹的Android中自定義view實(shí)現(xiàn)側(cè)滑效果,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Android下拉刷新官方版

    Android下拉刷新官方版

    這篇文章主要介紹了Android下拉刷新官方版的的相關(guān)資料,幫助大家實(shí)現(xiàn)Android下拉刷新,感興趣的小伙伴們可以參考一下
    2016-02-02
  • android Animation監(jiān)聽器AnimationListener的使用方法)

    android Animation監(jiān)聽器AnimationListener的使用方法)

    AnimaitonListener的使用方法主要是在Animation上設(shè)置一個(gè)監(jiān)聽器,下面通過一個(gè)實(shí)例說明它的使用方法
    2013-11-11
  • Android實(shí)現(xiàn)多線程斷點(diǎn)下載的方法

    Android實(shí)現(xiàn)多線程斷點(diǎn)下載的方法

    這篇文章主要介紹了Android實(shí)現(xiàn)多線程斷點(diǎn)下載的方法,可實(shí)現(xiàn)開始、暫停下載及百分比進(jìn)度條等功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-05-05
  • Android中檢測當(dāng)前是否為主線程最可靠的解決方法

    Android中檢測當(dāng)前是否為主線程最可靠的解決方法

    這篇文章主要介紹了Android中檢測當(dāng)前是否為主線程最可靠的解決方法,本文先是給出了最可靠的方法,然后給出了幾個(gè)實(shí)驗(yàn)例子,需要的朋友可以參考下
    2015-01-01
  • Android View滑動的實(shí)現(xiàn)分析示例

    Android View滑動的實(shí)現(xiàn)分析示例

    View滑動是Android實(shí)現(xiàn)自定義控件的基礎(chǔ),同時(shí)在開發(fā)中難免會遇到View的滑動處理,其實(shí)不管是那種滑動方法,基本思路是類似的;當(dāng)點(diǎn)擊事件傳到View時(shí),系統(tǒng)記下觸摸點(diǎn)的坐標(biāo),手指移動時(shí)系統(tǒng)記下移動后的左邊并算出偏移量,通過偏移量來修改View的坐標(biāo)
    2022-08-08
  • Android5.0中JobScheduler的使用方法

    Android5.0中JobScheduler的使用方法

    Android 5.0中如何使用JobScheduler API,這篇文章主要介紹了Android5.0中JobScheduler的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Flutter實(shí)現(xiàn)矩形取色器的封裝

    Flutter實(shí)現(xiàn)矩形取色器的封裝

    這篇文章主要為大家詳細(xì)介紹了Flutter實(shí)現(xiàn)矩形取色器的封裝,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • Android UI系列-----ScrollView和HorizontalScrollView的詳解

    Android UI系列-----ScrollView和HorizontalScrollView的詳解

    本篇文章主要是介紹的Android UI系列-----ScrollView和HorizontalScrollView,ScrollView和HorizontalScrollView都是布局容器,有需要的可以了解一下。
    2016-11-11
  • 詳解Android 裸眼3D效果View控件

    詳解Android 裸眼3D效果View控件

    主要的設(shè)計(jì)核心是依賴于傳感器對手機(jī)晃動的監(jiān)聽(重力感應(yīng)監(jiān)聽器),對每層圖片進(jìn)行不同的移動,實(shí)現(xiàn)仿3D效果。本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2021-08-08
  • 利用Jetpack Compose實(shí)現(xiàn)經(jīng)典俄羅斯方塊游戲

    利用Jetpack Compose實(shí)現(xiàn)經(jīng)典俄羅斯方塊游戲

    你的童年是否有俄羅斯方塊呢,本文就來介紹如何通過Jetpack Compose實(shí)現(xiàn)一個(gè)俄羅斯方塊!感興趣的小伙伴快跟隨小編一起動手嘗試一下吧
    2022-05-05

最新評論