Advertisement
pflammertsma

CustomGlowListView

Feb 27th, 2012
574
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.52 KB | None | 0 0
  1. import android.content.Context;
  2. import android.graphics.Rect;
  3. import android.os.AsyncTask;
  4. import android.util.AttributeSet;
  5. import android.view.GestureDetector;
  6. import android.view.GestureDetector.SimpleOnGestureListener;
  7. import android.view.MotionEvent;
  8. import android.view.ViewGroup;
  9. import android.widget.AbsListView;
  10. import android.widget.GridView;
  11. import android.widget.ImageView;
  12. import android.widget.ImageView.ScaleType;
  13. import android.widget.ListView;
  14. import android.widget.RelativeLayout;
  15.  
  16. public class CustomGlowListView extends RelativeLayout {
  17.  
  18.     private final ImageView underscrollEdge;
  19.     private final ImageView underscrollGlow;
  20.     private final ImageView overscrollGlow;
  21.     private final ImageView overscrollEdge;
  22.     private AbsListView listView;
  23.  
  24.     private final static float MAX_EDGE_SIZE = 11f;
  25.     private final static float MAX_GLOW_SIZE = 93f;
  26.  
  27.     protected static final float FLING_BUMP_HEIGHT = 160;
  28.  
  29.     private float scrollDistanceSinceBoundary = 0;
  30.  
  31.     private final Rect paddingRectangle = new Rect();
  32.  
  33.     GestureDetector listViewGestureDetector;
  34.  
  35.     // Gives the option of short circuiting the overscroll glow fade (Such as by
  36.     // scrolling away from the overscrolled edge)
  37.     boolean interruptFade = false;
  38.  
  39.     private GlowShrinker animator;
  40.  
  41.     public CustomGlowListView(Context context, AttributeSet attrs) {
  42.         super(context, attrs);
  43.  
  44.         listViewGestureDetector = new GestureDetector(
  45.                 new ListViewGestureDetector());
  46.  
  47.         if (getTag() == null
  48.                 || getTag().toString().equalsIgnoreCase("ListView")) {
  49.             listView = new ListView(context) {
  50.                 @Override
  51.                 protected void onOverScrolled(int scrollX, int scrollY,
  52.                         boolean clampedX, boolean clampedY) {
  53.                     if (listIsAtTop()) {
  54.                         scrollDistanceSinceBoundary += FLING_BUMP_HEIGHT;
  55.                         scaleEdges(underscrollEdge, underscrollGlow,
  56.                                 scrollDistanceSinceBoundary);
  57.                         reset();
  58.                     } else if (listIsAtBottom()) {
  59.                         scrollDistanceSinceBoundary += FLING_BUMP_HEIGHT;
  60.                         scaleEdges(overscrollEdge, overscrollGlow,
  61.                                 scrollDistanceSinceBoundary);
  62.                         reset();
  63.                     }
  64.                 }
  65.             };
  66.         } else if (getTag().toString().equalsIgnoreCase("GridView")) {
  67.             listView = new GridView(context, attrs);
  68.             ((GridView) listView).getSelector().getPadding(paddingRectangle);
  69.         }
  70.         listView.setId(android.R.id.list);
  71.         if (Integer.parseInt(Build.VERSION.SDK) >= 9) {
  72.             listView.setOverScrollMode(OVER_SCROLL_NEVER);
  73.         }
  74.         addView(listView, new RelativeLayout.LayoutParams(
  75.                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
  76.  
  77.         underscrollEdge = new ImageView(context);
  78.         underscrollEdge.setImageResource(R.drawable.underscroll_edge);
  79.         underscrollEdge.setScaleType(ScaleType.FIT_XY);
  80.         underscrollGlow = new ImageView(context);
  81.         underscrollGlow.setImageResource(R.drawable.underscroll_glow);
  82.         underscrollGlow.setScaleType(ScaleType.FIT_XY);
  83.         overscrollGlow = new ImageView(context);
  84.         overscrollGlow.setImageResource(R.drawable.overscroll_glow);
  85.         overscrollGlow.setScaleType(ScaleType.FIT_XY);
  86.         overscrollEdge = new ImageView(context);
  87.         overscrollEdge.setImageResource(R.drawable.overscroll_edge);
  88.         overscrollEdge.setScaleType(ScaleType.FIT_XY);
  89.  
  90.         addView(underscrollGlow, getWideLayout(ALIGN_PARENT_TOP));
  91.         addView(underscrollEdge, getWideLayout(ALIGN_PARENT_TOP));
  92.  
  93.         addView(overscrollGlow, getWideLayout(ALIGN_PARENT_BOTTOM));
  94.         addView(overscrollEdge, getWideLayout(ALIGN_PARENT_BOTTOM));
  95.     }
  96.  
  97.     @Override
  98.     public boolean dispatchTouchEvent(MotionEvent ev) {
  99.         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
  100.             interruptFade = true;
  101.         }
  102.         listViewGestureDetector.onTouchEvent(ev);
  103.  
  104.         if (ev.getAction() == MotionEvent.ACTION_UP) {
  105.             reset();
  106.         }
  107.         return super.dispatchTouchEvent(ev);
  108.     }
  109.  
  110.     private RelativeLayout.LayoutParams getWideLayout(int alignment) {
  111.         RelativeLayout.LayoutParams returnLayout = new RelativeLayout.LayoutParams(
  112.                 LayoutParams.MATCH_PARENT, 0);
  113.         returnLayout.addRule(alignment);
  114.         return returnLayout;
  115.     }
  116.  
  117.     public void reset() {
  118.         interruptFade = false;
  119.         if (animator != null && !animator.isFinished()) {
  120.             animator.cancel(true);
  121.         }
  122.         animator = new GlowShrinker();
  123.         animator.execute(scrollDistanceSinceBoundary);
  124.         scrollDistanceSinceBoundary = 0;
  125.     }
  126.  
  127.     private boolean listIsAtTop() {
  128.         if (listView.getChildCount() == 0) {
  129.             // No action for empty lists
  130.             return false;
  131.         }
  132.         if (listView.getFirstVisiblePosition() > 0) {
  133.             return false;
  134.         }
  135.         return listView.getChildAt(0).getTop() - paddingRectangle.top == 0;
  136.     }
  137.  
  138.     private boolean listIsAtBottom() {
  139.         if (listView.getChildCount() == 0) {
  140.             // No action for empty lists
  141.             return false;
  142.         }
  143.         int index = listView.getChildCount() - 1;
  144.         if (listView.getLastVisiblePosition() < index) {
  145.             return false;
  146.         }
  147.         return listView.getChildAt(index).getBottom()
  148.                 + paddingRectangle.bottom == listView.getHeight();
  149.     }
  150.  
  151.     private class ListViewGestureDetector extends SimpleOnGestureListener {
  152.         @Override
  153.         public boolean onScroll(MotionEvent downMotionEvent,
  154.                 MotionEvent currentMotionEvent, float distanceX, float distanceY) {
  155.             float distanceTraveled = downMotionEvent.getY()
  156.                     - currentMotionEvent.getY();
  157.             boolean atTop = listIsAtTop();
  158.             boolean atBottom = listIsAtBottom();
  159.  
  160.             if (atTop && distanceTraveled < 0) {
  161.                 // At top and finger moving down
  162.                 scrollDistanceSinceBoundary -= distanceY;
  163.                 scaleEdges(underscrollEdge, underscrollGlow,
  164.                         scrollDistanceSinceBoundary);
  165.             } else if (atTop && distanceTraveled > 0
  166.                     && scrollDistanceSinceBoundary > 0) {
  167.                 // At top and finger moving up while in overscroll
  168.                 scrollDistanceSinceBoundary -= distanceY;
  169.                 scaleEdges(underscrollEdge, underscrollGlow,
  170.                         scrollDistanceSinceBoundary);
  171.             } else if (atBottom && distanceTraveled > 0) {
  172.                 // At bottom and finger moving up
  173.                 scrollDistanceSinceBoundary += distanceY;
  174.                 scaleEdges(overscrollEdge, overscrollGlow,
  175.                         scrollDistanceSinceBoundary);
  176.             } else if (atBottom && distanceTraveled < 0
  177.                     && scrollDistanceSinceBoundary > 0) {
  178.                 // At bottom and finger moving up while in overscroll
  179.                 scrollDistanceSinceBoundary += distanceY;
  180.                 scaleEdges(overscrollEdge, overscrollGlow,
  181.                         scrollDistanceSinceBoundary);
  182.             } else if (scrollDistanceSinceBoundary != 0) {
  183.                 // Neither over scrolling or under scrolling but was at last
  184.                 // check. Reset both graphics.
  185.                 reset();
  186.             }
  187.  
  188.             return false;
  189.         }
  190.  
  191.     }
  192.  
  193.     private class GlowShrinker extends AsyncTask<Float, Integer, Void> {
  194.         ImageView glow;
  195.         ImageView edge;
  196.  
  197.         private final int SHRINK_SPEED = 4;
  198.         private final int SHRINK_INCREMENT = 50;
  199.  
  200.         private boolean finished;
  201.  
  202.         @Override
  203.         protected void onPreExecute() {
  204.             if (underscrollGlow.getHeight() > 0) {
  205.                 glow = underscrollGlow;
  206.                 edge = underscrollEdge;
  207.             } else if (overscrollGlow.getHeight() > 0) {
  208.                 glow = overscrollGlow;
  209.                 edge = overscrollEdge;
  210.             } else {
  211.                 return;
  212.             }
  213.         }
  214.  
  215.         @Override
  216.         protected Void doInBackground(Float... scrollDistanceSinceBoundary) {
  217.             if (glow != null && edge != null) {
  218.                 int currentSize = (int) scrollDistanceSinceBoundary[0]
  219.                         .floatValue();
  220.                 int shrinkRate = currentSize / SHRINK_INCREMENT;
  221.  
  222.                 for (int i = 0; i < SHRINK_INCREMENT; i++) {
  223.                     if (isCancelled()) {
  224.                         break;
  225.                     }
  226.                     if (interruptFade) {
  227.                         publishProgress(0);
  228.                         return null;
  229.                     }
  230.                     currentSize -= shrinkRate;
  231.                     publishProgress(currentSize);
  232.  
  233.                     try {
  234.                         Thread.sleep(SHRINK_SPEED);
  235.                     } catch (InterruptedException e) {
  236.                     }
  237.                 }
  238.             }
  239.             return null;
  240.         }
  241.  
  242.         @Override
  243.         protected void onProgressUpdate(Integer... values) {
  244.             CustomGlowListView.scaleEdges(edge, glow, values[0]);
  245.         }
  246.  
  247.         @Override
  248.         protected void onPostExecute(Void result) {
  249.             if (glow != null && edge != null) {
  250.                 CustomGlowListView.scaleEdges(edge, glow, 0);
  251.             }
  252.             finished = true;
  253.         }
  254.  
  255.         public boolean isFinished() {
  256.             return finished;
  257.         }
  258.  
  259.     }
  260.  
  261.     private static void scaleEdges(ImageView scrollEdge, ImageView scrollGlow,
  262.             float scrollBy) {
  263.         float edgeSize = scrollBy / 20;
  264.         float glowSize = scrollBy / 2;
  265.         if (edgeSize > MAX_EDGE_SIZE) {
  266.             edgeSize = MAX_EDGE_SIZE;
  267.         }
  268.         if (glowSize > MAX_GLOW_SIZE) {
  269.             glowSize = MAX_GLOW_SIZE;
  270.         }
  271.         setHeight(scrollEdge, edgeSize);
  272.         setHeight(scrollGlow, glowSize);
  273.     }
  274.  
  275.     private static void setHeight(ImageView viewIn, float height) {
  276.         ViewGroup.LayoutParams params = viewIn.getLayoutParams();
  277.         params.height = (int) height;
  278.         viewIn.setLayoutParams(params);
  279.     }
  280.  
  281.     public AbsListView getListView() {
  282.         return listView;
  283.     }
  284. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement