1. 程式人生 > >Android:自定義滾動邊緣(EdgeEffect)效果

Android:自定義滾動邊緣(EdgeEffect)效果

原文

0

Android可滾動控制元件(GridView、ListView、ScrollView等)當用戶滾動到頭的時候會有個邊緣反饋效果,在4.0上預設為Holo藍色效果。  如果您的App自定義了主題顏色,比如Google Play Music的橘黃色。 那麼在滾動內容控制元件還是用預設的Holo藍色邊緣效果看起來可能不太協調。這個時候就需要自定義邊緣效果了。

邊緣效果在Android系統中是通過 EdgeEffect 類來實現的,在該類的的建構函式中使用兩個系統圖片來繪製邊緣效果:

final Resources res = context.getResources();
        mEdge = res.getDrawable(R.drawable.overscroll_edge);
        mGlow = res.getDrawable(R.drawable.overscroll_glow);

4.0預設的這兩個圖片如下(點選連結檢視圖片):

所以要實現自定義邊緣效果,只需要hack系統在獲取這兩個圖片的時候使用您App提供的圖片即可。 

Android系統的App是通過ContextWrapper類來獲取Resources類,然後通過Resources類來獲取各種資源。所以通過自定義這兩個類並把自定義的類應用到這些滾動控制元件中即可。

首先自定義Resources類,在該類中如果判斷需要獲取上面這兩個邊緣效果圖片,就返回自定義的圖片(ResourcesEdgeEffect.java):

public class ResourcesEdgeEffect extends Resources
{
private int overscroll_edge = getPlatformDrawableId("overscroll_edge"); private int overscroll_glow = getPlatformDrawableId("overscroll_glow"); public ResourcesEdgeEffect(AssetManager assets, DisplayMetrics metrics, Configuration config) { super(assets, metrics, config); } private int getPlatformDrawableId(String name) { try
{ int i = ((Integer) Class.forName("com.android.internal.R$drawable").getField(name).get(null)).intValue(); return i; } catch (ClassNotFoundException e) { Log.e("[ContextWrapperEdgeEffect].getPlatformDrawableId()", "Cannot find internal resource class"); return 0; } catch (NoSuchFieldException e1) { Log.e("[ContextWrapperEdgeEffect].getPlatformDrawableId()", "Internal resource id does not exist: " + name); return 0; } catch (IllegalArgumentException e2) { Log.e("[ContextWrapperEdgeEffect].getPlatformDrawableId()", "Cannot access internal resource id: " + name); return 0; } catch (IllegalAccessException e3) { Log.e("[ContextWrapperEdgeEffect].getPlatformDrawableId()", "Cannot access internal resource id: " + name); } return 0; } public Drawable getDrawable(int resId) throws Resources.NotFoundException { if (resId == this.overscroll_edge) return ContextWrapperEdgeEffect.this.getBaseContext().getResources().getDrawable(R.drawable.overscroll_edge); if (resId == this.overscroll_glow) return ContextWrapperEdgeEffect.this.getBaseContext().getResources().getDrawable(R.drawable.overscroll_glow); return super.getDrawable(resId); } }

然後自定義一個ContextWrapper類(ContextWrapperEdgeEffect.java):

public class ContextWrapperEdgeEffect extends ContextWrapper {

private static ResourcesEdgeEffect RES_EDGE_EFFECT;

public ContextWrapperEdgeEffect(Context context) {
super(context);
Resources resources = context.getResources();
if (RES_EDGE_EFFECT == null)
RES_EDGE_EFFECT = new ResourcesEdgeEffect(resources.getAssets(), resources.getDisplayMetrics(), resources.getConfiguration());
}
        //返回自定義的Resources
public Resources getResources() {
return RES_EDGE_EFFECT;
}
}

最後再自定義App中使用到的滾動控制元件,把Context物件替換為前面自定義的ContextWrapperEdgeEffect類即可(如下是GridView的示例):

public class GridView extends android.widget.GridView {

public GridView(Context context, AttributeSet attrs) {
super(new ContextWrapperEdgeEffect(context), attrs);
}

public GridView(Context context, AttributeSet attrs, int defStyle) {
super(new ContextWrapperEdgeEffect(context), attrs, defStyle);
}

}

然後讓您的UE同學按照Holo藍色邊緣效果的兩張圖來提供自定義的兩張圖即可。

如果您感覺上面這些步驟比較繁瑣的話,也可以下載 EdgeEffectOverride  這個專案,該專案已經實現了ListView、GridView、ScrollVeiw、ExpandableListView和ViewPager類, 下載該專案只需要替換兩個圖片即可。

下圖是一個自定義紅色效果的截圖: