Android ListView滑動回彈——overScrollBy
註解
/*** Scroll the view with standard behavior for scrolling beyond the normal
* content boundaries. Views that call this method should override
* {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
* results of an over-scroll operation.
*
* Views can use this method to handle any touch or fling-based scrolling.
*
* @param deltaX Change in X in pixels
* @param deltaY Change in Y in pixels
* @param scrollX Current X scroll value in pixels before applying deltaX
* @param scrollY Current Y scroll value in pixels before applying deltaY
* @param scrollRangeX Maximum content scroll range along the X axis
* @param scrollRangeY Maximum content scroll range along the Y axis
* @param maxOverScrollX Number of pixels to overscroll by in either direction
* along the X axis.
* @param maxOverScrollY Number of pixels to overscroll by in either direction
* along the Y axis.
* @param isTouchEvent true if this scroll operation is the result of a touch event.
* @return true if scrolling was clamped to an over-scroll boundary along either
* axis, false otherwise.
*/
protected boolean overScrollBy(int deltaX, int deltaY,
int scrollX, int scrollY,
int scrollRangeX, int scrollRangeY,
int maxOverScrollX, int maxOverScrollY,
boolean isTouchEvent)
maxOverScrollX、maxOverScrollY預設為0
注:
只有當listview不能單一螢幕顯示時才有該效果轉載內容
第一部分 原理分析
IOS上的bounce功能給人的感覺很爽,當一個可以滾動的區域被拖到邊界時,它允許使用者將內容拖過界,放手後再彈回來,以一種非常棒的方式提示了使用者邊界的存在,是IOS的一大特色。android2.3新增了overscroll功能,聽名字就知道應該是bounce功能的翻版,但也許是出於專利方面的考慮,google的預設實現跟IOS有所不同,它只是在list拖到邊界處時做了一個發光的動畫,個人覺得體驗比IOS差遠了。而且這個黃色的發光在黑色背景下雖然效果不錯,在其它背景下可就難說了,因此很多人想要關掉它。日前google上搜索“android overscroll”,對此效果的介紹很多,但關於其具體使用方式和實現,則很少涉及,偶有提及,也經常答非所問或似是而非,反而誤導了別人。於是我查閱了android相關原始碼,並做了一些測試,在此講講我的理解。
首先是overscroll功能本身,在最頂層的View類提供了支援,可通過setOverScrollMode函式控制其出現條件。但其實View中並沒有實現overscroll功能,它僅僅提供了一個輔助函式overScrollBy,該函式根據overScrollMode和內容是否需要滾動控制最大滾動範圍,最後將計算結果傳給onOverScrolled實現具體的overscroll功能,但此函式在View類中是全空的。
overscroll功能真正的實現分別在ScrollView、AbsListView、HorizontalScrollView和WebView中各有一份,程式碼基本一樣。以ScrollView為例,它在處理筆點移動訊息時呼叫overScrollBy來滾動檢視,然後過載了overScrollBy函式來實現具體功能,其位置計算通過OverScroller類實現。OverScroller作為一個計算引擎,應該是一個獨立的模組,具體滾動效果和範圍都不可能通過它來設定,我覺得沒有必要細看。但滾動位置最終是它給出的,那相關資料肯定要傳遞給它,回頭看overScrollBy函式,它有兩個控制overScroll出界範圍的引數,幾個實現裡面都是取自ViewConfiguration.getScaledOverscrollDistance,而這個引數的值在我的原始碼中都是0,而且我沒找到任何可以影響其結果的設定。
真悲催,繞了半天,android的預設實現裡面根本沒有給出overscroll功能,它只是提供了實現機制,要想用起來還得應用程式自己顯式重寫相關控制元件,估計還有一層隱含的意思,法律風險自負。在我的系統中一試,果然一個畫素都不能拉出界。但那個閃光是怎麼回事呢?
在處理筆點訊息處,overScrollBy後面不遠處有一段mEdgeGlowTop的操作程式碼,看名字就像,用它一搜,相關機制就全明白了。mEdgeGlowTop在setOverScrollMode函式時建立,它使用的圖片都是系統中固有的,甚至不能通過theme改變。它的實現原理也很簡單,僅僅是兩張png圖片的合成,通過透明度的變化製造閃光的效果。更無語的是它既不能被應用程式訪問,也不受任何控制,要關閉它的唯一辦法是setOverScrollMode(View.OVER_SCROLL_NEVER)。否則就重寫onTouchEvent函式吧,想幹啥都可以,只是得自己做。
談到overScroll,很多文章都提到了ListView的setOverscrollHeader和setOverscrollFooter,很多人想通過這個來控制那個閃光效果。這兩玩意不但可以通過函式設定,也可以在xml中指定,相當方便。但最後很多人發現沒有任何作用,百思不得其解。其實這兩張圖片是用來作為overScroll拖過界時的背景的,預設系統不能拖過界,自然永遠都看不到,有些定製的系統中能拖出界幾個畫素,但也很難看清。
第二部分 程式碼實現
1. 在View中增加了overSrollBy方法,用於記錄x, y 軸上滾動。
2. 在AbsListView的onTouchEvent中判斷是否到達邊界(頂部 或 底部) ,然後呼叫view.overScrollBy ,傳入 mScrollY等引數
3. overScrollBy 最終賦值給View的mScrollX, mScrollY 兩個變數
4. 在AbsListView中呼叫完overScrollBy之後,呼叫invalidate重繪
自定義ListView
Java程式碼
- public class BounceListView extends ListView{
- private static final int MAX_Y_OVERSCROLL_DISTANCE = 200;
- private Context mContext;
- private int mMaxYOverscrollDistance;
- public BounceListView(Context context){
- super(context);
- mContext = context;
- initBounceListView();
- }
- public BounceListView(Context context, AttributeSet attrs){
- super(context, attrs);
- mContext = context;
- initBounceListView();
- }
- public BounceListView(Context context, AttributeSet attrs, int defStyle){
- super(context, attrs, defStyle);
- mContext = context;
- initBounceListView();
- }
- private void initBounceListView(){
- //get the density of the screen and do some maths with it on the max overscroll distance
- //variable so that you get similar behaviors no matter what the screen size
- final DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
- final float density = metrics.density;
- mMaxYOverscrollDistance = (int) (density * MAX_Y_OVERSCROLL_DISTANCE);
- }
- @Override
- protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent){
- //This is where the magic happens, we have replaced the incoming maxOverScrollY with our own custom variable mMaxYOverscrollDistance;
- return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, mMaxYOverscrollDistance, isTouchEvent);
- }
- }
Java程式碼
- public class MainActivity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- LinearLayout linearLayout = new LinearLayout(this);
- linearLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
- setContentView(linearLayout);
- BounceListView bounceListView = new BounceListView(this);
- String[] data = new String[30];
- for (int i = 0; i < data.length; i++) {
- data[i] = "回彈效果 " + i;
- }
- ArrayAdapter<String> arrayAdapter =
- new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, data);
- bounceListView.setAdapter(arrayAdapter);
- linearLayout.addView(bounceListView);
- }
- }
相關推薦
Android ListView滑動回彈——overScrollBy
註解 /** * Scroll the view with standard behavior for scrolling beyond the normal * content boundaries. Views that call this met
Android滑動回彈效果
原理: addHeaderView裡做的事: 1.測量出header的寬高,呼叫了measureView方法 2.設定LayoutParams,寬:MATCH_PARENT,高:10 3.設定topMargin的值為負的header的高度,即將header隱藏在螢幕最上方
Android使用CoordinatorLayout與AppBarLayout時快速滑動回彈問題
在使用CoordinatorLayout時,套用AppBarLayout,實現滑動效果如果快速滑動,頂部就會出現回彈問題。解決方法:重寫AppBarLayout.Behavior程式碼如下:1.public class TestBehavior extends AppBarL
使用原生js封裝webapp滑動效果(慣性滑動、滑動回彈)
pla 手指 測試 距離 ack cti 時間 .proto start PC 移動端兼容 IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+ 慣性助動,滑動回彈 門面模式 window.onload = function() { /*測試
Android ListView滑動刪除及響應事件詳解
源代碼下載 引用 example imp cor toast don float 發現 目標:實現類似QQ,微信的消息列表滑動刪除 具體操作: 1. 主頁面布局 首先在布局文件(本例是activity_main.xml)中引入ListView控件,並指定id(如下代
Android Listview滑動時不載入資料,停下來時載入資料,讓App更優
資料來源配置(Adapter) package com.zhengsonglan.listview_loading.adapter; import android.content.Context; import android.view.LayoutInflate
Android ListView長按彈出對話方塊
ListView長按彈出對話方塊可以用PopupWindow實現 今天記錄的是重寫onCreateContextMenu和onContextItemSelected實現彈出對話方塊,比前者簡單很多
移動端阻止瀏覽器中預設元素滑動回彈效果(橡皮筋效果)
在js檔案中加如下程式碼: document.addEventListener('touchstart',function(e){ e.preventDefault(); //
Android 帶阻尼回彈效果的ScorllView
import android.content.Context; import android.graphics.Color; import android.graphics.Rect; import android.util.AttributeSet; impo
Android ListView長按彈出CheckBox,實現全選,反選,批量刪除功能
ListView長按彈出CheckBox,實現全選,反選,批量刪除功能. 主佈局:activity_main <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="
android ListView 仿IOS 回彈效果
最近看IOS的下拉效果感覺很不錯,當拉倒最上面和最下面的時候繼續拉動會有緩衝,想在android裡面也做一個,到網上到處找,沒有找到好的方法,據說android新的API對ListView有這樣的支援,感覺不是特別好用。 自己利用scroller實現了一下,廢話不多說了直接
Android超簡單實現listview上下拉伸回彈動畫效果
超簡單實現listview上下拉伸回彈動畫效果 希望能幫到大家,共同進步 import android.annotation.SuppressLint; import android.content.Context; import android.uti
Android中自定義仿IOS回彈效果的ListView
ios中有一個控制元件回彈的效果,比如listview ,拉動到第一條或者最後一條資料的時候,還可以繼續拉動,鬆手就回彈到原來位置,很贊,其實在android中實現起來也非常簡單,我們只需要重寫listview的下面兩個 方法即可 先上圖 @Override pub
Android 自定義ScrollView 支援慣性滑動,慣性回彈效果。支援上拉載入更多
先講下原理: ScrollView的子View 主要分為3部分:head頭部,滾動內容,fooder底部 我們實現慣性滑動,以及回彈,都是靠超過head或者fooder 就重新滾動到 ,內容的頂部或者底部。 之前看了Pulltorefresh 他是通過不斷改變 head或
Android實現ListView阻尼式(下拉回彈)效果
最近想模仿小米MIUI V5簡訊裡面的一個功能——私密簡訊,它的入口在簡訊列表,列表往下拉到1/3左右,我用Eclipse上的工具截了圖,包括該結構的佈局,如下圖: 從它的UI結構可以看出,用的是層疊結構,即將ListView和一個普通View(取名叫privateEn
ios 下防止整個網頁滑動(阻尼回彈 . 瞞天過海,騙IOS,把阻尼回彈限制在滾動區div內
list ont 16px 一點 width sta 常見 沒有 手機app 下面是一個手機APP頁面,分成上中下三部分,最上面和最下面是固定的,中間可以滾動。這是常見的APP布局方式。 <style> .box{ overflow: auto; -
Android關於CoordinatorLayout和ListView滑動衝突的解決(上滑ToolBar隱藏,下滑出現)
最近專案中使用到了CoordinatorLayout這種佈局方式,搭配RecycleView,實現起來比較簡單,而且不用自己處理滑動事件,但是改為了ListView後發生了滑動衝突. 所以想到了以下解決方案: 1.使用事件分發,當ListView在Y軸滑動時,將事件交給C
android listview巢狀時,顯示不全和不能滑動的解決
在listview巢狀listview的過程中,如果我們不寫一點特殊的操作的話,可能子listview會顯示不全,並且無法滑動,那麼應該怎麼解決呢 1.子listview繼承listview,然後重寫onmeasure方法,在裡面手動的去計算高度,然後傳給super方法,這
webapp在ios中簡單實現滑動,回彈,加速等效果
-webkit-overflow-scrolling來自safari原生控制元件的實現,工作原理是:在有這個屬性的容器上,系統會建立了一個uiscrollview,應用於該元素並將之作為渲染物件,從而為我們實現體驗流暢的觸屏滑動 在Ios上的表現結果令人十分滿意,並且網
Android重寫ScrollView實現上拉下拉回彈,下拉頭部放大功能
效果圖: 自定義ScrollView: public class MyScrollView extends ScrollView { //----頭部收縮屬性-------- // 記錄首次按下位置 private float mFirstPositi