package com.duguang.baseanimation.ui.tab.paralloid.library1.utlis; import android.graphics.drawable.Drawable; import android.os.Build; import android.view.View; import android.view.ViewTreeObserver; import android.widget.AbsListView; import android.widget.HorizontalScrollView; import android.widget.ScrollView; import com.duguang.baseanimation.ui.tab.paralloid.library1.graphics.ParallaxDrawable; import com.duguang.baseanimation.ui.tab.paralloid.library1.measure.AbsListScrollSize; import com.duguang.baseanimation.ui.tab.paralloid.library1.transform.Transformer; /** * Created by chris on 02/10/2013 * Project: Paralloid */ public final class ParallaxHelper { public static void scrollViewBy(final View view, final int x, final int y, final float factor) { if (view == null) return; view.scrollTo((int) (x * factor), (int) (y * factor)); } public static void scrollViewBy(final View view, final int x, final int y, final Transformer transformer, final float factor) { if (view == null || transformer == null) return; final int[] transform = transformer.scroll(x, y, factor); view.scrollTo(transform[0], transform[1]); } public static void scrollParallaxDrawableBy(final ParallaxDrawable drawable, final int scrollX, final int scrollY) { if (drawable == null) return; drawable.setScrollTo(scrollX, scrollY); } public static ParallaxDrawable getParallaxDrawable(final Drawable drawable, float factor) { if(drawable == null) return null; return new ParallaxDrawable(drawable, factor); } public static void setParallaxBackground(final View view, final ParallaxDrawable parallaxDrawable) { if (view == null || parallaxDrawable == null) return; // We request the size before attaching just incase the view has drawn we can pre populate the drawable with the extra height/width requestScrollableWidthHeight(view, parallaxDrawable.getFactor(), new ParallaxHelper.ScrollableWidthHeightCallback() { @Override public void onScrollableWidthHeight(final float width, final float height) { // This is called back when the view has (hopefully) the correct width/height parallaxDrawable.setParallaxExtraWidthHeight(width, height); } }); view.setBackgroundDrawable(parallaxDrawable); fixParallaxBackgroundPreJBMR1(view, parallaxDrawable); } static void requestScrollableWidthHeight(final View view, final float multiplier, final ScrollableWidthHeightCallback callback) { if (callback == null) return; // Have we done a layout pass? if (view.getHeight() > 0 || view.getWidth() > 0) { final float[] xy = calculateScrollableWidthHeightFromView(view, multiplier); callback.onScrollableWidthHeight(xy[0], xy[1]); } else { // Call back to self when we have laid out view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { view.getViewTreeObserver().removeOnPreDrawListener(this); requestScrollableWidthHeight(view, multiplier, callback); return true; } }); } } static float[] calculateScrollableWidthHeightFromView(View view, float factor) { if (view == null) return new float[2]; if (view instanceof ScrollView) { // Get the ScrollView's only child final View child = ((ScrollView) view).getChildAt(0); return new float[]{view.getWidth(), calculateExtraScroll(view.getHeight(), child.getHeight(), factor)}; } if (view instanceof HorizontalScrollView) { // Get the ScrollView's only child final View child = ((HorizontalScrollView) view).getChildAt(0); return new float[]{calculateExtraScroll(view.getWidth(), child.getWidth(), factor), view.getHeight()}; } if (view instanceof AbsListView) { final AbsListScrollSize absListScrollSize = new AbsListScrollSize((AbsListView) view); float estimatedHeight = calculateExtraScroll( view.getHeight(), absListScrollSize.getMaxScrollY(), factor); // Log.d("Parallax", "Est Height: " + estimatedHeight); return new float[]{absListScrollSize.getMaxScrollX(), estimatedHeight}; } // Not sure what it is? Just use the width/height return new float[]{ calculateExtraScroll(view.getWidth(), view.getWidth(), factor), calculateExtraScroll(view.getHeight(), view.getHeight(), factor) }; } static float calculateExtraScroll(float parent, float child, float factor) { return parent + (child - parent) * factor; } /** * Hack to fix pre JB MR1 Kudos to @cyrilmottier * * @param view view drawable attached too. * @param drawable drawable which gets invalidated */ static void fixParallaxBackgroundPreJBMR1(final View view, final Drawable drawable) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { drawable.setCallback(new Drawable.Callback() { @Override public void invalidateDrawable(Drawable who) { view.setBackgroundDrawable(who); } @Override public void scheduleDrawable(Drawable who, Runnable what, long when) { } @Override public void unscheduleDrawable(Drawable who, Runnable what) { } }); } } static interface ScrollableWidthHeightCallback { void onScrollableWidthHeight(float width, float height); } }