/******************************************************************************* * Copyright 2012-present Pixate, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.pixate.freestyle.styling.stylers; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import android.widget.ListView; import com.pixate.freestyle.annotations.PXDocProperty; import com.pixate.freestyle.annotations.PXDocStyler; import com.pixate.freestyle.styling.PXDeclaration; import com.pixate.freestyle.styling.stylers.PXStylerContext.OverscrollStyle; import com.pixate.freestyle.util.PXDrawableUtil; import com.pixate.freestyle.util.PXLog; // @formatter:off /** * -distance: length * -header: paint * -footer: paint */ // @formatter:on @PXDocStyler(properties = { @PXDocProperty(name = "distance", syntax = "<length>"), @PXDocProperty(name = "header", syntax = "<paint>"), @PXDocProperty(name = "footer", syntax = "<paint>"), }) public class PXOverscrollStyler extends PXStylerBase { private static Map<String, PXDeclarationHandler> handlers; private static PXOverscrollStyler instance; public synchronized static PXOverscrollStyler getInstance() { if (instance == null) { instance = new PXOverscrollStyler(null); } return instance; } public PXOverscrollStyler(PXStylerInvocation invocation) { super(invocation); } @Override public Map<String, PXDeclarationHandler> getDeclarationHandlers() { synchronized (PXOverscrollStyler.class) { if (handlers == null) { handlers = new HashMap<String, PXDeclarationHandler>(3); handlers.put("distance", new PXDeclarationHandler() { @Override public void process(PXDeclaration declaration, PXStylerContext stylerContext) { stylerContext.setOverscrollDistance(declaration.getFloatValue(stylerContext .getDisplayMetrics())); } }); handlers.put("footer", new PXDeclarationHandler() { @Override public void process(PXDeclaration declaration, PXStylerContext stylerContext) { stylerContext.setOverscrollFooter(declaration.getPaintValue()); } }); handlers.put("header", new PXDeclarationHandler() { @Override public void process(PXDeclaration declaration, PXStylerContext stylerContext) { stylerContext.setOverscrollHeader(declaration.getPaintValue()); } }); } return handlers; } } /* * (non-Javadoc) * @see * com.pixate.freestyle.styling.stylers.PXStylerBase#applyStylesWithContext * (com.pixate.freestyle.styling.stylers.PXStylerContext) */ @Override public void applyStylesWithContext(PXStylerContext stylerContext) { // view.setOverScrollMode(ListView.OVER_SCROLL_ALWAYS); // needed? OverscrollStyle overscrollStyle = stylerContext.getOverscrollStyle(); if (overscrollStyle != null) { // Get the ListView through the virtual styleable. ListView view = (ListView) stylerContext.getStyleable(); // Apply the overscroll setOverscrollDistance(view, overscrollStyle.distance); int viewWidth = view.getWidth(); if (overscrollStyle.header != null) { view.setOverscrollHeader(PXDrawableUtil.createDrawable((viewWidth != 0) ? viewWidth : overscrollStyle.distance, overscrollStyle.distance, overscrollStyle.header)); } if (overscrollStyle.footer != null) { view.setOverscrollFooter(PXDrawableUtil.createDrawable((viewWidth != 0) ? viewWidth : overscrollStyle.distance, overscrollStyle.distance, overscrollStyle.footer)); } } super.applyStylesWithContext(stylerContext); } /** * Set the overscroll distance using reflection. By default, Android sets * this distance to zero, and unless we override the ListView class there is * no other way to update that value. * * @param view * @param distance */ private void setOverscrollDistance(ListView view, int distance) { try { Class<?> c = view.getClass().getSuperclass(); Field field = c.getDeclaredField("mOverscrollDistance"); field.setAccessible(true); field.setInt(view, distance); } catch (NoSuchFieldException e) { if (PXLog.isLogging()) { PXLog.v(PXOverscrollStyler.class.getSimpleName(), e, "Could not set the mOverscrollDistance"); } } catch (IllegalAccessException e) { if (PXLog.isLogging()) { PXLog.v(PXOverscrollStyler.class.getSimpleName(), e, "Could not set the mOverscrollDistance"); } } } }