欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android ReboundScrollView仿IOS拖拽回彈效果

 更新時間:2016年11月11日 10:16:41   作者:jia-huan  
這篇文章主要為大家詳細(xì)介紹了Android ReboundScrollView仿IOS拖拽回彈效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

初衷:

其實github上有很多這種ScrollView的項目,但是不得不說功能太多太亂了,我就只是想要一個簡單效果的ScrollView,另外監(jiān)聽下滑動距離而已,想想還是自己寫了個。

這里先說下思路吧,如果不愿意看的朋友可以直接跳過這一步,看下面的代碼:

Android 原生的ScrollView是不支持拉出屏幕外,并且也沒有回彈效果的,用戶友好度卻不不太好,不知道為什么不那么設(shè)計。

我想做的事情正如上面所述:

1.希望能拉出屏幕外
2.松手后希望控件回彈

我的思路是對ScrollView的子View進行操作

所有View的滑動控制肯定都受著onTouchEvent控制,所以,理所應(yīng)當(dāng)?shù)?,我要關(guān)注的重點,也就是onTouchEvent這個方法。

回彈的效果,就牽涉到位置的計算,這里我的想法就用簡單的TranslateAnimation來實現(xiàn)。

大體思路就是這樣了,先把思路確定了,然后代碼總是磨出來的。

貼代碼:

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView;

public class ReboundScrollView extends ScrollView {

 private static final float MOVE_DELAY = 0.3f;//當(dāng)拉出屏幕時的拖拽系數(shù)
 private static final int ANIM_TIME = 300;//回彈耗時
 private static final int FLING = 2;//fling 系數(shù)

 private View childView;
 private boolean havaMoved;

 private Rect originalRect = new Rect();

 private float startY;

 @Override
 protected void onFinishInflate() {
 super.onFinishInflate();
 if (getChildCount() > 0) {
  childView = getChildAt(0);
 }
 }

 @Override
 public void fling(int velocityY) {
 super.fling(velocityY / 2);
 }

 @Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {
 super.onLayout(changed, l, t, r, b);

 if (childView == null)
  return;

 originalRect.set(childView.getLeft(), childView.getTop(),
  childView.getRight(), childView.getBottom());
 }


 public ReboundScrollView(Context context, AttributeSet attrs,
    int defStyle) {
 super(context, attrs, defStyle);
 }

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

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


 /**
 * 在觸摸事件中, 處理上拉和下拉的邏輯
 */
 @Override
 public boolean dispatchTouchEvent(MotionEvent ev) {

 if (childView == null) {
  return super.dispatchTouchEvent(ev);
 }

 int action = ev.getAction();

 switch (action) {
  case MotionEvent.ACTION_DOWN:
  startY = ev.getY();
  break;

  case MotionEvent.ACTION_UP:
  case MotionEvent.ACTION_CANCEL:
  if (!havaMoved)
   break;

  TranslateAnimation anim = new TranslateAnimation(0, 0,
   childView.getTop(), originalRect.top);
  anim.setDuration(ANIM_TIME);

  childView.startAnimation(anim);
  // 將標(biāo)志位設(shè)回false
  havaMoved = false;
  resetViewLayout();

  break;
  case MotionEvent.ACTION_MOVE:

  float nowY = ev.getY();
  int deltaY = (int) (nowY - startY);
  int offset = (int) (deltaY * MOVE_DELAY);
  childView.layout(originalRect.left, originalRect.top + offset,
   originalRect.right, originalRect.bottom + offset);

  havaMoved = true;

  break;
  default:
  break;
 }

 return super.dispatchTouchEvent(ev);
 }

 public void resetViewLayout() {
 childView.layout(originalRect.left, originalRect.top,
  originalRect.right, originalRect.bottom);
 }

}

把代碼貼出來后,再來分析具體的實現(xiàn):

首先是拉出屏幕,在MOVE的過程中,對于超出部分代碼,我使用layout重置子View的位置。

第二個要實現(xiàn)的就是回彈了,拖出去總是要回來的:

這里我定義了一個Rect,在onLayout(boolean changed, int l, int t, int r, int b)方法中,記錄下了ScrollView的初始位置,以便于重置回彈。

說了許多,看一下代碼里的關(guān)鍵代碼

MOVE的代碼:

 float nowY = ev.getY();
  int deltaY = (int) (nowY - startY);
  int offset = (int) (deltaY * MOVE_DELAY);
  childView.layout(originalRect.left, originalRect.top + offset,
   originalRect.right, originalRect.bottom + offset);

  havaMoved = true;

這是MotionEvent.ACTION_MOVE的時候要做的,對chlidView的位置重新設(shè)置也就是lauout方法,這是基于originalRect的值來的,設(shè)定了相應(yīng)的滑動系數(shù),不然感覺實在是太靈敏了。

回彈的代碼:

 if (!havaMoved)
   break;

  TranslateAnimation anim = new TranslateAnimation(0, 0,
   childView.getTop(), originalRect.top);
  anim.setDuration(ANIM_TIME);

  childView.startAnimation(anim);
  // 將標(biāo)志位設(shè)回false
  havaMoved = false;
  resetViewLayout();
...
...
 public void resetViewLayout() {
 childView.layout(originalRect.left, originalRect.top,
  originalRect.right, originalRect.bottom);
 }

當(dāng)手指 MotionEvent.ACTION_UP或者MotionEvent.ACTION_CANCEL的時候把clildView置于原位,然后設(shè)置動畫,這就是回彈了。

補充:

這是個非常簡單的回彈ScrollView,需要注意的是,我這里沒有對在屏幕內(nèi)正常移動和屏幕外移動作區(qū)分,那樣就需要判斷當(dāng)前的移動是否需要我們重寫了,也就是是否處于上拉,下拉的部分。沒有做判斷,我現(xiàn)在的代碼就會導(dǎo)致你手勢移動的距離和控件滾動的距離是不一樣的。我是感覺如果你正常使用是不會注意到這一點的。但是不排除有這種需求。

下拉其實不太好判斷,因為我這里操作的是ChildView,ScrollView在上拉過程中g(shù)etScrollY()肯定是0,所以這一點,我也還沒想好。不過上拉倒是比較簡單。當(dāng)childView.height <= ScrollView.height + getScrollY的時候就是上拉出屏幕的點了,這個應(yīng)該能想通吧。

git地址:https://github.com/cjhandroid/ReboundScrollView

源碼下載:http://xiazai.jb51.net/201611/yuanma/androidReboundScrollView(jb51.net).rar

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論