這個網上總結的很多,見android 關於 clipToPadding 和 clipChildren區別和作用
最近遇到的一處android ui問題最終使用clipToPadding得到了完美的解決,下面談下個人對clipToPadding的理解。
- 這個是ViewGroup的屬性,View是沒有的
- clipToPadding必須與paddingTop等屬性一起用,不然沒有任何意義
- 默認的值是true,即padding範圍內子控件不做任何layout和draw的動作,RecyclerView等邊界處的顯示效果也是在padding範圍外的。
- 如果設置爲false,那麼子控件layout任然是在padding外的(不然padding還有啥意義),draw當然也是在padding外的,這個是一般情況。如果子控件有任何位移動畫的話,這個值爲false的意義就有了,它在padding範圍內依然會顯示!!!
- 網上我搜索到的例子全部是和RecyclerView,listView或者是ViewPager有關的,這個是clipToPadding使用最廣泛的場景。即在列表組件頭部和尾部添加padding,如果是直接加padding的話,可以看到就是把RecyclerView頭部和尾部削掉,拖動的時候padding範圍內是沒有任何顯示的,拖動到底的動畫效果也是顯示在padding範圍外的。當設置clipToPadding爲false的時候哦,設置padding的效果其實就是相當於設置了headView和FooterView,滑動到底的時候纔有padding,其餘的顯示和拖動padding範圍內也是佔據的,這個是大多數期望的效果。
下面看下RecyclerView的源碼就很清楚了:
@Override
public void setClipToPadding(boolean clipToPadding) {
if (clipToPadding != mClipToPadding) {
invalidateGlows();
}
mClipToPadding = clipToPadding;
super.setClipToPadding(clipToPadding);
if (mFirstLayoutComplete) {
requestLayout();
}
}
除了調用super的方法外,還用成員變量mClipToPadding保存了設置的值
void ensureTopGlow() {
if (mTopGlow != null) {
return;
}
mTopGlow = mEdgeEffectFactory.createEdgeEffect(this, EdgeEffectFactory.DIRECTION_TOP);
if (mClipToPadding) {
mTopGlow.setSize(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
getMeasuredHeight() - getPaddingTop() - getPaddingBottom());
} else {
mTopGlow.setSize(getMeasuredWidth(), getMeasuredHeight());
}
}
top邊界效果,mClipToPadding值爲true的話size要考慮4個padding的限制,而爲false的話就不用考慮了
public void draw(Canvas c) {
super.draw(c);
...
if (mTopGlow != null && !mTopGlow.isFinished()) {
final int restore = c.save();
if (mClipToPadding) {
c.translate(getPaddingLeft(), getPaddingTop());
}
needsInvalidate |= mTopGlow != null && mTopGlow.draw(c);
c.restoreToCount(restore);
}
...
}
draw的代碼,只關心mTopGlow的處理,mClipToPadding爲true的話要繪製的時候要依據padding做平移,而爲false的話則不用考慮,這樣邊界效果雖然設置了padding,顯示的時候卻不用考慮padding,這也就是mClipToPadding的意義啊。
同理在拖動的時候,內容依然是可以在padding範圍內顯示的,好像沒有padding一樣。clipToPadding就好像是針對列表組件特定的一樣,對於普通的ViewGroup並無多大意義。