2014年5月7日水曜日

Android 端までスクロールしたときのエフェクトを消す

ListViewやScrollView、ViewPagerなどで端までスクロールすると、水色(KitKat以前)や灰色(KitKat以後)のエフェクトが表示されます。



これを表示しないようにするには、View.setOverScrollMode()で、OVER_SCROLL_NEVERを指定します。(デフォルトでは、OVER_SCROLL_ALWAYSになっています。)
  1. listView.setOverScrollMode(View.OVER_SCROLL_NEVER);  

setOverScrollMode()はAPI Level 9からなので、ViewPagerをAPI Level 9未満でも使う場合は、ViewCompat.setOverScrollMode()を使います。
  1. ViewCompat.setOverScrollMode(viewPager, ViewCompat.OVER_SCROLL_NEVER);  


-------

解説

端のエフェクトはEdgeEffect(http://tools.oesf.biz/android-4.4.2_r1.0/xref/frameworks/base/core/java/android/widget/EdgeEffect.java)というクラスが担っています。

AbsListViewでは、OVER_SCROLL_NEVERが指定されると、EdgeEffect用の変数にnullを指定するようになっています。

http://tools.oesf.biz/android-4.4.2_r1.0/xref/frameworks/base/core/java/android/widget/AbsListView.java#840
  1. 840     @Override  
  2. 841     public void setOverScrollMode(int mode) {  
  3. 842         if (mode != OVER_SCROLL_NEVER) {  
  4. 843             if (mEdgeGlowTop == null) {  
  5. 844                 Context context = getContext();  
  6. 845                 mEdgeGlowTop = new EdgeEffect(context);  
  7. 846                 mEdgeGlowBottom = new EdgeEffect(context);  
  8. 847             }  
  9. 848         } else {  
  10. 849             mEdgeGlowTop = null;  
  11. 850             mEdgeGlowBottom = null;  
  12. 851         }  
  13. 852         super.setOverScrollMode(mode);  
  14. 853     }  
ScrollView、HorizontalScrollViewでも同じようになっています。

ViewPagerでは、描画時にOverScrollModeを取得して、OVER_SCROLL_NEVERの場合はエフェクトを描画しないようになっています。

http://tools.oesf.biz/android-4.4.2_r1.0/xref/frameworks/support/v4/java/android/support/v4/view/ViewPager.java#2169
  1. 2169     @Override  
  2. 2170     public void draw(Canvas canvas) {  
  3. 2171         super.draw(canvas);  
  4. 2172         boolean needsInvalidate = false;  
  5. 2173   
  6. 2174         final int overScrollMode = ViewCompat.getOverScrollMode(this);  
  7. 2175         if (overScrollMode == ViewCompat.OVER_SCROLL_ALWAYS ||  
  8. 2176                 (overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS &&  
  9. 2177                         mAdapter != null && mAdapter.getCount() > 1)) {  
  10. 2178             if (!mLeftEdge.isFinished()) {  
  11. 2179                 final int restoreCount = canvas.save();  
  12. 2180                 final int height = getHeight() - getPaddingTop() - getPaddingBottom();  
  13. 2181                 final int width = getWidth();  
  14. 2182   
  15. 2183                 canvas.rotate(270);  
  16. 2184                 canvas.translate(-height + getPaddingTop(), mFirstOffset * width);  
  17. 2185                 mLeftEdge.setSize(height, width);  
  18. 2186                 needsInvalidate |= mLeftEdge.draw(canvas);  
  19. 2187                 canvas.restoreToCount(restoreCount);  
  20. 2188             }  
  21. 2189             if (!mRightEdge.isFinished()) {  
  22. 2190                 final int restoreCount = canvas.save();  
  23. 2191                 final int width = getWidth();  
  24. 2192                 final int height = getHeight() - getPaddingTop() - getPaddingBottom();  
  25. 2193   
  26. 2194                 canvas.rotate(90);  
  27. 2195                 canvas.translate(-getPaddingTop(), -(mLastOffset + 1) * width);  
  28. 2196                 mRightEdge.setSize(height, width);  
  29. 2197                 needsInvalidate |= mRightEdge.draw(canvas);  
  30. 2198                 canvas.restoreToCount(restoreCount);  
  31. 2199             }  
  32. 2200         } else {  
  33. 2201             mLeftEdge.finish();  
  34. 2202             mRightEdge.finish();  
  35. 2203         }  
  36. 2204   
  37. 2205         if (needsInvalidate) {  
  38. 2206             // Keep animating  
  39. 2207             ViewCompat.postInvalidateOnAnimation(this);  
  40. 2208         }  
  41. 2209     }  




0 件のコメント:

コメントを投稿