BVB Source Codes

android-viewflow Show CircleFlowIndicator.java Source code

Return Download android-viewflow: download CircleFlowIndicator.java Source code - Download android-viewflow Source code - Type:.java
  1. /*
  2.  * Copyright (C) 2011 Patrik 脜kerfeldt
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *              http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. package org.taptwo.android.widget;
  17.  
  18. import android.content.Context;
  19. import android.content.res.TypedArray;
  20. import android.graphics.Canvas;
  21. import android.graphics.Paint;
  22. import android.graphics.Paint.Style;
  23. import android.os.AsyncTask;
  24. import android.util.AttributeSet;
  25. import android.view.View;
  26. import android.view.animation.Animation;
  27. import android.view.animation.Animation.AnimationListener;
  28. import android.view.animation.AnimationUtils;
  29. import org.taptwo.android.widget.viewflow.R;
  30.  
  31. /**
  32.  * A FlowIndicator which draws circles (one for each view).
  33.  * <br/>
  34.  * Available attributes are:<br/>
  35.  * <ul>
  36.  * <li>
  37.  * activeColor: Define the color used to draw the active circle (default to white)
  38.  * </li>
  39.  * <li>
  40.  * inactiveColor: Define the color used to draw the inactive circles (default to 0x44FFFFFF)
  41.  * </li>
  42.  * <li>
  43.  * inactiveType: Define how to draw the inactive circles, either stroke or fill (default to stroke)
  44.  * </li>
  45.  * <li>
  46.  * activeType: Define how to draw the active circle, either stroke or fill (default to fill)
  47.  * </li>
  48.  * <li>
  49.  * fadeOut: Define the time (in ms) until the indicator will fade out (default to 0 = never fade out)
  50.  * </li>
  51.  * <li>
  52.  * radius: Define the circle outer radius (default to 4.0)
  53.  * </li>
  54.  * <li>
  55.  * spacing: Define the circle spacing (default to 4.0)
  56.  * </li>
  57.  * <li>
  58.  * snap: If true, the 'active' indicator snaps from one page to the next; otherwise, it moves smoothly.
  59.  * </li>
  60.  * </ul>
  61.  */
  62. public class CircleFlowIndicator extends View implements FlowIndicator,
  63.                 AnimationListener {
  64.         private static final int STYLE_STROKE = 0;
  65.         private static final int STYLE_FILL = 1;
  66.  
  67.         private float mRadius = 4;
  68.         private float mRadiusInactive = 4;
  69.         private float mRadiusActive = 4;
  70.         private float spacing = 4;
  71.         private int fadeOutTime = 0;
  72.         private final Paint mPaintInactive = new Paint(Paint.ANTI_ALIAS_FLAG);
  73.         private final Paint mPaintActive = new Paint(Paint.ANTI_ALIAS_FLAG);
  74.         private ViewFlow viewFlow;
  75.         private int currentScroll = 0;
  76.         private int currentPosition = 0;
  77.         private int flowWidth = 0;
  78.         private FadeTimer timer;
  79.         public AnimationListener animationListener = this;
  80.         private Animation animation;
  81.         private boolean mCentered = false;
  82.         private boolean mSnap = false;
  83.  
  84.         /**
  85.          * Default constructor
  86.          *
  87.          * @param context
  88.          */
  89.         public CircleFlowIndicator(Context context) {
  90.                 super(context);
  91.                 initColors(0xFFFFFFFF, 0xFFFFFFFF, STYLE_FILL, STYLE_STROKE);
  92.         }
  93.  
  94.         /**
  95.          * The contructor used with an inflater
  96.          *
  97.          * @param context
  98.          * @param attrs
  99.          */
  100.         public CircleFlowIndicator(Context context, AttributeSet attrs) {
  101.                 super(context, attrs);
  102.                 // Retrieve styles attributs
  103.                 TypedArray a = context.obtainStyledAttributes(attrs,
  104.                                 R.styleable.CircleFlowIndicator);
  105.  
  106.                 // Gets the active circle type, defaulting to "fill"
  107.                 int activeType = a.getInt(R.styleable.CircleFlowIndicator_activeType,
  108.                                 STYLE_FILL);
  109.                
  110.                 int activeDefaultColor = 0xFFFFFFFF;
  111.                
  112.                 // Get a custom active color if there is one
  113.                 int activeColor = a
  114.                                 .getColor(R.styleable.CircleFlowIndicator_activeColor,
  115.                                                 activeDefaultColor);
  116.  
  117.                 // Gets the inactive circle type, defaulting to "stroke"
  118.                 int inactiveType = a.getInt(
  119.                                 R.styleable.CircleFlowIndicator_inactiveType, STYLE_STROKE);
  120.  
  121.                 int inactiveDefaultColor = 0x44FFFFFF;
  122.                 // Get a custom inactive color if there is one
  123.                 int inactiveColor = a.getColor(
  124.                                 R.styleable.CircleFlowIndicator_inactiveColor,
  125.                                 inactiveDefaultColor);
  126.  
  127.                 // Retrieve the radius
  128.                 mRadius = a.getDimension(R.styleable.CircleFlowIndicator_radius, 4.0f);
  129.                 mRadiusActive = mRadius;
  130.                 mRadiusInactive = mRadius;
  131.  
  132.                 // Retrieve the spacing
  133.                 spacing = a.getDimension(R.styleable.CircleFlowIndicator_spacing, 4.0f);
  134.                 // We want the spacing to be center-to-center
  135.                 spacing += 2 * mRadiusActive;
  136.                
  137.                 // Retrieve the fade out time
  138.                 fadeOutTime = a.getInt(R.styleable.CircleFlowIndicator_fadeOut, 0);
  139.                
  140.                 mCentered = a.getBoolean(R.styleable.CircleFlowIndicator_centered, false);
  141.  
  142.                 mSnap = a.getBoolean(R.styleable.CircleFlowIndicator_snap, false);
  143.                
  144.                 initColors(activeColor, inactiveColor, activeType, inactiveType);
  145.         }
  146.  
  147.         private void initColors(int activeColor, int inactiveColor, int activeType,
  148.                         int inactiveType) {
  149.                 // Select the paint type given the type attr
  150.                 switch (inactiveType) {
  151.                 case STYLE_FILL:
  152.                         mPaintInactive.setStyle(Style.FILL);
  153.                         break;
  154.                 default:
  155.                         mPaintInactive.setStyle(Style.STROKE);
  156.                         float strokeWidth = mPaintInactive.getStrokeWidth();
  157.                         if (strokeWidth == 0.0f) {
  158.                                 // It draws in "hairline mode", which is 1 px wide.
  159.                                 strokeWidth = 1.0f / getResources().getDisplayMetrics().density;
  160.                         }
  161.                         mRadiusInactive -= strokeWidth / 2.0f;
  162.                 }
  163.                 mPaintInactive.setColor(inactiveColor);
  164.  
  165.                 // Select the paint type given the type attr
  166.                 switch (activeType) {
  167.                 case STYLE_STROKE:
  168.                         mPaintActive.setStyle(Style.STROKE);
  169.                         float strokeWidth = mPaintInactive.getStrokeWidth();
  170.                         if (strokeWidth == 0.0f) {
  171.                                 // It draws in "hairline mode", which is 1 px wide.
  172.                                 strokeWidth = 1.0f / getResources().getDisplayMetrics().density;
  173.                         }
  174.                         mRadiusActive -= strokeWidth / 2.0f;
  175.                         break;
  176.                 default:
  177.                         mPaintActive.setStyle(Style.FILL);
  178.                 }
  179.                 mPaintActive.setColor(activeColor);
  180.         }
  181.  
  182.         /*
  183.          * (non-Javadoc)
  184.          *
  185.          * @see android.view.View#onDraw(android.graphics.Canvas)
  186.          */
  187.         @Override
  188.         protected void onDraw(Canvas canvas) {
  189.                 super.onDraw(canvas);
  190.                 int count = 3;
  191.                 if (viewFlow != null) {
  192.                         count = viewFlow.getViewsCount();
  193.                 }
  194.                
  195.                 //this is the amount the first circle should be offset to make the entire thing centered
  196.                 float centeringOffset = 0;
  197.                
  198.                 int leftPadding = getPaddingLeft();
  199.                
  200.                 // Draw stroked circles
  201.                 for (int iLoop = 0; iLoop < count; iLoop++) {
  202.                         canvas.drawCircle(leftPadding + mRadius
  203.                                         + (iLoop * spacing) + centeringOffset,
  204.                                         getPaddingTop() + mRadius, mRadiusInactive, mPaintInactive);
  205.                 }
  206.                 float cx = 0;
  207.                 if (mSnap) {
  208.                         cx = currentPosition * spacing;
  209.                 } else {
  210.                         if (flowWidth != 0) {
  211.                                 // Draw the filled circle according to the current scroll
  212.                                 cx = (currentScroll * spacing) / flowWidth;
  213.                         }
  214.                         // else, the flow width hasn't been updated yet. Draw the default position.
  215.                 }
  216.                 canvas.drawCircle(leftPadding + mRadius + cx+centeringOffset, getPaddingTop()
  217.                                 + mRadius, mRadiusActive, mPaintActive);
  218.         }
  219.  
  220.         /*
  221.          * (non-Javadoc)
  222.          *
  223.          * @see
  224.          * org.taptwo.android.widget.ViewFlow.ViewSwitchListener#onSwitched(android
  225.          * .view.View, int)
  226.          */
  227.         @Override
  228.         public void onSwitched(View view, int position) {
  229.                 currentPosition = position;
  230.                 if (mSnap) {
  231.                         setVisibility(View.VISIBLE);
  232.                         resetTimer();
  233.                         invalidate();
  234.                 }
  235.         }
  236.  
  237.         /*
  238.          * (non-Javadoc)
  239.          *
  240.          * @see
  241.          * org.taptwo.android.widget.FlowIndicator#setViewFlow(org.taptwo.android
  242.          * .widget.ViewFlow)
  243.          */
  244.         @Override
  245.         public void setViewFlow(ViewFlow view) {
  246.                 resetTimer();
  247.                 viewFlow = view;
  248.                 flowWidth = viewFlow.getChildWidth();
  249.                 invalidate();
  250.         }
  251.  
  252.         /*
  253.          * (non-Javadoc)
  254.          *
  255.          * @see org.taptwo.android.widget.FlowIndicator#onScrolled(int, int, int,
  256.          * int)
  257.          */
  258.         @Override
  259.         public void onScrolled(int h, int v, int oldh, int oldv) {
  260.                 currentScroll = h;
  261.                 flowWidth = viewFlow.getChildWidth();
  262.                 if (!mSnap) {
  263.                         setVisibility(View.VISIBLE);
  264.                         resetTimer();
  265.                         invalidate();
  266.                 }
  267.         }
  268.  
  269.         /*
  270.          * (non-Javadoc)
  271.          *
  272.          * @see android.view.View#onMeasure(int, int)
  273.          */
  274.         @Override
  275.         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  276.                 setMeasuredDimension(measureWidth(widthMeasureSpec),
  277.                                 measureHeight(heightMeasureSpec));
  278.         }
  279.  
  280.         /**
  281.          * Determines the width of this view
  282.          *
  283.          * @param measureSpec
  284.          *                        A measureSpec packed into an int
  285.          * @return The width of the view, honoring constraints from measureSpec
  286.          */
  287.         private int measureWidth(int measureSpec) {
  288.                 int result = 0;
  289.                 int specMode = MeasureSpec.getMode(measureSpec);
  290.                 int specSize = MeasureSpec.getSize(measureSpec);
  291.  
  292.                 // We were told how big to be
  293.                 if (specMode == MeasureSpec.EXACTLY) {
  294.                         result = specSize;
  295.                 }
  296.                 // Calculate the width according the views count
  297.                 else {
  298.                         int count = 3;
  299.                         if (viewFlow != null) {
  300.                                 count = viewFlow.getViewsCount();
  301.                         }
  302.                         // Remember that spacing is centre-to-centre
  303.                         result = (int) (getPaddingLeft() + getPaddingRight()
  304.                                         + (2 * mRadius) + (count - 1) * spacing);
  305.                         // Respect AT_MOST value if that was what is called for by
  306.                         // measureSpec
  307.                         if (specMode == MeasureSpec.AT_MOST) {
  308.                                 result = Math.min(result, specSize);
  309.                         }
  310.                 }
  311.                 return result;
  312.         }
  313.  
  314.         /**
  315.          * Determines the height of this view
  316.          *
  317.          * @param measureSpec
  318.          *                        A measureSpec packed into an int
  319.          * @return The height of the view, honoring constraints from measureSpec
  320.          */
  321.         private int measureHeight(int measureSpec) {
  322.                 int result = 0;
  323.                 int specMode = MeasureSpec.getMode(measureSpec);
  324.                 int specSize = MeasureSpec.getSize(measureSpec);
  325.  
  326.                 // We were told how big to be
  327.                 if (specMode == MeasureSpec.EXACTLY) {
  328.                         result = specSize;
  329.                 }
  330.                 // Measure the height
  331.                 else {
  332.                         result = (int) (2 * mRadius + getPaddingTop() + getPaddingBottom() + 1);
  333.                         // Respect AT_MOST value if that was what is called for by
  334.                         // measureSpec
  335.                         if (specMode == MeasureSpec.AT_MOST) {
  336.                                 result = Math.min(result, specSize);
  337.                         }
  338.                 }
  339.                 return result;
  340.         }
  341.  
  342.         /**
  343.          * Sets the fill color
  344.          *
  345.          * @param color
  346.          *                        ARGB value for the text
  347.          */
  348.         public void setFillColor(int color) {
  349.                 mPaintActive.setColor(color);
  350.                 invalidate();
  351.         }
  352.  
  353.         /**
  354.          * Sets the stroke color
  355.          *
  356.          * @param color
  357.          *                        ARGB value for the text
  358.          */
  359.         public void setStrokeColor(int color) {
  360.                 mPaintInactive.setColor(color);
  361.                 invalidate();
  362.         }
  363.  
  364.         /**
  365.          * Resets the fade out timer to 0. Creating a new one if needed
  366.          */
  367.         private void resetTimer() {
  368.                 // Only set the timer if we have a timeout of at least 1 millisecond
  369.                 if (fadeOutTime > 0) {
  370.                         // Check if we need to create a new timer
  371.                         if (timer == null || timer._run == false) {
  372.                                 // Create and start a new timer
  373.                                 timer = new FadeTimer();
  374.                                 timer.execute();
  375.                         } else {
  376.                                 // Reset the current tiemr to 0
  377.                                 timer.resetTimer();
  378.                         }
  379.                 }
  380.         }
  381.  
  382.         /**
  383.          * Counts from 0 to the fade out time and animates the view away when
  384.          * reached
  385.          */
  386.         private class FadeTimer extends AsyncTask<Void, Void, Void> {
  387.                 // The current count
  388.                 private int timer = 0;
  389.                 // If we are inside the timing loop
  390.                 private boolean _run = true;
  391.  
  392.                 public void resetTimer() {
  393.                         timer = 0;
  394.                 }
  395.  
  396.                 @Override
  397.                 protected Void doInBackground(Void... arg0) {
  398.                         while (_run) {
  399.                                 try {
  400.                                         // Wait for a millisecond
  401.                                         Thread.sleep(1);
  402.                                         // Increment the timer
  403.                                         timer++;
  404.  
  405.                                         // Check if we've reached the fade out time
  406.                                         if (timer == fadeOutTime) {
  407.                                                 // Stop running
  408.                                                 _run = false;
  409.                                         }
  410.                                 } catch (InterruptedException e) {
  411.                                         // TODO Auto-generated catch block
  412.                                         e.printStackTrace();
  413.                                 }
  414.                         }
  415.                         return null;
  416.                 }
  417.  
  418.                 @Override
  419.                 protected void onPostExecute(Void result) {
  420.                         animation = AnimationUtils.loadAnimation(getContext(),
  421.                                         android.R.anim.fade_out);
  422.                         animation.setAnimationListener(animationListener);
  423.                         startAnimation(animation);
  424.                 }
  425.         }
  426.  
  427.         @Override
  428.         public void onAnimationEnd(Animation animation) {
  429.                 setVisibility(View.GONE);
  430.         }
  431.  
  432.         @Override
  433.         public void onAnimationRepeat(Animation animation) {
  434.         }
  435.  
  436.         @Override
  437.         public void onAnimationStart(Animation animation) {
  438.         }
  439. }
  440.  
downloadCircleFlowIndicator.java Source code - Download android-viewflow Source code
Related Source Codes/Software:
onionshare - Securely and anonymously share a file of any size ... 2017-04-16
Android-ItemTouchHelper-Demo - Basic example of using ItemTouchHelper to add drag... 2017-04-16
later - A javascript library for defining recurring schedu... 2017-04-16
x64dbg - An open-source x64/x32 debugger for windows. ... 2017-04-16
pencil - Multiplatform GUI Prototyping/Wireframing 2017-04-16
css-in-js - React: CSS in JS techniques comparison. 2017-04-16
st2 - StackStorm (aka IFTTT for Ops) is event-driven aut... 2017-04-16
WNXHuntForCity - City find By Objective - C 2017-04-16
tmate - Instant Terminal Sharing ht... 2017-04-16
dat.gui - dat.gui is a lightweight controller library for Ja... 2017-04-16
EventStore - The open-source, functional database with Complex ... 2017-04-23
screencat - 2017-04-23
viz.js - A hack to put Graphviz on the web. ... 2017-04-23
JKeyboardPanelSwitch - For resolve the layout conflict when keybord & amp... 2017-04-23
mama2 - Mother plan - all firewood high flame 2017-04-23
BlurEffectForAndroidDesign - Sample to show how to implement blur graphical tri... 2017-04-23
sphinx_rtd_theme - Sphinx theme for readthedocs.org 2017-04-23
rouge - A pure-ruby code highlighter that is compatible wi... 2017-04-23
spring-security-oauth - Support for adding OAuth1(a) and OAuth2 features (... 2017-04-23
Toucan - Fabulous Image Processing in Swift 2017-04-23

 Back to top