一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Android - Android ScrollView的頂部下拉和底部上拉回彈效果

Android ScrollView的頂部下拉和底部上拉回彈效果

2022-02-17 17:16Denluoyia Android

本篇文章主要介紹了Android ScrollView的頂部下拉和底部上拉回彈效果,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

要實現ScrollView的回彈效果,需要對其進行觸摸事件處理。先來看一下簡單的效果:

Android ScrollView的頂部下拉和底部上拉回彈效果

根據Android的View事件分發處理機制,下面對dispatchTouchEvent進行詳細分析:

在加載布局完成之后,獲取ScrollView的第一個子元素,保存它的參數,left top right bottom參數,根據頂部下拉操作和底部上拉操作進行子View的布局參數根據滑動距離改變,ACTION_UP的時候判斷是否存在回彈,如果需要則進行動畫回彈到原來的位置,可以添加一個回彈結束監聽,比如監聽回彈處理跳轉到其他的頁面的操作等。

具體的實現如下,添加了是否禁用頂部和底部回彈的參數設置,以及回彈效果結束監聽。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/**
 * A Simple Rebound ScrollView
 * @author Denluoyia
 */
public class ReboundScrollView extends ScrollView{
 
  private boolean mEnableTopRebound = true;
  private boolean mEnableBottomRebound = true;
  private OnReboundEndListener mOnReboundEndListener;
  private View mContentView;
  private Rect mRect = new Rect();
 
  public ReboundScrollView(Context context) {
    super(context);
  }
 
  public ReboundScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }
 
  public ReboundScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }
 
  /** after inflating view, we can get the width and height of view */
  @Override
  protected void onFinishInflate() {
    super.onFinishInflate();
    mContentView = getChildAt(0);
  }
 
  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    if (mContentView == null) return;
    // to remember the location of mContentView
    mRect.set(mContentView.getLeft(), mContentView.getTop(), mContentView.getRight(), mContentView.getBottom());
  }
 
  public ReboundScrollView setOnReboundEndListener(OnReboundEndListener onReboundEndListener){
    this.mOnReboundEndListener = onReboundEndListener;
    return this;
 
  }
 
  public ReboundScrollView setEnableTopRebound(boolean enableTopRebound){
    this.mEnableTopRebound = enableTopRebound;
    return this;
  }
 
  public ReboundScrollView setEnableBottomRebound(boolean mEnableBottomRebound){
    this.mEnableBottomRebound = mEnableBottomRebound;
    return this;
  }
 
  private int lastY;
  private boolean rebound = false;
  private int reboundDirection = 0; //<0 表示下部回彈 >0 表示上部回彈 0表示不回彈
 
  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
    if (mContentView == null){
      return super.dispatchTouchEvent(ev);
    }
    switch (ev.getAction()){
      case MotionEvent.ACTION_DOWN:
        lastY = (int) ev.getY();
        break;
 
      case MotionEvent.ACTION_MOVE:
        if (!isScrollToTop() && !isScrollToBottom()){
          lastY = (int) ev.getY();
          break;
        }
        //處于頂部或者底部
        int deltaY = (int) (ev.getY() - lastY);
        //deltaY > 0 下拉 deltaY < 0 上拉
 
 
        //disable top or bottom rebound
        if ((!mEnableTopRebound && deltaY > 0) || (!mEnableBottomRebound && deltaY < 0)){
          break;
        }
 
        int offset = (int) (deltaY * 0.48);
        mContentView.layout(mRect.left, mRect.top + offset, mRect.right, mRect.bottom + offset);
        rebound = true;
        break;
 
      case MotionEvent.ACTION_UP:
        if (!rebound) break;
        reboundDirection = mContentView.getTop() - mRect.top;
        TranslateAnimation animation = new TranslateAnimation(0, 0, mContentView.getTop(), mRect.top);
        animation.setDuration(300);
        animation.setAnimationListener(new Animation.AnimationListener() {
          @Override
          public void onAnimationStart(Animation animation) {
 
          }
 
          @Override
          public void onAnimationEnd(Animation animation) {
            if (mOnReboundEndListener != null){
              if (reboundDirection > 0){
                mOnReboundEndListener.onReboundTopComplete();
              }
              if (reboundDirection < 0){
                mOnReboundEndListener.onReboundBottomComplete();
              }
              reboundDirection = 0;
            }
          }
 
          @Override
          public void onAnimationRepeat(Animation animation) {
 
          }
        });
        mContentView.startAnimation(animation);
        mContentView.layout(mRect.left, mRect.top, mRect.right, mRect.bottom);
        rebound = false;
        break;
    }
    return super.dispatchTouchEvent(ev);
  }
 
  @Override
  public void setFillViewport(boolean fillViewport) {
    super.setFillViewport(true); //默認是填充ScrollView 或者再XML布局文件中設置fillViewport屬性
  }
 
  /**
   * 判斷當前ScrollView是否處于頂部
   */
  private boolean isScrollToTop(){
    return getScrollY() == 0;
  }
 
  /**
   * 判斷當前ScrollView是否已滑到底部
   */
  private boolean isScrollToBottom(){
    return mContentView.getHeight() <= getHeight() + getScrollY();
  }
 
  /**
   * listener for top and bottom rebound
   * do your implement in the following methods
   */
  public interface OnReboundEndListener{
 
    void onReboundTopComplete();
 
    void onReboundBottomComplete();
  }
}

 使用:

直接在XML布局文件中把ScrollView替換成ReboundScrollView就可以了。還可以拓展把回彈頂部和底部添加其他的動畫效果(之后再拓展試下)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="utf-8"?>
<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"
  android:orientation="vertical"
  tools:context=".TestActivity">
 
  <com.denluoyia.dtils.widget.ReboundScrollView
    android:id="@+id/reboundScrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="#eefade"
      android:padding="16dp">
 
      <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="15sp"
        android:lineSpacingExtra="5dp"
        android:text="@string/content"/>
    </LinearLayout>
  </com.denluoyia.dtils.widget.ReboundScrollView>
 
</LinearLayout>

 如果需要禁用回彈,可以直接設置enableTopRebound和enableBottomRebound參數,同樣設置回彈結束(或開始)監聽。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class TestActivity extends AppCompatActivity {
 
  private ReboundScrollView reboundScrollView;
 
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);
 
    reboundScrollView = findViewById(R.id.reboundScrollView);
    //reboundScrollView.setEnableTopRebound(false);
    //reboundScrollView.setEnableBottomRebound(false);
    reboundScrollView.setOnReboundEndListener(new ReboundScrollView.OnReboundEndListener() {
      @Override
      public void onReboundTopComplete() {
        Toast.makeText(TestActivity.this, "頂部回彈", Toast.LENGTH_SHORT).show();
      }
 
      @Override
      public void onReboundBottomComplete() {
        Toast.makeText(TestActivity.this, "底部回彈", Toast.LENGTH_SHORT).show();
      }
    });
  }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/denluoyia/p/8995589.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 无码射肉在线播放视频 | 西野翔全部作品在线观看 | 精品久久香蕉国产线看观看亚洲 | 日韩视频在线精品视频免费观看 | 国内交换一区二区三区 | 欧美s级人做人爱c视频 | www在线免费观看 | 亚洲区精品 | 久久久久九九 | 丁香网五月天 | 欧美专区亚洲 | 日本韩国推理片免费观看网站 | 色婷婷网 | 亚洲红怡院 | 深夜免费网站 | 日本又大又硬又粗的视频 | 女子监狱第二季未删减在线看 | 日本阿v精品视频在线观看 日本xxx片免费高清在线 | 美女被吸乳老师羞羞漫画 | 欧美二区视频 | 给我免费观看的视频在线播放 | 婷婷色网| 日韩视频在线精品视频免费观看 | 日本老妇乱子伦中文视频 | 国产精品日韩欧美在线 | 国产一级在线观看 | 性xxxx18学生第一次出血 | 射逼视频 | 海角社区在线视频 | 高h辣h双处全是肉军婚 | 国产午夜免费秋霞影院 | 精品国产一区二区三区在线观看 | 色女阁 | 国产成人福利色视频 | 九九久久精品 | 成人网视频免费播放 | 国产日产欧产精品精品软件 | acg火影忍者熟密姬纲手h | 国产成人精品日本亚洲网址 | 好男人资源大全免费观看 | 免费网站看v片在线成人国产系列 |