2014年5月7日水曜日

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

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



これを表示しないようにするには、View.setOverScrollMode()で、OVER_SCROLL_NEVERを指定します。(デフォルトでは、OVER_SCROLL_ALWAYSになっています。) listView.setOverScrollMode(View.OVER_SCROLL_NEVER);
setOverScrollMode()はAPI Level 9からなので、ViewPagerをAPI Level 9未満でも使う場合は、ViewCompat.setOverScrollMode()を使います。 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 840 @Override 841 public void setOverScrollMode(int mode) { 842 if (mode != OVER_SCROLL_NEVER) { 843 if (mEdgeGlowTop == null) { 844 Context context = getContext(); 845 mEdgeGlowTop = new EdgeEffect(context); 846 mEdgeGlowBottom = new EdgeEffect(context); 847 } 848 } else { 849 mEdgeGlowTop = null; 850 mEdgeGlowBottom = null; 851 } 852 super.setOverScrollMode(mode); 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 2169 @Override 2170 public void draw(Canvas canvas) { 2171 super.draw(canvas); 2172 boolean needsInvalidate = false; 2173 2174 final int overScrollMode = ViewCompat.getOverScrollMode(this); 2175 if (overScrollMode == ViewCompat.OVER_SCROLL_ALWAYS || 2176 (overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS && 2177 mAdapter != null && mAdapter.getCount() > 1)) { 2178 if (!mLeftEdge.isFinished()) { 2179 final int restoreCount = canvas.save(); 2180 final int height = getHeight() - getPaddingTop() - getPaddingBottom(); 2181 final int width = getWidth(); 2182 2183 canvas.rotate(270); 2184 canvas.translate(-height + getPaddingTop(), mFirstOffset * width); 2185 mLeftEdge.setSize(height, width); 2186 needsInvalidate |= mLeftEdge.draw(canvas); 2187 canvas.restoreToCount(restoreCount); 2188 } 2189 if (!mRightEdge.isFinished()) { 2190 final int restoreCount = canvas.save(); 2191 final int width = getWidth(); 2192 final int height = getHeight() - getPaddingTop() - getPaddingBottom(); 2193 2194 canvas.rotate(90); 2195 canvas.translate(-getPaddingTop(), -(mLastOffset + 1) * width); 2196 mRightEdge.setSize(height, width); 2197 needsInvalidate |= mRightEdge.draw(canvas); 2198 canvas.restoreToCount(restoreCount); 2199 } 2200 } else { 2201 mLeftEdge.finish(); 2202 mRightEdge.finish(); 2203 } 2204 2205 if (needsInvalidate) { 2206 // Keep animating 2207 ViewCompat.postInvalidateOnAnimation(this); 2208 } 2209 }



0 件のコメント:

コメントを投稿