• Tutorials
  • Tips & Tricks
  • Applications
  • News

Android Trainee

  • Tutorials
  • Tips & Tricks
  • Applications
  • News
Home  /  Tutorials  /  Android Progress Dialog For Material Design (Android L).
03 June 2015

Android Progress Dialog For Material Design (Android L).

Written by admin@androidtrainee
Tutorials android L, android lollipop, android progress dialog, material design, pogress dialog Leave a Comment

Android Progress Dialog For Material Design (Android L).

Create New Project In Android Eclips.

—>  AndroidManifest.xml

 


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.materialprogressdailogdesign"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

 

—> activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbarStyle="outsideOverlay">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/title_text"
android:padding="8dp"
android:textColor="#FF000000"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Title"
android:text="Circular"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="horizontal"
android:weightSum="2.0"
android:baselineAligned="false">

<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0">

<com.example.material.widget.ProgressView
android:id="@+id/progress_pv_circular"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
app:pv_autostart = "false"
app:pv_circular="true"
app:pv_progressStyle="@style/CircularProgressDrawableStyle"
app:pv_progressMode="indeterminate"/>

</FrameLayout>

<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0">

<com.example.material.widget.ProgressView
android:id="@+id/progress_pv_circular_colors"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
app:pv_autostart = "false"
app:pv_circular="true"
app:pv_progressStyle="@style/ColorsCircularProgressDrawableStyle"
app:pv_progressMode="indeterminate"/>

</FrameLayout>

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="horizontal"
android:weightSum="2.0"
android:baselineAligned="false">

<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0">

<com.example.material.widget.ProgressView
android:id="@+id/progress_pv_circular_inout"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
app:pv_autostart = "false"
app:pv_circular="true"
app:pv_progressStyle="@style/InOutCircularProgressDrawableStyle"
app:pv_progressMode="indeterminate"/>

</FrameLayout>

<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0">

<com.example.material.widget.ProgressView
android:id="@+id/progress_pv_circular_inout_colors"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
app:pv_autostart = "false"
app:pv_circular="true"
app:pv_progressStyle="@style/InOutColorsCircularProgressDrawableStyle"
app:pv_progressMode="indeterminate"/>

</FrameLayout>

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="horizontal"
android:weightSum="2.0"
android:baselineAligned="false">

<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0">

<com.example.material.widget.ProgressView
android:id="@+id/progress_pv_circular_determinate_in_out"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
app:pv_autostart = "false"
app:pv_circular="true"
app:pv_progressStyle="@style/DeterminateInOutCircularProgressDrawableStyle"
app:pv_progressMode="determinate"/>

</FrameLayout>

<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0">

<com.example.material.widget.ProgressView
android:id="@+id/progress_pv_circular_determinate"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
app:pv_autostart = "false"
app:pv_circular="true"
app:pv_progressStyle="@style/DeterminateCircularProgressDrawableStyle"
app:pv_progressMode="determinate"/>

</FrameLayout>

</LinearLayout>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/title_text"
android:padding="8dp"
android:textColor="#FF000000"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Title"
android:text="Linear"/>

<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">

<com.example.material.widget.ProgressView
android:id="@+id/progress_pv_linear"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_gravity="center"
app:pv_autostart = "false"
app:pv_circular="false"
app:pv_progressStyle="@style/LinearProgressDrawableStyle"
app:pv_progressMode="indeterminate"/>

</FrameLayout>

<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">

<com.example.material.widget.ProgressView
android:id="@+id/progress_pv_linear_colors"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_gravity="center"
app:pv_autostart = "false"
app:pv_circular="false"
app:pv_progressStyle="@style/ColorsLinearProgressDrawableStyle"
app:pv_progressMode="indeterminate"/>

</FrameLayout>

<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">

<com.example.material.widget.ProgressView
android:id="@+id/progress_pv_linear_determinate"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_gravity="center"
app:pv_autostart = "false"
app:pv_circular="false"
app:pv_progressStyle="@style/DeterminateLinearProgressDrawableStyle"
app:pv_progressMode="determinate"/>

</FrameLayout>

<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">

<com.example.material.widget.ProgressView
android:id="@+id/progress_pv_linear_query"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_gravity="center"
app:pv_autostart = "false"
app:pv_circular="false"
app:pv_progressStyle="@style/QueryLinearProgressDrawableStyle"
app:pv_progressMode="query"/>

</FrameLayout>

<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">

<com.example.material.widget.ProgressView
android:id="@+id/progress_pv_linear_buffer"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_gravity="center"
app:pv_autostart = "false"
app:pv_circular="false"
app:pv_progressStyle="@style/BufferLinearProgressDrawableStyle"
app:pv_progressMode="buffer"/>

</FrameLayout>

</LinearLayout>

</ScrollView>

—-> Values Folder

attrs.xml


<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="WeekView">
<attr name="wv_backgroundColor" format="reference|color"/>
<attr name="wv_verticalPadding" format="reference|dimension"/>
<attr name="wv_horizontalPadding" format="reference|dimension"/>
<attr name="wv_animDuration" format="reference|integer"/>
</declare-styleable>

<declare-styleable name="ContactView">
<attr name="cv_buttonSrc" format="reference"/>
<attr name="cv_buttonSize" format="reference|dimension"/>
<attr name="cv_avatarSrc" format="reference"/>
<attr name="cv_avatarSize" format="reference|dimension"/>
<attr name="cv_spacing" format="reference|dimension"/>
<attr name="cv_name" format="reference|string"/>
<attr name="cv_nameTextAppearance" format="reference"/>
<attr name="cv_nameTextSize" format="reference|dimension"/>
<attr name="cv_nameTextColor" format="reference|color"/>
<attr name="cv_address" format="reference|string"/>
<attr name="cv_addressTextAppearance" format="reference"/>
<attr name="cv_addressTextSize" format="reference|dimension"/>
<attr name="cv_addressTextColor" format="reference|color"/>
<attr name="android:minHeight" />
</declare-styleable>

<declare-styleable name="ContactEditText">
<attr name="cet_spanHeight" format="reference|dimension"/>
<attr name="cet_spanMaxWidth" format="reference|dimension"/>
<attr name="cet_spanPaddingLeft" format="reference|dimension"/>
<attr name="cet_spanPaddingRight" format="reference|dimension"/>
<attr name="cet_spanFontFamily" format="reference|string"/>
<attr name="cet_spanTextStyle" format="integer">
<enum name="normal" value="0" />
<enum name="bold" value="1" />
<enum name="italic" value="2" />
<enum name="bold_italic" value="3" />
</attr>
<attr name="cet_spanTextSize" format="reference|dimension"/>
<attr name="cet_spanTextColor" format="reference|color"/>
<attr name="cet_spanBackgroundColor" format="reference|color"/>
<attr name="cet_spanSpacing" format="reference|dimension"/>
</declare-styleable>
<attr name="pv_progressMode" format="integer">
<enum name="determinate" value="0x00000000" />
<enum name="indeterminate" value="0x00000001" />
<enum name="buffer" value="0x00000002" />
<enum name="query" value="0x00000003" />
</attr>

<attr name="pv_progress" format="float"/>
<attr name="pv_secondaryProgress" format="float"/>

<attr name="rd_style" format="reference"/>
<attr name="rd_enable" format="boolean"/>

<declare-styleable name="CircularProgressDrawable">
<attr name="cpd_padding" format="reference|dimension"/>
<attr name="cpd_initialAngle" format="reference|integer"/>
<attr name="cpd_maxSweepAngle" format="reference|integer"/>
<attr name="cpd_minSweepAngle" format="reference|integer"/>
<attr name="cpd_strokeSize" format="reference|dimension"/>
<attr name="cpd_strokeColor" format="reference|color"/>
<attr name="cpd_strokeSecondaryColor" format="reference|color"/>
<attr name="cpd_strokeColors" format="reference"/>
<attr name="cpd_reverse" format="boolean"/>
<attr name="cpd_rotateDuration" format="reference|integer"/>
<attr name="cpd_transformDuration" format="reference|integer"/>
<attr name="cpd_keepDuration" format="reference|integer"/>
<attr name="cpd_transformInterpolator" format="reference"/>
<attr name="cpd_inAnimDuration" format="reference|integer"/>
<attr name="cpd_outAnimDuration" format="reference|integer"/>
<attr name="cpd_inStepColors" format="reference"/>
<attr name="cpd_inStepPercent" format="float"/>
<attr name="pv_progressMode"/>
<attr name="pv_progress"/>
<attr name="pv_secondaryProgress"/>
</declare-styleable>

<declare-styleable name="LinearProgressDrawable">
<attr name="lpd_maxLineWidth" format="reference|dimension|fraction"/>
<attr name="lpd_minLineWidth" format="reference|dimension|fraction"/>
<attr name="lpd_strokeSize" format="reference|dimension"/>
<attr name="lpd_strokeColor" format="reference|color"/>
<attr name="lpd_strokeSecondaryColor" format="reference|color"/>
<attr name="lpd_strokeColors" format="reference"/>
<attr name="lpd_reverse" format="boolean"/>
<attr name="lpd_travelDuration" format="reference|integer"/>
<attr name="lpd_transformDuration" format="reference|integer"/>
<attr name="lpd_keepDuration" format="reference|integer"/>
<attr name="lpd_transformInterpolator" format="reference"/>
<attr name="lpd_inAnimDuration" format="reference|integer"/>
<attr name="lpd_outAnimDuration" format="reference|integer"/>
<attr name="lpd_verticalAlign" format="integer">
<enum name="top" value="0x00000000" />
<enum name="center" value="0x00000001" />
<enum name="bottom" value="0x00000002" />
</attr>
<attr name="pv_progressMode"/>
<attr name="pv_progress"/>
<attr name="pv_secondaryProgress"/>
</declare-styleable>

<declare-styleable name="ProgressView">
<attr name="pv_autostart" format="boolean"/>
<attr name="pv_circular" format="boolean"/>
<attr name="pv_progressStyle" format="reference"/>
</declare-styleable>

<declare-styleable name="RippleView">
<attr name="rd_style" />
<attr name="rd_enable" />
</declare-styleable>

<declare-styleable name="RippleDrawable">
<attr name="rd_backgroundColor" format="reference|color"/>
<attr name="rd_backgroundAnimDuration" format="reference|integer"/>
<attr name="rd_maxRippleRadius" format="reference|dimension|integer">
<enum name="match_view" value="0x00000000" />
</attr>
<attr name="rd_rippleColor" format="reference|color"/>
<attr name="rd_rippleAnimDuration" format="reference|integer"/>
<attr name="rd_inInterpolator" format="reference"/>
<attr name="rd_outInterpolator" format="reference"/>
<attr name="rd_maskType" format="integer">
<enum name="rectangle" value="0x00000000" />
<enum name="oval" value="0x00000001" />
</attr>
<attr name="rd_rippleType" format="integer">
<enum name="touch" value="0x00000000" />
<enum name="wave" value="0x00000001" />
</attr>
<attr name="rd_cornerRadius" format="reference|dimension"/>
<attr name="rd_topLeftCornerRadius" format="reference|dimension"/>
<attr name="rd_topRightCornerRadius" format="reference|dimension"/>
<attr name="rd_bottomLeftCornerRadius" format="reference|dimension"/>
<attr name="rd_bottomRightCornerRadius" format="reference|dimension"/>
<attr name="rd_padding" format="reference|dimension"/>
<attr name="rd_leftPadding" format="reference|dimension"/>
<attr name="rd_topPadding" format="reference|dimension"/>
<attr name="rd_rightPadding" format="reference|dimension"/>
<attr name="rd_bottomPadding" format="reference|dimension"/>
<attr name="rd_delayClick" format="boolean"/>
</declare-styleable>

<declare-styleable name="LineMorphingDrawable">
<attr name="lmd_state" format="reference"/>
<attr name="lmd_curState" format="integer"/>
<attr name="lmd_padding" format="reference|dimension"/>
<attr name="lmd_paddingLeft" format="reference|dimension"/>
<attr name="lmd_paddingTop" format="reference|dimension"/>
<attr name="lmd_paddingRight" format="reference|dimension"/>
<attr name="lmd_paddingBottom" format="reference|dimension"/>
<attr name="lmd_animDuration" format="reference|integer"/>
<attr name="lmd_interpolator" format="reference"/>
<attr name="lmd_strokeSize" format="reference|dimension"/>
<attr name="lmd_strokeColor" format="reference|color"/>
<attr name="lmd_strokeCap" format="integer">
<enum name="butt" value="0x00000000" />
<enum name="round" value="0x00000001" />
<enum name="square" value="0x00000002" />
</attr>
<attr name="lmd_strokeJoin" format="integer">
<enum name="miter" value="0x00000000" />
<enum name="round" value="0x00000001" />
<enum name="bevel" value="0x00000002" />
</attr>
<attr name="lmd_clockwise" format="boolean"/>
</declare-styleable>

<declare-styleable name="RadioButtonDrawable">
<attr name="rbd_width" format="reference|dimension"/>
<attr name="rbd_height" format="reference|dimension"/>
<attr name="rbd_strokeSize" format="reference|dimension"/>
<attr name="rbd_radius" format="reference|dimension"/>
<attr name="rbd_innerRadius" format="reference|dimension"/>
<attr name="rbd_strokeColor" format="reference|color"/>
<attr name="rbd_animDuration" format="reference|integer"/>
</declare-styleable>

<declare-styleable name="CheckBoxDrawable">
<attr name="cbd_width" format="reference|dimension"/>
<attr name="cbd_height" format="reference|dimension"/>
<attr name="cbd_boxSize" format="reference|dimension"/>
<attr name="cbd_cornerRadius" format="reference|dimension"/>
<attr name="cbd_strokeSize" format="reference|dimension"/>
<attr name="cbd_strokeColor" format="reference|color"/>
<attr name="cbd_tickColor" format="reference|color"/>
<attr name="cbd_animDuration" format="reference|integer"/>
</declare-styleable>

<declare-styleable name="Switch">
<attr name="sw_trackSize" format="reference|dimension"/>
<attr name="sw_trackColor" format="reference|color"/>
<attr name="sw_trackCap" format="integer">
<enum name="butt" value="0x00000000" />
<enum name="round" value="0x00000001" />
<enum name="square" value="0x00000002" />
</attr>
<attr name="sw_thumbColor" format="reference|color"/>
<attr name="sw_thumbRadius" format="reference|dimension"/>
<attr name="sw_thumbElevation" format="reference|dimension"/>
<attr name="sw_animDuration" format="reference|integer"/>
<attr name="sw_interpolator" format="reference"/>
<attr name="android:gravity" />
<attr name="android:checked" />
</declare-styleable>

<declare-styleable name="Slider">
<attr name="sl_trackSize" format="reference|dimension"/>
<attr name="sl_primaryColor" format="reference|color"/>
<attr name="sl_secondaryColor" format="reference|color"/>
<attr name="sl_trackCap" format="integer">
<enum name="butt" value="0x00000000" />
<enum name="round" value="0x00000001" />
<enum name="square" value="0x00000002" />
</attr>
<attr name="sl_thumbBorderSize" format="reference|dimension"/>
<attr name="sl_thumbRadius" format="reference|dimension"/>
<attr name="sl_thumbFocusRadius" format="reference|dimension"/>
<attr name="sl_travelAnimDuration" format="reference|integer"/>
<attr name="sl_transformAnimDuration" format="reference|integer"/>
<attr name="sl_interpolator" format="reference"/>
<attr name="sl_minValue" format="reference|integer"/>
<attr name="sl_maxValue" format="reference|integer"/>
<attr name="sl_stepValue" format="reference|integer"/>
<attr name="sl_value" format="reference|integer"/>
<attr name="sl_discreteMode" format="reference|boolean"/>
<attr name="sl_fontFamily" format="string|reference"/>
<attr name="sl_textStyle" format="integer">
<enum name="normal" value="0" />
<enum name="bold" value="1" />
<enum name="italic" value="2" />
<enum name="bold_italic" value="3" />
</attr>
<attr name="sl_textSize" format="reference|dimension"/>
<attr name="sl_textColor" format="reference|color"/>
<attr name="android:gravity" />
<attr name="android:enabled" />
</declare-styleable>

<declare-styleable name="NavigationDrawerDrawable">
<attr name="nd_ripple" format="reference"/>
<attr name="nd_icon" format="reference"/>
</declare-styleable>

<declare-styleable name="TabPageIndicator">
<attr name="tpi_tabPadding" format="reference|dimension"/>
<attr name="tpi_tabRipple" format="reference"/>
<attr name="tpi_indicatorColor" format="reference|color"/>
<attr name="tpi_indicatorHeight" format="reference|dimension"/>
<attr name="android:textAppearance" />
<attr name="tpi_mode" format="integer">
<enum name="scroll" value="0x00000000" />
<enum name="fixed" value="0x00000001" />
</attr>
</declare-styleable>

<declare-styleable name="EditText">
<attr name="et_inputId" format="reference"/>
<attr name="et_labelEnable" format="boolean"/>
<attr name="et_labelPadding" format="reference|dimension"/>
<attr name="et_labelTextSize" format="reference|dimension"/>
<attr name="et_labelTextColor" format="reference|color"/>
<attr name="et_labelTextAppearance" format="reference"/>
<attr name="et_labelEllipsize" format="integer">
<enum name="start" value="0x00000001" />
<enum name="middle" value="0x00000002" />
<enum name="end" value="0x00000003" />
<enum name="marquee" value="0x00000004" />
</attr>
<attr name="et_labelInAnim" format="reference"/>
<attr name="et_labelOutAnim" format="reference"/>
<attr name="et_supportMode" format="integer">
<enum name="none" value="0x00000000" />
<enum name="helper" value="0x00000001" />
<enum name="helperWithError" value="0x00000002" />
<enum name="charCounter" value="0x00000003" />
</attr>
<attr name="et_supportMaxChars" format="reference|integer"/>
<attr name="et_helper" format="reference|string"/>
<attr name="et_error" format="reference|string"/>
<attr name="et_supportPadding" format="reference|dimension"/>
<attr name="et_supportTextSize" format="reference|dimension"/>
<attr name="et_supportTextColor" format="reference|color"/>
<attr name="et_supportTextErrorColor" format="reference|color"/>
<attr name="et_supportTextAppearance" format="reference"/>
<attr name="et_supportSingleLine" format="boolean"/>
<attr name="et_supportMaxLines" format="reference|integer"/>
<attr name="et_supportLines" format="reference|integer"/>
<attr name="et_supportEllipsize" format="integer">
<enum name="start" value="0x00000001" />
<enum name="middle" value="0x00000002" />
<enum name="end" value="0x00000003" />
<enum name="marquee" value="0x00000004" />
</attr>
<attr name="et_dividerColor" format="reference|color"/>
<attr name="et_dividerErrorColor" format="reference|color"/>
<attr name="et_dividerHeight" format="reference|dimension"/>
<attr name="et_dividerPadding" format="reference|dimension"/>
<attr name="et_dividerAnimDuration" format="reference|integer"/>
<attr name="et_dividerCompoundPadding" format="boolean"/>
<attr name="et_autoCompleteMode" format="integer">
<enum name="none"   value="0"/>
<enum name="single" value="1"/>
<enum name="multi"  value="2"/>
</attr>
</declare-styleable>

<declare-styleable name="SnackBar">
<attr name="sb_backgroundColor" format="reference|color"/>
<attr name="sb_backgroundCornerRadius" format="reference|dimension"/>
<attr name="sb_horizontalPadding" format="reference|dimension"/>
<attr name="sb_verticalPadding" format="reference|dimension"/>
<attr name="sb_width" format="reference|dimension|integer">
<enum name="match_parent" value="-1" />
<enum name="wrap_content" value="-2" />
</attr>
<attr name="sb_minWidth" format="reference|dimension"/>
<attr name="sb_maxWidth" format="reference|dimension"/>
<attr name="sb_height" format="reference|dimension|integer">
<enum name="match_parent" value="-1" />
<enum name="wrap_content" value="-2" />
</attr>
<attr name="sb_minHeight" format="reference|dimension"/>
<attr name="sb_maxHeight" format="reference|dimension"/>
<attr name="sb_marginLeft" format="reference|dimension"/>
<attr name="sb_marginBottom" format="reference|dimension"/>
<attr name="sb_textSize" format="reference|dimension"/>
<attr name="sb_textColor" format="reference|color"/>
<attr name="sb_textAppearance" format="reference"/>
<attr name="sb_text" format="reference|string"/>
<attr name="sb_singleLine" format="boolean"/>
<attr name="sb_maxLines" format="reference|integer"/>
<attr name="sb_lines" format="reference|integer"/>
<attr name="sb_ellipsize" format="integer">
<enum name="start" value="0x00000001" />
<enum name="middle" value="0x00000002" />
<enum name="end" value="0x00000003" />
<enum name="marquee" value="0x00000004" />
</attr>
<attr name="sb_actionTextSize" format="reference|dimension"/>
<attr name="sb_actionTextColor" format="reference|color"/>
<attr name="sb_actionTextAppearance" format="reference"/>
<attr name="sb_actionText" format="reference|string"/>
<attr name="sb_actionRipple" format="reference"/>
<attr name="sb_duration" format="reference|integer"/>
<attr name="sb_inAnimation" format="reference"/>
<attr name="sb_outAnimation" format="reference"/>
<attr name="sb_removeOnDismiss" format="boolean" />
</declare-styleable>

<declare-styleable name="FloatingActionButton">
<attr name="fab_backgroundColor" format="reference|color"/>
<attr name="fab_radius" format="reference|dimension"/>
<attr name="fab_elevation" format="reference|dimension"/>
<attr name="fab_iconSrc" format="reference"/>
<attr name="fab_iconLineMorphing" format="reference"/>
<attr name="fab_iconSize" format="reference|dimension"/>
<attr name="fab_interpolator" format="reference"/>
<attr name="fab_animDuration" format="reference|integer"/>
</declare-styleable>

<declare-styleable name="Spinner">
<attr name="android:dropDownWidth" />
<attr name="android:popupBackground" />
<attr name="android:minWidth"/>
<attr name="android:minHeight"/>
<attr name="spn_labelEnable" format="boolean"/>
<attr name="spn_labelPadding" format="reference|dimension"/>
<attr name="spn_labelTextSize" format="reference|dimension"/>
<attr name="spn_labelTextColor" format="reference|color"/>
<attr name="spn_labelTextAppearance" format="reference"/>
<attr name="spn_labelEllipsize" format="integer">
<enum name="start" value="0x00000001" />
<enum name="middle" value="0x00000002" />
<enum name="end" value="0x00000003" />
<enum name="marquee" value="0x00000004" />
</attr>
<attr name="spn_label" format="string|reference"/>
<attr name="spn_popupItemAnimation" format="reference"/>
<attr name="spn_popupItemAnimOffset" format="integer"/>
<attr name="spn_arrowColor" format="reference|color"/>
<attr name="spn_arrowSize" format="reference|dimension"/>
<attr name="spn_arrowPadding" format="reference|dimension"/>
<attr name="spn_arrowAnimDuration" format="integer"/>
<attr name="spn_arrowInterpolator" format="reference"/>
<attr name="spn_arrowAnimClockwise" format="boolean"/>
<attr name="spn_arrowSwitchMode" format="boolean"/>
<attr name="spn_dividerColor" format="reference|color"/>
<attr name="spn_dividerHeight" format="reference|dimension"/>
<attr name="spn_dividerPadding" format="reference|dimension"/>
<attr name="spn_dividerAnimDuration" format="reference|integer"/>
</declare-styleable>

<declare-styleable name="Dialog">
<attr name="android:layout_width" />
<attr name="android:layout_height" />
<attr name="di_dimAmount" format="float" />
<attr name="di_backgroundColor" format="color|reference" />
<attr name="di_elevation" format="dimension|reference" />
<attr name="di_maxElevation" format="dimension|reference" />
<attr name="di_cornerRadius" format="dimension|reference" />
<attr name="di_titleTextAppearance" format="reference" />
<attr name="di_titleTextColor" format="color|reference" />
<attr name="di_actionBackground" format="reference" />
<attr name="di_actionRipple" format="reference" />
<attr name="di_actionTextAppearance" format="reference" />
<attr name="di_actionTextColor" format="color|reference" />
<attr name="di_positiveActionBackground" format="reference" />
<attr name="di_positiveActionRipple" format="reference" />
<attr name="di_positiveActionTextAppearance" format="reference" />
<attr name="di_positiveActionTextColor" format="color|reference" />
<attr name="di_negativeActionBackground" format="reference" />
<attr name="di_negativeActionRipple" format="reference" />
<attr name="di_negativeActionTextAppearance" format="reference" />
<attr name="di_negativeActionTextColor" format="color|reference" />
<attr name="di_neutralActionBackground" format="reference" />
<attr name="di_neutralActionRipple" format="reference" />
<attr name="di_neutralActionTextAppearance" format="reference" />
<attr name="di_neutralActionTextColor" format="color|reference" />
<attr name="di_dividerColor" format="color|reference" />
<attr name="di_dividerHeight" format="dimension|reference" />
<attr name="di_inAnimation" format="reference" />
<attr name="di_outAnimation" format="reference" />
<attr name="di_cancelable" format="boolean" />
<attr name="di_canceledOnTouchOutside" format="boolean" />
</declare-styleable>

<declare-styleable name="SimpleDialog">
<attr name="di_messageTextAppearance" format="reference" />
<attr name="di_messageTextColor" format="color|reference" />
<attr name="di_radioButtonStyle" format="reference" />
<attr name="di_checkBoxStyle" format="reference" />
<attr name="di_itemHeight" format="dimension|reference" />
<attr name="di_itemTextAppearance" format="reference" />
</declare-styleable>

<declare-styleable name="TimePicker">
<attr name="tp_backgroundColor" format="color|reference" />
<attr name="tp_selectionColor" format="color|reference" />
<attr name="tp_selectionRadius" format="dimension|reference" />
<attr name="tp_tickSize" format="dimension|reference" />
<attr name="tp_fontFamily" format="string|reference"/>
<attr name="tp_textStyle" format="integer">
<enum name="normal" value="0" />
<enum name="bold" value="1" />
<enum name="italic" value="2" />
<enum name="bold_italic" value="3" />
</attr>
<attr name="tp_textSize" format="dimension|reference" />
<attr name="tp_textColor" format="color|reference" />
<attr name="tp_textHighlightColor" format="color|reference" />
<attr name="tp_animDuration" format="integer|reference" />
<attr name="tp_inInterpolator" format="reference" />
<attr name="tp_outInterpolator" format="reference" />
<attr name="tp_mode" format="integer">
<enum name="hour" value="0" />
<enum name="minute" value="1" />
</attr>
<attr name="tp_24Hour" format="boolean"/>
<attr name="tp_hour" format="integer"/>
<attr name="tp_minute" format="integer"/>
</declare-styleable>

<declare-styleable name="TimePickerDialog">
<attr name="tp_headerHeight" format="dimension|reference" />
<attr name="tp_textTimeColor" format="color|reference" />
<attr name="tp_textTimeSize" format="dimension|reference" />
<attr name="tp_am" format="string|reference"/>
<attr name="tp_pm" format="string|reference"/>
</declare-styleable>

<attr name="dp_textHighlightColor" format="color|reference" />
<attr name="dp_textColor" format="color|reference" />
<attr name="dp_selectionColor" format="color|reference" />
<attr name="dp_animDuration" format="integer|reference" />
<attr name="dp_inInterpolator" format="reference" />
<attr name="dp_outInterpolator" format="reference" />
<attr name="dp_yearMin" format="integer"/>
<attr name="dp_monthMin" format="integer"/>
<attr name="dp_dayMin" format="integer"/>
<attr name="dp_yearMax" format="integer"/>
<attr name="dp_monthMax" format="integer"/>
<attr name="dp_dayMax" format="integer"/>
<attr name="dp_year" format="integer"/>
<attr name="dp_month" format="integer"/>
<attr name="dp_day" format="integer"/>
<attr name="dp_fontFamily" format="string|reference"/>
<attr name="dp_textStyle" format="integer">
<enum name="normal" value="0" />
<enum name="bold" value="1" />
<enum name="italic" value="2" />
<enum name="bold_italic" value="3" />
</attr>

<declare-styleable name="YearPicker">
<attr name="dp_yearMin" />
<attr name="dp_yearMax" />
<attr name="dp_year" />
<attr name="dp_yearTextSize" format="dimension|reference" />
<attr name="dp_yearItemHeight" format="dimension|reference" />
<attr name="dp_textHighlightColor" />
<attr name="dp_textColor" />
<attr name="dp_selectionColor" />
<attr name="dp_animDuration" />
<attr name="dp_inInterpolator" />
<attr name="dp_outInterpolator" />
<attr name="dp_fontFamily" />
<attr name="dp_textStyle" />
</declare-styleable>

<declare-styleable name="DatePicker">
<attr name="dp_yearMin" />
<attr name="dp_monthMin" />
<attr name="dp_dayMin" />
<attr name="dp_yearMax" />
<attr name="dp_monthMax" />
<attr name="dp_dayMax" />
<attr name="dp_year" />
<attr name="dp_month" />
<attr name="dp_day" />
<attr name="dp_dayTextSize" format="dimension|reference" />
<attr name="dp_textLabelColor" format="color|reference" />
<attr name="dp_textDisableColor" format="color|reference" />
<attr name="dp_textHighlightColor" />
<attr name="dp_textColor" />
<attr name="dp_selectionColor" />
<attr name="dp_animDuration" />
<attr name="dp_inInterpolator" />
<attr name="dp_outInterpolator" />
<attr name="dp_fontFamily" />
<attr name="dp_textStyle" />
<attr name="android:padding" />
<attr name="android:paddingLeft" />
<attr name="android:paddingTop" />
<attr name="android:paddingRight" />
<attr name="android:paddingBottom" />
</declare-styleable>

<declare-styleable name="DatePickerDialog">
<attr name="dp_headerPrimaryHeight" format="dimension|reference" />
<attr name="dp_headerPrimaryColor" format="color|reference" />
<attr name="dp_headerSecondaryHeight" format="dimension|reference" />
<attr name="dp_headerSecondaryColor" format="color|reference" />
<attr name="dp_headerPrimaryTextSize" format="dimension|reference" />
<attr name="dp_headerSecondaryTextSize" format="dimension|reference" />
<attr name="dp_textHeaderColor" format="color|reference" />
</declare-styleable>
</resources>

colors.xml


<?xml version="1.0" encoding="utf-8"?>
<resources>

<array name="progress_colors">
<item>#FF3F8AF8</item>
<item>#FFD8433C</item>
<item>#FFF2AF3A</item>
<item>#FF279B5E</item>
</array>

<array name="in_colors">
<item>#FFB5D4FF</item>
<item>#FFDEEAFC</item>
<item>#FFFAFFFE</item>
</array>

</resources>

 

 

dimens.xml

 


<resources>

<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="title_text">16sp</dimen>
</resources>

 

styles.xml

 


<resources>

<!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>

<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
<!-- Progress Style -->

<style name="CircularProgressDrawableStyle" parent="Material.Drawable.CircularProgress"/>

<style name="ColorsCircularProgressDrawableStyle" parent="Material.Drawable.CircularProgress">
<item name="cpd_strokeColors">@array/progress_colors</item>
</style>

<style name="InOutCircularProgressDrawableStyle" parent="Material.Drawable.CircularProgress">
<item name="cpd_inAnimDuration">800</item>
<item name="cpd_inStepPercent">0.5</item>
<item name="cpd_inStepColors">@array/in_colors</item>
<item name="cpd_outAnimDuration">400</item>
</style>

<style name="InOutColorsCircularProgressDrawableStyle" parent="Material.Drawable.CircularProgress">
<item name="cpd_inAnimDuration">800</item>
<item name="cpd_inStepPercent">0.5</item>
<item name="cpd_inStepColors">@array/in_colors</item>
<item name="cpd_outAnimDuration">400</item>
<item name="cpd_strokeColors">@array/progress_colors</item>
</style>

<style name="DeterminateInOutCircularProgressDrawableStyle" parent="Material.Drawable.CircularProgress.Determinate">
<item name="cpd_inAnimDuration">400</item>
<item name="cpd_outAnimDuration">400</item>
<item name="cpd_initialAngle">-90</item>
</style>

<style name="DeterminateCircularProgressDrawableStyle" parent="Material.Drawable.CircularProgress.Determinate">
<item name="cpd_inAnimDuration">0</item>
<item name="cpd_outAnimDuration">0</item>
<item name="cpd_initialAngle">-90</item>
</style>

<style name="LinearProgressDrawableStyle" parent="Material.Drawable.LinearProgress">
<item name="lpd_strokeSecondaryColor">#00000000</item>
</style>

<style name="ColorsLinearProgressDrawableStyle" parent="Material.Drawable.LinearProgress">
<item name="lpd_strokeColors">@array/progress_colors</item>
<item name="lpd_strokeSecondaryColor">#00000000</item>
</style>

<style name="DeterminateLinearProgressDrawableStyle" parent="Material.Drawable.LinearProgress.Determinate">
<item name="lpd_strokeColor">#FF4389F3</item>
<item name="lpd_strokeSecondaryColor">#FFB6CDF2</item>
</style>

<style name="QueryLinearProgressDrawableStyle" parent="Material.Drawable.LinearProgress.Query">
<item name="lpd_strokeColor">#FF4389F3</item>
<item name="lpd_strokeSecondaryColor">#FFB6CDF2</item>
</style>

<style name="BufferLinearProgressDrawableStyle" parent="Material.Drawable.LinearProgress.Buffer">
<item name="lpd_strokeColor">#FF4389F3</item>
<item name="lpd_strokeSecondaryColor">#FFB6CDF2</item>
<item name="lpd_travelDuration">400</item>
<item name="lpd_transformDuration">400</item>
<item name="lpd_keepDuration">100</item>
</style>

<style name="Material"></style>

<style name="Material.Drawable"></style>

<style name="Material.Widget"></style>

<style name="Material.App"></style>

<style name="Material.TextAppearance"></style>

<style name="Material.Drawable.CircularProgress">
<item name="cpd_padding">0dp</item>
<item name="cpd_initialAngle">0</item>
<item name="cpd_maxSweepAngle">270</item>
<item name="cpd_minSweepAngle">1</item>
<item name="cpd_strokeSize">4dp</item>
<item name="cpd_strokeColor">?attr/colorPrimary</item>
<item name="cpd_strokeSecondaryColor">@android:color/transparent</item>
<item name="cpd_reverse">false</item>
<item name="cpd_rotateDuration">1000</item>
<item name="cpd_transformDuration">600</item>
<item name="cpd_keepDuration">200</item>
<item name="cpd_transformInterpolator">@android:anim/decelerate_interpolator</item>
<item name="pv_progressMode">indeterminate</item>
<item name="cpd_inAnimDuration">0</item>
<item name="cpd_outAnimDuration">@android:integer/config_mediumAnimTime</item>
</style>

<style name="Material.Drawable.CircularProgress.Determinate" parent="Material.Drawable.CircularProgress">
<item name="pv_progressMode">determinate</item>
<item name="cpd_inAnimDuration">@android:integer/config_mediumAnimTime</item>
</style>

<style name="Material.Drawable.LinearProgress">
<item name="lpd_maxLineWidth">75%</item>
<item name="lpd_minLineWidth">10%</item>
<item name="lpd_strokeSize">4dp</item>
<item name="lpd_strokeColor">?attr/colorPrimary</item>
<item name="lpd_strokeSecondaryColor">?attr/colorControlNormal</item>
<item name="lpd_reverse">false</item>
<item name="lpd_travelDuration">1000</item>
<item name="lpd_transformDuration">600</item>
<item name="lpd_keepDuration">200</item>
<item name="lpd_transformInterpolator">@android:anim/decelerate_interpolator</item>
<item name="pv_progressMode">indeterminate</item>
<item name="lpd_inAnimDuration">@android:integer/config_mediumAnimTime</item>
<item name="lpd_outAnimDuration">@android:integer/config_mediumAnimTime</item>
<item name="lpd_verticalAlign">bottom</item>
</style>

<style name="Material.Drawable.LinearProgress.Determinate" parent="Material.Drawable.LinearProgress">
<item name="pv_progressMode">determinate</item>
</style>

<style name="Material.Drawable.LinearProgress.Query" parent="Material.Drawable.LinearProgress">
<item name="pv_progressMode">query</item>
</style>

<style name="Material.Drawable.LinearProgress.Buffer" parent="Material.Drawable.LinearProgress">
<item name="pv_progressMode">buffer</item>
</style>

<style name="Material.Widget.ProgressView">
<item name="pv_progress">0</item>
</style>

<style name="Material.Widget.ProgressView.Circular" parent="Material.Widget.ProgressView">
<item name="pv_autostart">true</item>
<item name="pv_circular">true</item>
<item name="pv_progressStyle">@style/Material.Drawable.CircularProgress</item>
<item name="pv_progressMode">indeterminate</item>
</style>

<style name="Material.Widget.ProgressView.Circular.Determinate" parent="Material.Widget.ProgressView.Circular">
<item name="pv_progressStyle">@style/Material.Drawable.CircularProgress.Determinate</item>
<item name="pv_progressMode">determinate</item>
</style>

<style name="Material.Widget.ProgressView.Linear" parent="Material.Widget.ProgressView">
<item name="pv_autostart">true</item>
<item name="pv_circular">false</item>
<item name="pv_progressStyle">@style/Material.Drawable.LinearProgress</item>
<item name="pv_progressMode">indeterminate</item>
</style>

<style name="Material.Widget.ProgressView.Linear.Determinate" parent="Material.Widget.ProgressView.Linear">
<item name="pv_progressStyle">@style/Material.Drawable.LinearProgress.Determinate</item>
<item name="pv_progressMode">determinate</item>
</style>

<style name="Material.Widget.ProgressView.Linear.Query" parent="Material.Widget.ProgressView.Linear">
<item name="pv_progressStyle">@style/Material.Drawable.LinearProgress.Query</item>
<item name="pv_progressMode">query</item>
</style>

<style name="Material.Widget.ProgressView.Linear.Buffer" parent="Material.Widget.ProgressView.Linear">
<item name="pv_progressStyle">@style/Material.Drawable.LinearProgress.Buffer</item>
<item name="pv_progressMode">buffer</item>
</style>
</resources>

 

open MyActivity.java file…


package com.example.materialprogressdailogdesign;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
import android.view.View;

import com.example.material.widget.ProgressView;

public class MainActivity extends Activity implements Callback{
private ProgressView pv_circular;
private ProgressView pv_circular_colors;
private ProgressView pv_circular_inout;
private ProgressView pv_circular_inout_colors;
private ProgressView pv_circular_determinate_in_out;
private ProgressView pv_circular_determinate;
private ProgressView pv_linear;
private ProgressView pv_linear_colors;
private ProgressView pv_linear_determinate;
private ProgressView pv_linear_query;
private ProgressView pv_linear_buffer;

private Handler mHandler;

private static final int MSG_START_PROGRESS = 1000;
private static final int MSG_STOP_PROGRESS = 1001;
private static final int MSG_UPDATE_PROGRESS = 1002;
private static final int MSG_UPDATE_QUERY_PROGRESS = 1003;
private static final int MSG_UPDATE_BUFFER_PROGRESS = 1004;

private static final long PROGRESS_INTERVAL = 7000;
private static final long START_DELAY = 2000;
private static final long PROGRESS_UPDATE_INTERVAL = PROGRESS_INTERVAL / 100;
private static final long START_QUERY_DELAY = PROGRESS_INTERVAL / 2;
private static final long QUERY_PROGRESS_UPDATE_INTERVAL = (PROGRESS_INTERVAL - START_QUERY_DELAY) / 100;
private static final long BUFFER_PROGRESS_UPDATE_INTERVAL = (PROGRESS_INTERVAL - START_QUERY_DELAY) / 100;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pv_circular = (ProgressView)findViewById(R.id.progress_pv_circular);
pv_circular_colors = (ProgressView)findViewById(R.id.progress_pv_circular_colors);
pv_circular_inout = (ProgressView)findViewById(R.id.progress_pv_circular_inout);
pv_circular_inout_colors = (ProgressView)findViewById(R.id.progress_pv_circular_inout_colors);
pv_circular_determinate_in_out = (ProgressView)findViewById(R.id.progress_pv_circular_determinate_in_out);
pv_circular_determinate = (ProgressView)findViewById(R.id.progress_pv_circular_determinate);
pv_linear = (ProgressView)findViewById(R.id.progress_pv_linear);
pv_linear_colors = (ProgressView)findViewById(R.id.progress_pv_linear_colors);
pv_linear_determinate = (ProgressView)findViewById(R.id.progress_pv_linear_determinate);
pv_linear_query = (ProgressView)findViewById(R.id.progress_pv_linear_query);
pv_linear_buffer = (ProgressView)findViewById(R.id.progress_pv_linear_buffer);

mHandler = new Handler(this);

}
@Override
public void onPause() {
super.onPause();

mHandler.removeCallbacksAndMessages(null);
pv_circular_determinate_in_out.setVisibility(View.GONE);
}

@Override
public void onResume() {
super.onResume();
mHandler.sendEmptyMessageDelayed(MSG_START_PROGRESS, START_DELAY);
}

@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_START_PROGRESS:
pv_circular.start();
pv_circular_colors.start();
pv_circular_inout.start();
pv_circular_inout_colors.start();
pv_circular_determinate_in_out.setProgress(0f);
pv_circular_determinate_in_out.start();
pv_circular_determinate.setProgress(0f);
pv_circular_determinate.start();
pv_linear.start();
pv_linear_colors.start();
pv_linear_determinate.setProgress(0f);
pv_linear_determinate.start();
pv_linear_query.setProgress(0f);
pv_linear_query.start();
pv_linear_buffer.setProgress(0f);
pv_linear_buffer.setSecondaryProgress(0f);
pv_linear_buffer.start();
mHandler.sendEmptyMessageDelayed(MSG_STOP_PROGRESS, PROGRESS_INTERVAL);
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_PROGRESS, PROGRESS_UPDATE_INTERVAL);
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_QUERY_PROGRESS, START_QUERY_DELAY);
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_BUFFER_PROGRESS, BUFFER_PROGRESS_UPDATE_INTERVAL);
break;
case MSG_UPDATE_QUERY_PROGRESS:
pv_linear_query.setProgress(pv_linear_query.getProgress() + 0.01f);

if(pv_linear_query.getProgress() < 1f)
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_QUERY_PROGRESS, QUERY_PROGRESS_UPDATE_INTERVAL);
else
pv_linear_query.stop();
break;
case MSG_UPDATE_BUFFER_PROGRESS:
pv_linear_buffer.setSecondaryProgress(pv_linear_buffer.getSecondaryProgress() + 0.01f);

if(pv_linear_buffer.getSecondaryProgress() < 1f)
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_BUFFER_PROGRESS, BUFFER_PROGRESS_UPDATE_INTERVAL);
break;
case MSG_UPDATE_PROGRESS:
pv_circular_determinate_in_out.setProgress(pv_circular_determinate_in_out.getProgress() + 0.01f);
pv_circular_determinate.setProgress(pv_circular_determinate.getProgress() + 0.01f);

pv_linear_determinate.setProgress(pv_linear_determinate.getProgress() + 0.01f);
pv_linear_buffer.setProgress(pv_linear_buffer.getProgress() + 0.01f);
if(pv_circular_determinate_in_out.getProgress() < 1f)
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_PROGRESS, PROGRESS_UPDATE_INTERVAL);
else{
pv_circular_determinate_in_out.stop();
pv_circular_determinate.stop();
pv_linear_determinate.stop();
pv_linear_buffer.stop();
}
break;
case MSG_STOP_PROGRESS:
pv_circular.stop();
pv_circular_colors.stop();
pv_circular_inout.stop();
pv_circular_inout_colors.stop();
pv_linear.stop();
pv_linear_colors.stop();
mHandler.sendEmptyMessageDelayed(MSG_START_PROGRESS, START_DELAY);
break;
}
return false;
}

}

ProgressView.java

 


package com.example.material.widget;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;

import com.example.material.drawable.CircularProgressDrawable;
import com.example.material.drawable.LinearProgressDrawable;
import com.example.materialprogressdailogdesign.R;

public class ProgressView extends View {

private boolean mAutostart;
private boolean mCircular;
private int mProgressId;

public static final int MODE_DETERMINATE = 0;
public static final int MODE_INDETERMINATE = 1;
public static final int MODE_BUFFER = 2;
public static final int MODE_QUERY = 3;

private Drawable mProgressDrawable;

public ProgressView(Context context) {
this(context, null, 0, 0);
}

public ProgressView(Context context, AttributeSet attrs) {
this(context, attrs, 0, 0);
}

public ProgressView(Context context, AttributeSet attrs, int defStyleAttr){
this(context, attrs, defStyleAttr, 0);
}

@SuppressWarnings("deprecation")
@TargetApi(android.os.Build.VERSION_CODES.JELLY_BEAN)
public ProgressView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr);

init(context, attrs, defStyleAttr, defStyleRes);
}

private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
applyStyle(context, attrs, defStyleAttr, defStyleRes);
}

public void applyStyle(int resId){
applyStyle(getContext(), null, 0, resId);
}

private void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProgressView, defStyleAttr, defStyleRes);
mAutostart = a.getBoolean(R.styleable.ProgressView_pv_autostart, true);
mCircular = a.getBoolean(R.styleable.ProgressView_pv_circular, true);
mProgressId = a.getResourceId(R.styleable.ProgressView_pv_progressStyle, 0);

a.recycle();

if(mProgressId == 0)
mProgressId = mCircular ? R.style.Material_Drawable_CircularProgress : R.style.Material_Drawable_LinearProgress;

if(mCircular)
mProgressDrawable = new CircularProgressDrawable.Builder(context, mProgressId).build();
else
mProgressDrawable = new LinearProgressDrawable.Builder(context, mProgressId).build();

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
setBackground(mProgressDrawable);
else
setBackgroundDrawable(mProgressDrawable);
}

@Override
public void setVisibility(int v) {
if(getVisibility() != v) {
super.setVisibility(v);

if (getProgressMode() == MODE_INDETERMINATE && mAutostart) {
if (v == GONE || v == INVISIBLE)
stop();
else
start();
}
}
}

@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);

if (getProgressMode() == MODE_INDETERMINATE && mAutostart) {
if (visibility == GONE || visibility == INVISIBLE)
stop();
else
start();
}
}

@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (getProgressMode() == MODE_INDETERMINATE && mAutostart)
start();
}

@Override
protected void onDetachedFromWindow() {
if (getProgressMode() == MODE_INDETERMINATE && mAutostart)
stop();

super.onDetachedFromWindow();
}

public int getProgressMode(){
if(mCircular)
return ((CircularProgressDrawable)mProgressDrawable).getProgressMode();
else
return ((LinearProgressDrawable)mProgressDrawable).getProgressMode();
}

public float getProgress(){
if(mCircular)
return ((CircularProgressDrawable)mProgressDrawable).getProgress();
else
return ((LinearProgressDrawable)mProgressDrawable).getProgress();
}

public float getSecondaryProgress(){
if(mCircular)
return ((CircularProgressDrawable)mProgressDrawable).getSecondaryProgress();
else
return ((LinearProgressDrawable)mProgressDrawable).getSecondaryProgress();
}

public void setProgress(float percent){
if(mCircular)
((CircularProgressDrawable)mProgressDrawable).setProgress(percent);
else
((LinearProgressDrawable)mProgressDrawable).setProgress(percent);
}

public void setSecondaryProgress(float percent){
if(mCircular)
((CircularProgressDrawable)mProgressDrawable).setSecondaryProgress(percent);
else
((LinearProgressDrawable)mProgressDrawable).setSecondaryProgress(percent);
}

public void start(){
if(mProgressDrawable != null)
((Animatable)mProgressDrawable).start();
}

public void stop(){
if(mProgressDrawable != null)
((Animatable)mProgressDrawable).stop();
}

}

ViewUtil.java


package com.example.material.util;

import java.util.concurrent.atomic.AtomicInteger;

import android.annotation.SuppressLint;

public class ViewUtil {

public static final long FRAME_DURATION = 1000 / 60;

private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);

@SuppressLint("NewApi")
public static int generateViewId() {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
for (;;) {
final int result = sNextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF)
newValue = 1; // Roll over to 1, not 0.
if (sNextGeneratedId.compareAndSet(result, newValue))
return result;
}
}
else
return android.view.View.generateViewId();
}

public static boolean hasState(int[] states, int state){
if(states == null)
return false;

for (int state1 : states)
if (state1 == state)
return true;

return false;
}
}

TypefaceUtil.java


package com.example.material.util;

import android.content.Context;
import android.graphics.Typeface;

import java.util.HashMap;

/**
* Created by Rey on 12/23/2014.
*/
public class TypefaceUtil {

private static final HashMap<String, Typeface> sCachedFonts = new HashMap<String, Typeface>();
private static final String PREFIX_ASSET = "asset:";

private TypefaceUtil() {
}

/**
* @param familyName if start with 'asset:' prefix, then load font from asset folder.
* @return
*/
public static Typeface load(Context context, String familyName, int style) {
if(familyName != null && familyName.startsWith(PREFIX_ASSET))
synchronized (sCachedFonts) {
try {
if (!sCachedFonts.containsKey(familyName)) {
final Typeface typeface = Typeface.createFromAsset(context.getAssets(), familyName);
sCachedFonts.put(familyName, typeface);
return typeface;
}
} catch (Exception e) {
return Typeface.DEFAULT;
}

return sCachedFonts.get(familyName);
}

return Typeface.create(familyName, style);
}
}

ThemeUtil.java


package com.example.material.util;

import com.example.materialprogressdailogdesign.R;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.os.Build;
import android.support.v7.internal.widget.TintTypedArray;
import android.util.TypedValue;

public class ThemeUtil {

private static TypedValue value;

public static int dpToPx(Context context, int dp){
return (int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics()) + 0.5f);
}

public static int spToPx(Context context, int sp){
return (int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics()) + 0.5f);
}

private static int getColor(Context context, int id, int defaultValue){
if(value == null)
value = new TypedValue();

try{
Theme theme = context.getTheme();
if(theme != null && theme.resolveAttribute(id, value, true)){
if (value.type >= TypedValue.TYPE_FIRST_INT && value.type <= TypedValue.TYPE_LAST_INT)
return value.data;
else if (value.type == TypedValue.TYPE_STRING)
return context.getResources().getColor(value.resourceId);
}
}
catch(Exception ex){}

return defaultValue;
}

public static int windowBackground(Context context, int defaultValue){
return getColor(context, android.R.attr.windowBackground, defaultValue);
}

public static int textColorPrimary(Context context, int defaultValue){
return getColor(context, android.R.attr.textColorPrimary, defaultValue);
}

public static int textColorSecondary(Context context, int defaultValue){
return getColor(context, android.R.attr.textColorSecondary, defaultValue);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static int colorPrimary(Context context, int defaultValue){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return getColor(context, android.R.attr.colorPrimary, defaultValue);

return getColor(context, R.attr.colorPrimary, defaultValue);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static int colorPrimaryDark(Context context, int defaultValue){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return getColor(context, android.R.attr.colorPrimaryDark, defaultValue);

return getColor(context, R.attr.colorPrimaryDark, defaultValue);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static int colorAccent(Context context, int defaultValue){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return getColor(context, android.R.attr.colorAccent, defaultValue);

return getColor(context, R.attr.colorAccent, defaultValue);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static int colorControlNormal(Context context, int defaultValue){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return getColor(context, android.R.attr.colorControlNormal, defaultValue);

return getColor(context, R.attr.colorControlNormal, defaultValue);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static int colorControlActivated(Context context, int defaultValue){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return getColor(context, android.R.attr.colorControlActivated, defaultValue);

return getColor(context, R.attr.colorControlActivated, defaultValue);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static int colorControlHighlight(Context context, int defaultValue){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return getColor(context, android.R.attr.colorControlHighlight, defaultValue);

return getColor(context, R.attr.colorControlHighlight, defaultValue);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static int colorButtonNormal(Context context, int defaultValue){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return getColor(context, android.R.attr.colorButtonNormal, defaultValue);

return getColor(context, R.attr.colorButtonNormal, defaultValue);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static int colorSwitchThumbNormal(Context context, int defaultValue){
return getColor(context, R.attr.colorSwitchThumbNormal, defaultValue);
}

public static int getType(TypedArray array, int index){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return array.getType(index);
else{
TypedValue value = array.peekValue(index);
return value == null ? TypedValue.TYPE_NULL : value.type;
}
}

public static CharSequence getString(TypedArray array, int index, CharSequence defaultValue){
String result = array.getString(index);
return result == null ? defaultValue : result;
}

public static CharSequence getString(TintTypedArray array, int index, CharSequence defaultValue){
String result = array.getString(index);
return result == null ? defaultValue : result;
}
}

ColorUtil.java


package com.example.material.util;

import android.graphics.Color;

public class ColorUtil {

private static int getMiddleValue(int prev, int next, float factor){
return Math.round(prev + (next - prev) * factor);
}

public static int getMiddleColor(int prevColor, int curColor, float factor){
if(prevColor == curColor)
return curColor;

if(factor == 0f)
return prevColor;
else if(factor == 1f)
return curColor;

int a = getMiddleValue(Color.alpha(prevColor), Color.alpha(curColor), factor);
int r = getMiddleValue(Color.red(prevColor), Color.red(curColor), factor);
int g = getMiddleValue(Color.green(prevColor), Color.green(curColor), factor);
int b = getMiddleValue(Color.blue(prevColor), Color.blue(curColor), factor);

return Color.argb(a, r, g, b);
}

public static int getColor(int baseColor, float alphaPercent){
int alpha = Math.round(Color.alpha(baseColor) * alphaPercent);

return (baseColor & 0x00FFFFFF) | (alpha << 24);
}
}

 

LinearProgressDrawable.java


package com.example.material.drawable;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;

import com.example.material.util.ColorUtil;
import com.example.material.util.ThemeUtil;
import com.example.material.util.ViewUtil;
import com.example.material.widget.ProgressView;
import com.example.materialprogressdailogdesign.R;

public class LinearProgressDrawable extends Drawable implements Animatable {

private long mLastUpdateTime;
private long mLastProgressStateTime;
private long mLastRunStateTime;

private int mProgressState;

private static final int PROGRESS_STATE_STRETCH = 0;
private static final int PROGRESS_STATE_KEEP_STRETCH = 1;
private static final int PROGRESS_STATE_SHRINK = 2;
private static final int PROGRESS_STATE_KEEP_SHRINK = 3;

private int mRunState = RUN_STATE_STOPPED;

private static final int RUN_STATE_STOPPED = 0;
private static final int RUN_STATE_STARTING = 1;
private static final int RUN_STATE_STARTED = 2;
private static final int RUN_STATE_RUNNING = 3;
private static final int RUN_STATE_STOPPING = 4;

public static final int ALIGN_TOP = 0;
public static final int ALIGN_CENTER = 1;
public static final int ALIGN_BOTTOM = 2;

private Paint mPaint;
private float mStartLine;
private float mLineWidth;
private int mStrokeColorIndex;
private float mAnimTime;

private Path mPath;
private DashPathEffect mPathEffect;

private float mProgressPercent;
private float mSecondaryProgressPercent;
private int mMaxLineWidth;
private float mMaxLineWidthPercent;
private int mMinLineWidth;
private float mMinLineWidthPercent;
private int mStrokeSize;
private int mVerticalAlign;
private int[] mStrokeColors;
private int mStrokeSecondaryColor;
private boolean mReverse;
private int mTravelDuration;
private int mTransformDuration;
private int mKeepDuration;
private int mInAnimationDuration;
private int mOutAnimationDuration;
private int mProgressMode;
private Interpolator mTransformInterpolator;

private LinearProgressDrawable(float progressPercent, float secondaryProgressPercent, int maxLineWidth, float maxLineWidthPercent, int minLineWidth, float minLineWidthPercent, int strokeSize, int verticalAlign, int[] strokeColors, int strokeSecondaryColor, boolean reverse, int travelDuration, int transformDuration, int keepDuration, Interpolator transformInterpolator, int progressMode, int inAnimDuration, int outAnimDuration){
setProgress(progressPercent);
setSecondaryProgress(secondaryProgressPercent);
mMaxLineWidth = maxLineWidth;
mMaxLineWidthPercent = maxLineWidthPercent;
mMinLineWidth = minLineWidth;
mMinLineWidthPercent = minLineWidthPercent;
mStrokeSize = strokeSize;
mVerticalAlign = verticalAlign;
mStrokeColors = strokeColors;
mStrokeSecondaryColor = strokeSecondaryColor;
mReverse = reverse;
mTravelDuration = travelDuration;
mTransformDuration = transformDuration;
mKeepDuration = keepDuration;
mTransformInterpolator = transformInterpolator;
mProgressMode = progressMode;
mInAnimationDuration = inAnimDuration;
mOutAnimationDuration = outAnimDuration;

mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeJoin(Paint.Join.ROUND);

mPath = new Path();
}

@Override
public void draw(Canvas canvas) {
switch (mProgressMode) {
case ProgressView.MODE_DETERMINATE:
drawDeterminate(canvas);
break;
case ProgressView.MODE_INDETERMINATE:
drawIndeterminate(canvas);
break;
case ProgressView.MODE_BUFFER:
drawBuffer(canvas);
break;
case ProgressView.MODE_QUERY:
drawQuery(canvas);
break;
}
}

private void drawLinePath(Canvas canvas, float x1, float y1, float x2, float y2, Paint paint){
mPath.reset();
mPath.moveTo(x1, y1);
mPath.lineTo(x2, y2);
canvas.drawPath(mPath, paint);
}

private void drawDeterminate(Canvas canvas){
Rect bounds = getBounds();
int width = bounds.width();
float size = 0f;

if(mRunState == RUN_STATE_STARTING)
size = (float)mStrokeSize * Math.min(mInAnimationDuration, (SystemClock.uptimeMillis() - mLastRunStateTime)) / mInAnimationDuration;
else if(mRunState == RUN_STATE_STOPPING)
size = (float)mStrokeSize * Math.max(0, (mOutAnimationDuration - SystemClock.uptimeMillis() + mLastRunStateTime)) / mOutAnimationDuration;
else if(mRunState != RUN_STATE_STOPPED)
size = mStrokeSize;

if(size > 0){
float y = 0;
float lineWidth = width * mProgressPercent;

switch (mVerticalAlign) {
case ALIGN_TOP:
y = size / 2;
break;
case ALIGN_CENTER:
y = bounds.height() / 2f;
break;
case ALIGN_BOTTOM:
y = bounds.height() - size / 2;
break;
}

mPaint.setStrokeWidth(size);
mPaint.setStyle(Paint.Style.STROKE);

if(mProgressPercent != 1f){
mPaint.setColor(mStrokeSecondaryColor);

if(mReverse)
canvas.drawLine(0, y, width - lineWidth, y, mPaint);
else
canvas.drawLine(lineWidth, y, width, y, mPaint);
}

if(mProgressPercent != 0f){
mPaint.setColor(mStrokeColors[0]);
if(mReverse)
drawLinePath(canvas, width - lineWidth, y, width, y, mPaint);
else
drawLinePath(canvas, 0, y, lineWidth, y, mPaint);
}
}
}

private int getIndeterminateStrokeColor(){
if(mProgressState != PROGRESS_STATE_KEEP_SHRINK || mStrokeColors.length == 1)
return mStrokeColors[mStrokeColorIndex];

float value = Math.max(0f, Math.min(1f, (float)(SystemClock.uptimeMillis() - mLastProgressStateTime) / mKeepDuration));
int prev_index = mStrokeColorIndex == 0 ? mStrokeColors.length - 1 : mStrokeColorIndex - 1;

return ColorUtil.getMiddleColor(mStrokeColors[prev_index], mStrokeColors[mStrokeColorIndex], value);
}

private void drawIndeterminate(Canvas canvas){
Rect bounds = getBounds();
int width = bounds.width();
float size = 0f;

if(mRunState == RUN_STATE_STARTING)
size = (float)mStrokeSize * Math.min(mInAnimationDuration, (SystemClock.uptimeMillis() - mLastRunStateTime)) / mInAnimationDuration;
else if(mRunState == RUN_STATE_STOPPING)
size = (float)mStrokeSize * Math.max(0, (mOutAnimationDuration - SystemClock.uptimeMillis() + mLastRunStateTime)) / mOutAnimationDuration;
else if(mRunState != RUN_STATE_STOPPED)
size = mStrokeSize;

if(size > 0){
float y = 0;

switch (mVerticalAlign) {
case ALIGN_TOP:
y = size / 2;
break;
case ALIGN_CENTER:
y = bounds.height() / 2f;
break;
case ALIGN_BOTTOM:
y = bounds.height() - size / 2;
break;
}

mPaint.setStrokeWidth(size);
mPaint.setStyle(Paint.Style.STROKE);

float endLine = offset(mStartLine, mLineWidth, width);

if(mReverse){
if(endLine <= mStartLine){
mPaint.setColor(mStrokeSecondaryColor);
if(endLine > 0)
canvas.drawLine(0, y, endLine, y, mPaint);
if(mStartLine < width)
canvas.drawLine(mStartLine, y, width, y, mPaint);

mPaint.setColor(getIndeterminateStrokeColor());
drawLinePath(canvas, endLine, y, mStartLine, y, mPaint);
}
else{
mPaint.setColor(mStrokeSecondaryColor);
canvas.drawLine(mStartLine, y, endLine, y, mPaint);

mPaint.setColor(getIndeterminateStrokeColor());
mPath.reset();

if(mStartLine > 0){
mPath.moveTo(0, y);
mPath.lineTo(mStartLine, y);
}
if(endLine < width){
mPath.moveTo(endLine, y);
mPath.lineTo(width, y);
}

canvas.drawPath(mPath, mPaint);
}
}
else{
if(endLine >= mStartLine){
mPaint.setColor(mStrokeSecondaryColor);
if(mStartLine > 0)
canvas.drawLine(0, y, mStartLine, y, mPaint);
if(endLine < width)
canvas.drawLine(endLine, y, width, y, mPaint);

mPaint.setColor(getIndeterminateStrokeColor());
drawLinePath(canvas, mStartLine, y, endLine, y, mPaint);
}
else{
mPaint.setColor(mStrokeSecondaryColor);
canvas.drawLine(endLine, y, mStartLine, y, mPaint);

mPaint.setColor(getIndeterminateStrokeColor());
mPath.reset();

if(endLine > 0){
mPath.moveTo(0, y);
mPath.lineTo(endLine, y);
}
if(mStartLine < width){
mPath.moveTo(mStartLine, y);
mPath.lineTo(width, y);
}

canvas.drawPath(mPath, mPaint);
}
}
}
}

private PathEffect getPathEffect(){
if(mPathEffect == null)
mPathEffect = new DashPathEffect(new float[]{0.1f, mStrokeSize * 2}, 0f);

return mPathEffect;
}

private void drawBuffer(Canvas canvas){
Rect bounds = getBounds();
int width = bounds.width();
float size = 0f;

if(mRunState == RUN_STATE_STARTING)
size = (float)mStrokeSize * Math.min(mInAnimationDuration, (SystemClock.uptimeMillis() - mLastRunStateTime)) / mInAnimationDuration;
else if(mRunState == RUN_STATE_STOPPING)
size = (float)mStrokeSize * Math.max(0, (mOutAnimationDuration - SystemClock.uptimeMillis() + mLastRunStateTime)) / mOutAnimationDuration;
else if(mRunState != RUN_STATE_STOPPED)
size = mStrokeSize;

if(size > 0){
float y = 0;
float lineWidth = width * mProgressPercent;
float secondaryLineWidth = width * mSecondaryProgressPercent;

switch (mVerticalAlign) {
case ALIGN_TOP:
y = size / 2;
break;
case ALIGN_CENTER:
y = bounds.height() / 2f;
break;
case ALIGN_BOTTOM:
y = bounds.height() - size / 2;
break;
}

mPaint.setStyle(Paint.Style.STROKE);

if(mProgressPercent != 1f){
mPaint.setStrokeWidth(size);
mPaint.setColor(mStrokeSecondaryColor);
mPaint.setPathEffect(null);

if(mReverse)
drawLinePath(canvas, width - secondaryLineWidth, y, width - lineWidth, y, mPaint);
else
drawLinePath(canvas, secondaryLineWidth, y, lineWidth, y, mPaint);

mPaint.setStrokeWidth(mLineWidth);
mPaint.setPathEffect(getPathEffect());
float offset = mStrokeSize * 2 - mStartLine;

if(mReverse)
drawLinePath(canvas, -offset, y, width - secondaryLineWidth, y, mPaint);
else
drawLinePath(canvas, width + offset, y, secondaryLineWidth, y, mPaint);
}

if(mProgressPercent != 0f){
mPaint.setStrokeWidth(size);
mPaint.setColor(mStrokeColors[0]);
mPaint.setPathEffect(null);

if(mReverse)
drawLinePath(canvas, width - lineWidth, y, width, y, mPaint);
else
drawLinePath(canvas, 0, y, lineWidth, y, mPaint);
}
}
}

private int getQueryStrokeColor(){
return ColorUtil.getColor(mStrokeColors[0], mAnimTime);
}

private void drawQuery(Canvas canvas){
Rect bounds = getBounds();
int width = bounds.width();
float size = 0f;

if(mRunState == RUN_STATE_STARTING)
size = (float)mStrokeSize * Math.min(mInAnimationDuration, (SystemClock.uptimeMillis() - mLastRunStateTime)) / mInAnimationDuration;
else if(mRunState == RUN_STATE_STOPPING)
size = (float)mStrokeSize * Math.max(0, (mOutAnimationDuration - SystemClock.uptimeMillis() + mLastRunStateTime)) / mOutAnimationDuration;
else if(mRunState != RUN_STATE_STOPPED)
size = mStrokeSize;

if(size > 0){
float y = 0;

switch (mVerticalAlign) {
case ALIGN_TOP:
y = size / 2;
break;
case ALIGN_CENTER:
y = bounds.height() / 2f;
break;
case ALIGN_BOTTOM:
y = bounds.height() - size / 2;
break;
}

mPaint.setStrokeWidth(size);
mPaint.setStyle(Paint.Style.STROKE);

if(mProgressPercent != 1f){
mPaint.setColor(mStrokeSecondaryColor);
canvas.drawLine(0, y, width, y, mPaint);

if(mAnimTime < 1f){
float endLine = Math.max(0, Math.min(width, mStartLine + mLineWidth));
mPaint.setColor(getQueryStrokeColor());
drawLinePath(canvas, mStartLine, y, endLine, y, mPaint);
}
}

if(mProgressPercent != 0f){
float lineWidth = width * mProgressPercent;
mPaint.setColor(mStrokeColors[0]);

if(mReverse)
drawLinePath(canvas, width - lineWidth, y, width, y, mPaint);
else
drawLinePath(canvas, 0, y, lineWidth, y, mPaint);
}

}
}

@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}

@Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}

@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}

public int getProgressMode(){
return mProgressMode;
}

public float getProgress(){
return mProgressPercent;
}

public float getSecondaryProgress(){
return mSecondaryProgressPercent;
}

public void setProgress(float percent){
percent = Math.min(1f, Math.max(0f, percent));
if(mProgressPercent != percent){
mProgressPercent = percent;
if(isRunning())
invalidateSelf();
else if(mProgressPercent != 0f)
start();
}
}

public void setSecondaryProgress(float percent){
percent = Math.min(1f, Math.max(0f, percent));
if(mSecondaryProgressPercent != percent){
mSecondaryProgressPercent = percent;
if(isRunning())
invalidateSelf();
else if(mSecondaryProgressPercent != 0f)
start();
}
}

//Animation: based on http://cyrilmottier.com/2012/11/27/actionbar-on-the-move/

private void resetAnimation(){
mLastUpdateTime = SystemClock.uptimeMillis();
mLastProgressStateTime = mLastUpdateTime;
if(mProgressMode == ProgressView.MODE_INDETERMINATE){
mStartLine = mReverse ? getBounds().width() : 0;
mStrokeColorIndex = 0;
mLineWidth = mReverse ? -mMinLineWidth : mMinLineWidth;
mProgressState = PROGRESS_STATE_STRETCH;
}
else if(mProgressMode == ProgressView.MODE_BUFFER){
mStartLine = 0;
}
else if(mProgressMode == ProgressView.MODE_QUERY){
mStartLine = !mReverse ? getBounds().width() : 0;
mStrokeColorIndex = 0;
mLineWidth = !mReverse ? -mMaxLineWidth : mMaxLineWidth;
}
}

@Override
public void start() {
start(mInAnimationDuration > 0);
}

@Override
public void stop() {
stop(mOutAnimationDuration > 0);
}

private void start(boolean withAnimation){
if(isRunning())
return;

if(withAnimation){
mRunState = RUN_STATE_STARTING;
mLastRunStateTime = SystemClock.uptimeMillis();
}

resetAnimation();

scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);
invalidateSelf();
}

private void stop(boolean withAnimation){
if(!isRunning())
return;

if(withAnimation){
mLastRunStateTime = SystemClock.uptimeMillis();

if(mRunState == RUN_STATE_STARTED){
scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);
invalidateSelf();
}
mRunState = RUN_STATE_STOPPING;
}
else{
mRunState = RUN_STATE_STOPPED;
unscheduleSelf(mUpdater);
invalidateSelf();
}
}

@Override
public boolean isRunning() {
return mRunState != RUN_STATE_STOPPED;
}

@Override
public void scheduleSelf(Runnable what, long when) {
if(mRunState == RUN_STATE_STOPPED)
mRunState = mInAnimationDuration > 0 ? RUN_STATE_STARTING : RUN_STATE_RUNNING;
super.scheduleSelf(what, when);
}

private final Runnable mUpdater = new Runnable() {

@Override
public void run() {
update();
}

};

private void update(){
switch (mProgressMode) {
case ProgressView.MODE_DETERMINATE:
updateDeterminate();
break;
case ProgressView.MODE_INDETERMINATE:
updateIndeterminate();
break;
case ProgressView.MODE_BUFFER:
updateBuffer();
break;
case ProgressView.MODE_QUERY:
updateQuery();
break;
}
}

private void updateDeterminate(){
long curTime = SystemClock.uptimeMillis();

if(mRunState == RUN_STATE_STARTING){
if(curTime - mLastRunStateTime > mInAnimationDuration){
mRunState = RUN_STATE_STARTED;
return;
}
}
else if(mRunState == RUN_STATE_STOPPING){
if(curTime - mLastRunStateTime > mOutAnimationDuration){
stop(false);
return;
}
}

if(isRunning())
scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);

invalidateSelf();
}

private float offset(float pos, float offset, float max){
pos += offset;
if(pos > max)
return pos - max;
if(pos < 0)
return max + pos;
return pos;
}

private void updateIndeterminate(){
Rect bounds = getBounds();
int width = bounds.width();

long curTime = SystemClock.uptimeMillis();
float travelOffset = (float)(curTime - mLastUpdateTime) * width / mTravelDuration;
if(mReverse)
travelOffset = -travelOffset;
mLastUpdateTime = curTime;

switch (mProgressState) {
case PROGRESS_STATE_STRETCH:
if(mTransformDuration <= 0){
mLineWidth = mMinLineWidth == 0 ? width * mMinLineWidthPercent : mMinLineWidth;
if(mReverse)
mLineWidth = -mLineWidth;
mStartLine = offset(mStartLine, travelOffset, width);
mProgressState = PROGRESS_STATE_KEEP_STRETCH;
mLastProgressStateTime = curTime;
}
else{
float value = (curTime - mLastProgressStateTime) / (float)mTransformDuration;
float maxWidth = mMaxLineWidth == 0 ? width * mMaxLineWidthPercent : mMaxLineWidth;
float minWidth = mMinLineWidth == 0 ? width * mMinLineWidthPercent : mMinLineWidth;

mStartLine = offset(mStartLine, travelOffset, width);
mLineWidth = mTransformInterpolator.getInterpolation(value) * (maxWidth - minWidth) + minWidth;
if(mReverse)
mLineWidth = -mLineWidth;

if(value > 1f){
mLineWidth = mReverse ? -maxWidth : maxWidth;
mProgressState = PROGRESS_STATE_KEEP_STRETCH;
mLastProgressStateTime = curTime;
}
}
break;
case PROGRESS_STATE_KEEP_STRETCH:
mStartLine = offset(mStartLine, travelOffset, width);

if(curTime - mLastProgressStateTime > mKeepDuration){
mProgressState = PROGRESS_STATE_SHRINK;
mLastProgressStateTime = curTime;
}
break;
case PROGRESS_STATE_SHRINK:
if(mTransformDuration <= 0){
mLineWidth = mMinLineWidth == 0 ? width * mMinLineWidthPercent : mMinLineWidth;
if(mReverse)
mLineWidth = -mLineWidth;
mStartLine = offset(mStartLine, travelOffset, width);
mProgressState = PROGRESS_STATE_KEEP_SHRINK;
mLastProgressStateTime = curTime;
mStrokeColorIndex = (mStrokeColorIndex + 1) % mStrokeColors.length;
}
else{
float value = (curTime - mLastProgressStateTime) / (float)mTransformDuration;
float maxWidth = mMaxLineWidth == 0 ? width * mMaxLineWidthPercent : mMaxLineWidth;
float minWidth = mMinLineWidth == 0 ? width * mMinLineWidthPercent : mMinLineWidth;

float newLineWidth = (1f - mTransformInterpolator.getInterpolation(value)) * (maxWidth - minWidth) + minWidth;
if(mReverse)
newLineWidth = -newLineWidth;

mStartLine = offset(mStartLine, travelOffset + mLineWidth - newLineWidth, width);
mLineWidth = newLineWidth;

if(value > 1f){
mLineWidth = mReverse ? -minWidth : minWidth;
mProgressState = PROGRESS_STATE_KEEP_SHRINK;
mLastProgressStateTime = curTime;
mStrokeColorIndex = (mStrokeColorIndex + 1) % mStrokeColors.length;
}
}
break;
case PROGRESS_STATE_KEEP_SHRINK:
mStartLine = offset(mStartLine, travelOffset, width);

if(curTime - mLastProgressStateTime > mKeepDuration){
mProgressState = PROGRESS_STATE_STRETCH;
mLastProgressStateTime = curTime;
}
break;
}

if(mRunState == RUN_STATE_STARTING){
if(curTime - mLastRunStateTime > mInAnimationDuration)
mRunState = RUN_STATE_RUNNING;
}
else if(mRunState == RUN_STATE_STOPPING){
if(curTime - mLastRunStateTime > mOutAnimationDuration){
stop(false);
return;
}
}

if (isRunning())
scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);

invalidateSelf();
}

private void updateBuffer(){
long curTime = SystemClock.uptimeMillis();
float maxDistance = mStrokeSize * 2;
mStartLine += maxDistance * (float)(curTime - mLastUpdateTime) / mTravelDuration;
while(mStartLine > maxDistance)
mStartLine -= maxDistance;
mLastUpdateTime = curTime;

switch (mProgressState) {
case PROGRESS_STATE_STRETCH:
if(mTransformDuration <= 0){
mProgressState = PROGRESS_STATE_KEEP_STRETCH;
mLastProgressStateTime = curTime;
}
else{
float value = (curTime - mLastProgressStateTime) / (float)mTransformDuration;
mLineWidth = mTransformInterpolator.getInterpolation(value) * mStrokeSize;

if(value > 1f){
mLineWidth = mStrokeSize;
mProgressState = PROGRESS_STATE_KEEP_STRETCH;
mLastProgressStateTime = curTime;
}
}
break;
case PROGRESS_STATE_KEEP_STRETCH:
if(curTime - mLastProgressStateTime > mKeepDuration){
mProgressState = PROGRESS_STATE_SHRINK;
mLastProgressStateTime = curTime;
}
break;
case PROGRESS_STATE_SHRINK:
if(mTransformDuration <= 0){
mProgressState = PROGRESS_STATE_KEEP_SHRINK;
mLastProgressStateTime = curTime;
}
else{
float value = (curTime - mLastProgressStateTime) / (float)mTransformDuration;
mLineWidth = (1f - mTransformInterpolator.getInterpolation(value)) * mStrokeSize;

if(value > 1f){
mLineWidth = 0;
mProgressState = PROGRESS_STATE_KEEP_SHRINK;
mLastProgressStateTime = curTime;
}
}
break;
case PROGRESS_STATE_KEEP_SHRINK:
if(curTime - mLastProgressStateTime > mKeepDuration){
mProgressState = PROGRESS_STATE_STRETCH;
mLastProgressStateTime = curTime;
}
break;
}

if(mRunState == RUN_STATE_STARTING){
if(curTime - mLastRunStateTime > mInAnimationDuration)
mRunState = RUN_STATE_RUNNING;
}
else if(mRunState == RUN_STATE_STOPPING){
if(curTime - mLastRunStateTime > mOutAnimationDuration){
stop(false);
return;
}
}

if(isRunning())
scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);

invalidateSelf();
}

private void updateQuery(){
long curTime = SystemClock.uptimeMillis();
mAnimTime = (float)(curTime - mLastProgressStateTime) / mTravelDuration;
boolean requestUpdate = mRunState == RUN_STATE_STOPPING || mProgressPercent == 0 || mAnimTime < 1f;

if(mAnimTime > 1f){
mLastProgressStateTime = Math.round(curTime - (mAnimTime - 1f) * mTravelDuration);
mAnimTime -= 1f;
}

if(requestUpdate && mRunState != RUN_STATE_STOPPING){
Rect bounds = getBounds();
int width = bounds.width();

float maxWidth = mMaxLineWidth == 0 ? width * mMaxLineWidthPercent : mMaxLineWidth;
float minWidth = mMinLineWidth == 0 ? width * mMinLineWidthPercent : mMinLineWidth;
mLineWidth = mTransformInterpolator.getInterpolation(mAnimTime) * (minWidth - maxWidth) + maxWidth;
if(mReverse)
mLineWidth = -mLineWidth;

mStartLine = mReverse ? mTransformInterpolator.getInterpolation(mAnimTime) * (width + minWidth) : ((1f - mTransformInterpolator.getInterpolation(mAnimTime)) * (width + minWidth) - minWidth);
}

if(mRunState == RUN_STATE_STARTING){
if(curTime - mLastRunStateTime > mInAnimationDuration)
mRunState = RUN_STATE_RUNNING;
}
else if(mRunState == RUN_STATE_STOPPING){
if(curTime - mLastRunStateTime > mOutAnimationDuration){
stop(false);
return;
}
}

if (isRunning()){
if(requestUpdate)
scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);
else if(mRunState == RUN_STATE_RUNNING)
mRunState = RUN_STATE_STARTED;
}

invalidateSelf();
}

public static class Builder{
private float mProgressPercent = 0;
private float mSecondaryProgressPercent = 0;
private int mMaxLineWidth;
private float mMaxLineWidthPercent;
private int mMinLineWidth;
private float mMinLineWidthPercent;
private int mStrokeSize = 8;
private int mVerticalAlign = LinearProgressDrawable.ALIGN_BOTTOM;
private int[] mStrokeColors;
private int mStrokeSecondaryColor;
private boolean mReverse = false;
private int mTravelDuration = 1000;
private int mTransformDuration = 800;
private int mKeepDuration = 200;
private Interpolator mTransformInterpolator;
private int mProgressMode = ProgressView.MODE_INDETERMINATE;
private int mInAnimationDuration = 400;
private int mOutAnimationDuration = 400;

public Builder(){}

public Builder(Context context, int defStyleRes){
this(context, null, 0, defStyleRes);
}

public Builder(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LinearProgressDrawable, defStyleAttr, defStyleRes);
int resId;

progressPercent(a.getFloat(R.styleable.LinearProgressDrawable_pv_progress, 0));
secondaryProgressPercent(a.getFloat(R.styleable.LinearProgressDrawable_pv_secondaryProgress, 0));

TypedValue value = a.peekValue(R.styleable.LinearProgressDrawable_lpd_maxLineWidth);
if(value == null)
maxLineWidth(0.75f);
else if(value.type == TypedValue.TYPE_FRACTION)
maxLineWidth(a.getFraction(R.styleable.LinearProgressDrawable_lpd_maxLineWidth, 1, 1, 0.75f));
else
maxLineWidth(a.getDimensionPixelSize(R.styleable.LinearProgressDrawable_lpd_maxLineWidth, 0));

value = a.peekValue(R.styleable.LinearProgressDrawable_lpd_minLineWidth);
if(value == null)
minLineWidth(0.25f);
else if(value.type == TypedValue.TYPE_FRACTION)
minLineWidth(a.getFraction(R.styleable.LinearProgressDrawable_lpd_minLineWidth, 1, 1, 0.25f));
else
minLineWidth(a.getDimensionPixelSize(R.styleable.LinearProgressDrawable_lpd_minLineWidth, 0));

strokeSize(a.getDimensionPixelSize(R.styleable.LinearProgressDrawable_lpd_strokeSize, ThemeUtil.dpToPx(context, 4)));
verticalAlign(a.getInteger(R.styleable.LinearProgressDrawable_lpd_verticalAlign, LinearProgressDrawable.ALIGN_BOTTOM));
strokeColors(a.getColor(R.styleable.LinearProgressDrawable_lpd_strokeColor, ThemeUtil.colorPrimary(context, 0xFF000000)));
if((resId = a.getResourceId(R.styleable.LinearProgressDrawable_lpd_strokeColors, 0)) != 0){
TypedArray ta = context.getResources().obtainTypedArray(resId);
int[] colors = new int[ta.length()];
for(int j = 0; j < ta.length(); j++)
colors[j] = ta.getColor(j, 0);
ta.recycle();
strokeColors(colors);
}
strokeSecondaryColor(a.getColor(R.styleable.LinearProgressDrawable_lpd_strokeSecondaryColor, 0));
reverse(a.getBoolean(R.styleable.LinearProgressDrawable_lpd_reverse, false));
travelDuration(a.getInteger(R.styleable.LinearProgressDrawable_lpd_travelDuration, context.getResources().getInteger(android.R.integer.config_longAnimTime)));
transformDuration(a.getInteger(R.styleable.LinearProgressDrawable_lpd_transformDuration, context.getResources().getInteger(android.R.integer.config_mediumAnimTime)));
keepDuration(a.getInteger(R.styleable.LinearProgressDrawable_lpd_keepDuration, context.getResources().getInteger(android.R.integer.config_shortAnimTime)));
if((resId = a.getResourceId(R.styleable.LinearProgressDrawable_lpd_transformInterpolator, 0)) != 0)
transformInterpolator(AnimationUtils.loadInterpolator(context, resId));
progressMode(a.getInteger(R.styleable.LinearProgressDrawable_pv_progressMode, ProgressView.MODE_INDETERMINATE));
inAnimDuration(a.getInteger(R.styleable.LinearProgressDrawable_lpd_inAnimDuration, context.getResources().getInteger(android.R.integer.config_mediumAnimTime)));
outAnimDuration(a.getInteger(R.styleable.LinearProgressDrawable_lpd_outAnimDuration, context.getResources().getInteger(android.R.integer.config_mediumAnimTime)));

a.recycle();
}

public LinearProgressDrawable build(){
if(mStrokeColors == null)
mStrokeColors = new int[]{0xFF0099FF};

if(mTransformInterpolator == null)
mTransformInterpolator = new DecelerateInterpolator();

return new LinearProgressDrawable(mProgressPercent, mSecondaryProgressPercent, mMaxLineWidth, mMaxLineWidthPercent, mMinLineWidth, mMinLineWidthPercent, mStrokeSize, mVerticalAlign, mStrokeColors, mStrokeSecondaryColor, mReverse, mTravelDuration, mTransformDuration, mKeepDuration, mTransformInterpolator, mProgressMode, mInAnimationDuration, mOutAnimationDuration);
}

public Builder secondaryProgressPercent(float percent){
mSecondaryProgressPercent = percent;
return this;
}

public Builder progressPercent(float percent){
mProgressPercent = percent;
return this;
}

public Builder maxLineWidth(int width){
mMaxLineWidth = width;
return this;
}

public Builder maxLineWidth(float percent){
mMaxLineWidthPercent = Math.max(0f, Math.min(1f, percent));
mMaxLineWidth = 0;
return this;
}

public Builder minLineWidth(int width){
mMinLineWidth = width;
return this;
}

public Builder minLineWidth(float percent){
mMinLineWidthPercent = Math.max(0f, Math.min(1f, percent));
mMinLineWidth = 0;
return this;
}

public Builder strokeSize(int strokeSize){
mStrokeSize = strokeSize;
return this;
}

public Builder verticalAlign(int align){
mVerticalAlign = align;
return this;
}

public Builder strokeColors(int... strokeColors){
mStrokeColors = strokeColors;
return this;
}

public Builder strokeSecondaryColor(int color){
mStrokeSecondaryColor = color;
return this;
}

public Builder reverse(boolean reverse){
mReverse = reverse;
return this;
}

public Builder reverse(){
return reverse(true);
}

public Builder travelDuration(int duration){
mTravelDuration = duration;
return this;
}

public Builder transformDuration(int duration){
mTransformDuration = duration;
return this;
}

public Builder keepDuration(int duration){
mKeepDuration = duration;
return this;
}

public Builder transformInterpolator(Interpolator interpolator){
mTransformInterpolator = interpolator;
return this;
}

public Builder progressMode(int mode){
mProgressMode = mode;
return this;
}

public Builder inAnimDuration(int duration){
mInAnimationDuration = duration;
return this;
}

public Builder outAnimDuration(int duration){
mOutAnimationDuration = duration;
return this;
}

}
}

CircularProgressDrawable.java


package com.example.material.drawable;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;

import com.example.material.util.ColorUtil;
import com.example.material.util.ThemeUtil;
import com.example.material.util.ViewUtil;
import com.example.material.widget.ProgressView;
import com.example.materialprogressdailogdesign.R;

public class CircularProgressDrawable extends Drawable implements Animatable {

private long mLastUpdateTime;
private long mLastProgressStateTime;
private long mLastRunStateTime;

private int mProgressState;

private static final int PROGRESS_STATE_HIDE = -1;
private static final int PROGRESS_STATE_STRETCH = 0;
private static final int PROGRESS_STATE_KEEP_STRETCH = 1;
private static final int PROGRESS_STATE_SHRINK = 2;
private static final int PROGRESS_STATE_KEEP_SHRINK = 3;

private int mRunState = RUN_STATE_STOPPED;

private static final int RUN_STATE_STOPPED = 0;
private static final int RUN_STATE_STARTING = 1;
private static final int RUN_STATE_STARTED = 2;
private static final int RUN_STATE_RUNNING = 3;
private static final int RUN_STATE_STOPPING = 4;

private Paint mPaint;
private RectF mRect;
private float mStartAngle;
private float mSweepAngle;
private int mStrokeColorIndex;

private int mPadding;
private float mInitialAngle;
private float mProgressPercent;
private float mSecondaryProgressPercent;
private float mMaxSweepAngle;
private float mMinSweepAngle;
private int mStrokeSize;
private int[] mStrokeColors;
private int mStrokeSecondaryColor;
private boolean mReverse;
private int mRotateDuration;
private int mTransformDuration;
private int mKeepDuration;
private float mInStepPercent;
private int[] mInColors;
private int mInAnimationDuration;
private int mOutAnimationDuration;
private int mProgressMode;
private Interpolator mTransformInterpolator;

private CircularProgressDrawable(int padding, float initialAngle, float progressPercent, float secondaryProgressPercent, float maxSweepAngle, float minSweepAngle, int strokeSize, int[] strokeColors, int strokeSecondaryColor, boolean reverse, int rotateDuration, int transformDuration, int keepDuration, Interpolator transformInterpolator, int progressMode, int inAnimDuration, float inStepPercent, int[] inStepColors, int outAnimDuration){
mPadding = padding;
mInitialAngle = initialAngle;
setProgress(progressPercent);
setSecondaryProgress(secondaryProgressPercent);
mMaxSweepAngle = maxSweepAngle;
mMinSweepAngle = minSweepAngle;
mStrokeSize = strokeSize;
mStrokeColors = strokeColors;
mStrokeSecondaryColor = strokeSecondaryColor;
mReverse = reverse;
mRotateDuration = rotateDuration;
mTransformDuration = transformDuration;
mKeepDuration = keepDuration;
mTransformInterpolator = transformInterpolator;
mProgressMode = progressMode;
mInAnimationDuration = inAnimDuration;
mInStepPercent = inStepPercent;
mInColors = inStepColors;
mOutAnimationDuration = outAnimDuration;

mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeJoin(Paint.Join.ROUND);

mRect = new RectF();
}

@Override
public void draw(Canvas canvas) {
switch (mProgressMode) {
case ProgressView.MODE_DETERMINATE:
drawDeterminate(canvas);
break;
case ProgressView.MODE_INDETERMINATE:
drawIndeterminate(canvas);
break;
}
}

private void drawDeterminate(Canvas canvas){
Rect bounds = getBounds();
float radius = 0f;
float size = 0f;

if(mRunState == RUN_STATE_STARTING){
size = (float)mStrokeSize * Math.min(mInAnimationDuration, (SystemClock.uptimeMillis() - mLastRunStateTime)) / mInAnimationDuration;
if(size > 0)
radius = (Math.min(bounds.width(), bounds.height()) - mPadding * 2 - mStrokeSize * 2 + size) / 2f;
}
else if(mRunState == RUN_STATE_STOPPING){
size = (float)mStrokeSize * Math.max(0, (mOutAnimationDuration - SystemClock.uptimeMillis() + mLastRunStateTime)) / mOutAnimationDuration;
if(size > 0)
radius = (Math.min(bounds.width(), bounds.height()) - mPadding * 2 - mStrokeSize * 2 + size) / 2f;
}
else if(mRunState != RUN_STATE_STOPPED){
size = mStrokeSize;
radius = (Math.min(bounds.width(), bounds.height()) - mPadding * 2 - mStrokeSize) / 2f;
}

if(radius > 0){
float x = (bounds.left + bounds.right) / 2f;
float y = (bounds.top + bounds.bottom) / 2f;

mPaint.setStrokeWidth(size);
mPaint.setStyle(Paint.Style.STROKE);

if(mProgressPercent == 1f){
mPaint.setColor(mStrokeColors[0]);
canvas.drawCircle(x, y, radius, mPaint);
}
else if(mProgressPercent == 0f){
mPaint.setColor(mStrokeSecondaryColor);
canvas.drawCircle(x, y, radius, mPaint);
}
else{
float sweepAngle = (mReverse ? -360 : 360) * mProgressPercent;

mRect.set(x - radius, y - radius, x + radius, y + radius);
mPaint.setColor(mStrokeSecondaryColor);
canvas.drawArc(mRect, mInitialAngle + sweepAngle, (mReverse ? -360 : 360) - sweepAngle, false, mPaint);

mPaint.setColor(mStrokeColors[0]);
canvas.drawArc(mRect, mInitialAngle, sweepAngle, false, mPaint);
}
}
}

private int getIndeterminateStrokeColor(){
if(mProgressState != PROGRESS_STATE_KEEP_SHRINK || mStrokeColors.length == 1)
return mStrokeColors[mStrokeColorIndex];

float value = Math.max(0f, Math.min(1f, (float)(SystemClock.uptimeMillis() - mLastProgressStateTime) / mKeepDuration));
int prev_index = mStrokeColorIndex == 0 ? mStrokeColors.length - 1 : mStrokeColorIndex - 1;

return ColorUtil.getMiddleColor(mStrokeColors[prev_index], mStrokeColors[mStrokeColorIndex], value);
}

private void drawIndeterminate(Canvas canvas){
if(mRunState == RUN_STATE_STARTING){
Rect bounds = getBounds();
float x = (bounds.left + bounds.right) / 2f;
float y = (bounds.top + bounds.bottom) / 2f;
float maxRadius = (Math.min(bounds.width(), bounds.height()) - mPadding * 2) / 2f;

float stepTime = 1f / (mInStepPercent * (mInColors.length + 2) + 1);
float time = (float)(SystemClock.uptimeMillis() - mLastRunStateTime) / mInAnimationDuration;
float steps =  time / stepTime;

float outerRadius = 0f;
float innerRadius = 0f;

for(int i = (int)Math.floor(steps); i >= 0; i--){
innerRadius = outerRadius;
outerRadius = Math.min(1f, (steps - i) * mInStepPercent) * maxRadius;

if(i >= mInColors.length)
continue;

if(innerRadius == 0){
mPaint.setColor(mInColors[i]);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(x, y, outerRadius, mPaint);
}
else if(outerRadius > innerRadius){
float radius = (innerRadius + outerRadius) / 2;
mRect.set(x - radius, y - radius, x + radius, y + radius);

mPaint.setStrokeWidth(outerRadius - innerRadius);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(mInColors[i]);

canvas.drawCircle(x, y, radius, mPaint);
}
else
break;
}

if(mProgressState == PROGRESS_STATE_HIDE){
if(steps >= 1 / mInStepPercent || time >= 1)
resetAnimation();
}
else{
float radius = maxRadius - mStrokeSize / 2f;

mRect.set(x - radius, y - radius, x + radius, y + radius);
mPaint.setStrokeWidth(mStrokeSize);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(getIndeterminateStrokeColor());

canvas.drawArc(mRect, mStartAngle, mSweepAngle, false, mPaint);
}
}
else if(mRunState == RUN_STATE_STOPPING){
float size = (float)mStrokeSize * Math.max(0, (mOutAnimationDuration - SystemClock.uptimeMillis() + mLastRunStateTime)) / mOutAnimationDuration;

if(size > 0){
Rect bounds = getBounds();
float radius = (Math.min(bounds.width(), bounds.height()) - mPadding * 2 - mStrokeSize * 2 + size) / 2f;
float x = (bounds.left + bounds.right) / 2f;
float y = (bounds.top + bounds.bottom) / 2f;

mRect.set(x - radius, y - radius, x + radius, y + radius);
mPaint.setStrokeWidth(size);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(getIndeterminateStrokeColor());

canvas.drawArc(mRect, mStartAngle, mSweepAngle, false, mPaint);
}
}
else if(mRunState != RUN_STATE_STOPPED){
Rect bounds = getBounds();
float radius = (Math.min(bounds.width(), bounds.height()) - mPadding * 2 - mStrokeSize) / 2f;
float x = (bounds.left + bounds.right) / 2f;
float y = (bounds.top + bounds.bottom) / 2f;

mRect.set(x - radius, y - radius, x + radius, y + radius);
mPaint.setStrokeWidth(mStrokeSize);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(getIndeterminateStrokeColor());

canvas.drawArc(mRect, mStartAngle, mSweepAngle, false, mPaint);
}
}

@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}

@Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}

@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}

public int getProgressMode(){
return mProgressMode;
}

public float getProgress(){
return mProgressPercent;
}

public float getSecondaryProgress(){
return mSecondaryProgressPercent;
}

public void setProgress(float percent){
percent = Math.min(1f, Math.max(0f, percent));
if(mProgressPercent != percent){
mProgressPercent = percent;
if(isRunning())
invalidateSelf();
else if(mProgressPercent != 0f)
start();
}
}

public void setSecondaryProgress(float percent){
percent = Math.min(1f, Math.max(0f, percent));
if(mSecondaryProgressPercent != percent){
mSecondaryProgressPercent = percent;
if(isRunning())
invalidateSelf();
else if(mSecondaryProgressPercent != 0f)
start();
}
}

//Animation: based on http://cyrilmottier.com/2012/11/27/actionbar-on-the-move/

private void resetAnimation(){
mLastUpdateTime = SystemClock.uptimeMillis();
mLastProgressStateTime = mLastUpdateTime;
mStartAngle = mInitialAngle;
mStrokeColorIndex = 0;
mSweepAngle = mReverse ? -mMinSweepAngle : mMinSweepAngle;
mProgressState = PROGRESS_STATE_STRETCH;
}

@Override
public void start() {
start(mInAnimationDuration > 0);
}

@Override
public void stop() {
stop(mOutAnimationDuration > 0);
}

private void start(boolean withAnimation){
if(isRunning())
return;

if(withAnimation){
mRunState = RUN_STATE_STARTING;
mLastRunStateTime = SystemClock.uptimeMillis();
mProgressState = PROGRESS_STATE_HIDE;
}
else
resetAnimation();

scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);
invalidateSelf();
}

private void stop(boolean withAnimation){
if(!isRunning())
return;

if(withAnimation){
mLastRunStateTime = SystemClock.uptimeMillis();
if(mRunState == RUN_STATE_STARTED){
scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);
invalidateSelf();
}
mRunState = RUN_STATE_STOPPING;
}
else{
mRunState = RUN_STATE_STOPPED;
unscheduleSelf(mUpdater);
invalidateSelf();
}
}

@Override
public boolean isRunning() {
return mRunState != RUN_STATE_STOPPED;
}

@Override
public void scheduleSelf(Runnable what, long when) {
if(mRunState == RUN_STATE_STOPPED)
mRunState = mInAnimationDuration > 0 ? RUN_STATE_STARTING : RUN_STATE_RUNNING;
super.scheduleSelf(what, when);
}

private final Runnable mUpdater = new Runnable() {

@Override
public void run() {
update();
}

};

private void update(){
switch (mProgressMode) {
case ProgressView.MODE_DETERMINATE:
updateDeterminate();
break;
case ProgressView.MODE_INDETERMINATE:
updateIndeterminate();
break;
}
}

private void updateDeterminate(){
long curTime = SystemClock.uptimeMillis();

if(mRunState == RUN_STATE_STARTING){
if(curTime - mLastRunStateTime > mInAnimationDuration){
mRunState = RUN_STATE_STARTED;
return;
}
}
else if(mRunState == RUN_STATE_STOPPING){
if(curTime - mLastRunStateTime > mOutAnimationDuration){
stop(false);
return;
}
}

if(isRunning())
scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);

invalidateSelf();
}

private void updateIndeterminate(){
//update animation
long curTime = SystemClock.uptimeMillis();
float rotateOffset = (curTime - mLastUpdateTime) * 360f / mRotateDuration;
if(mReverse)
rotateOffset = -rotateOffset;
mLastUpdateTime = curTime;

switch (mProgressState) {
case PROGRESS_STATE_STRETCH:
if(mTransformDuration <= 0){
mSweepAngle = mReverse ? -mMinSweepAngle : mMinSweepAngle;
mProgressState = PROGRESS_STATE_KEEP_STRETCH;
mStartAngle += rotateOffset;
mLastProgressStateTime = curTime;
}
else{
float value = (curTime - mLastProgressStateTime) / (float)mTransformDuration;
float maxAngle = mReverse ? -mMaxSweepAngle : mMaxSweepAngle;
float minAngle = mReverse ? -mMinSweepAngle : mMinSweepAngle;

mStartAngle += rotateOffset;
mSweepAngle = mTransformInterpolator.getInterpolation(value) * (maxAngle - minAngle) + minAngle;

if(value > 1f){
mSweepAngle = maxAngle;
mProgressState = PROGRESS_STATE_KEEP_STRETCH;
mLastProgressStateTime = curTime;
}
}
break;
case PROGRESS_STATE_KEEP_STRETCH:
mStartAngle += rotateOffset;

if(curTime - mLastProgressStateTime > mKeepDuration){
mProgressState = PROGRESS_STATE_SHRINK;
mLastProgressStateTime = curTime;
}
break;
case PROGRESS_STATE_SHRINK:
if(mTransformDuration <= 0){
mSweepAngle = mReverse ? -mMinSweepAngle : mMinSweepAngle;
mProgressState = PROGRESS_STATE_KEEP_SHRINK;
mStartAngle += rotateOffset;
mLastProgressStateTime = curTime;
mStrokeColorIndex = (mStrokeColorIndex + 1) % mStrokeColors.length;
}
else{
float value = (curTime - mLastProgressStateTime) / (float)mTransformDuration;
float maxAngle = mReverse ? -mMaxSweepAngle : mMaxSweepAngle;
float minAngle = mReverse ? -mMinSweepAngle : mMinSweepAngle;

float newSweepAngle = (1f - mTransformInterpolator.getInterpolation(value)) * (maxAngle - minAngle) + minAngle;
mStartAngle += rotateOffset + mSweepAngle - newSweepAngle;
mSweepAngle = newSweepAngle;

if(value > 1f){
mSweepAngle = minAngle;
mProgressState = PROGRESS_STATE_KEEP_SHRINK;
mLastProgressStateTime = curTime;
mStrokeColorIndex = (mStrokeColorIndex + 1) % mStrokeColors.length;
}
}
break;
case PROGRESS_STATE_KEEP_SHRINK:
mStartAngle += rotateOffset;

if(curTime - mLastProgressStateTime > mKeepDuration){
mProgressState = PROGRESS_STATE_STRETCH;
mLastProgressStateTime = curTime;
}
break;
}

if(mRunState == RUN_STATE_STARTING){
if(curTime - mLastRunStateTime > mInAnimationDuration){
mRunState = RUN_STATE_RUNNING;
if(mProgressState == PROGRESS_STATE_HIDE)
resetAnimation();
}
}
else if(mRunState == RUN_STATE_STOPPING){
if(curTime - mLastRunStateTime > mOutAnimationDuration){
stop(false);
return;
}
}

if (isRunning())
scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);

invalidateSelf();
}

public static class Builder{
private int mPadding;
private float mInitialAngle;
private float mProgressPercent;
private float mSecondaryProgressPercent;
private float mMaxSweepAngle;
private float mMinSweepAngle;
private int mStrokeSize;
private int[] mStrokeColors;
private int mStrokeSecondaryColor;
private boolean mReverse;
private int mRotateDuration;
private int mTransformDuration;
private int mKeepDuration;
private Interpolator mTransformInterpolator;
private int mProgressMode;
private float mInStepPercent;
private int[] mInColors;
private int mInAnimationDuration;
private int mOutAnimationDuration;

public Builder(){}

public Builder(Context context, int defStyleRes){
this(context, null, 0, defStyleRes);
}

public Builder(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircularProgressDrawable, defStyleAttr, defStyleRes);
int resId;

padding(a.getDimensionPixelSize(R.styleable.CircularProgressDrawable_cpd_padding, 0));
initialAngle(a.getInteger(R.styleable.CircularProgressDrawable_cpd_initialAngle, 0));
progressPercent(a.getFloat(R.styleable.CircularProgressDrawable_pv_progress, 0));
secondaryProgressPercent(a.getFloat(R.styleable.CircularProgressDrawable_pv_secondaryProgress, 0));
maxSweepAngle(a.getInteger(R.styleable.CircularProgressDrawable_cpd_maxSweepAngle, 270));
minSweepAngle(a.getInteger(R.styleable.CircularProgressDrawable_cpd_minSweepAngle, 1));
strokeSize(a.getDimensionPixelSize(R.styleable.CircularProgressDrawable_cpd_strokeSize, ThemeUtil.dpToPx(context, 4)));
strokeColors(a.getColor(R.styleable.CircularProgressDrawable_cpd_strokeColor, ThemeUtil.colorPrimary(context, 0xFF000000)));
if((resId = a.getResourceId(R.styleable.CircularProgressDrawable_cpd_strokeColors, 0)) != 0){
TypedArray ta = context.getResources().obtainTypedArray(resId);
int[] colors = new int[ta.length()];
for(int j = 0; j < ta.length(); j++)
colors[j] = ta.getColor(j, 0);
ta.recycle();
strokeColors(colors);
}
strokeSecondaryColor(a.getColor(R.styleable.CircularProgressDrawable_cpd_strokeSecondaryColor, 0));
reverse(a.getBoolean(R.styleable.CircularProgressDrawable_cpd_reverse, false));
rotateDuration(a.getInteger(R.styleable.CircularProgressDrawable_cpd_rotateDuration, context.getResources().getInteger(android.R.integer.config_longAnimTime)));
transformDuration(a.getInteger(R.styleable.CircularProgressDrawable_cpd_transformDuration, context.getResources().getInteger(android.R.integer.config_mediumAnimTime)));
keepDuration(a.getInteger(R.styleable.CircularProgressDrawable_cpd_keepDuration, context.getResources().getInteger(android.R.integer.config_shortAnimTime)));
if((resId = a.getResourceId(R.styleable.CircularProgressDrawable_cpd_transformInterpolator, 0)) != 0)
transformInterpolator(AnimationUtils.loadInterpolator(context, resId));
progressMode(a.getInteger(R.styleable.CircularProgressDrawable_pv_progressMode, ProgressView.MODE_INDETERMINATE));
inAnimDuration(a.getInteger(R.styleable.CircularProgressDrawable_cpd_inAnimDuration, context.getResources().getInteger(android.R.integer.config_mediumAnimTime)));
if((resId = a.getResourceId(R.styleable.CircularProgressDrawable_cpd_inStepColors, 0)) != 0){
TypedArray ta = context.getResources().obtainTypedArray(resId);
int[] colors = new int[ta.length()];
for(int j = 0; j < ta.length(); j++)
colors[j] = ta.getColor(j, 0);
ta.recycle();
inStepColors(colors);
}
inStepPercent(a.getFloat(R.styleable.CircularProgressDrawable_cpd_inStepPercent, 0.5f));
outAnimDuration(a.getInteger(R.styleable.CircularProgressDrawable_cpd_outAnimDuration, context.getResources().getInteger(android.R.integer.config_mediumAnimTime)));
a.recycle();
}

public CircularProgressDrawable build(){
if(mStrokeColors == null)
mStrokeColors = new int[]{0xFF0099FF};

if(mInColors == null && mInAnimationDuration > 0)
mInColors = new int[]{0xFFB5D4FF, 0xFFDEEAFC, 0xFFFAFFFE};

if(mTransformInterpolator == null)
mTransformInterpolator = new DecelerateInterpolator();

return new CircularProgressDrawable(mPadding, mInitialAngle, mProgressPercent, mSecondaryProgressPercent, mMaxSweepAngle, mMinSweepAngle, mStrokeSize, mStrokeColors, mStrokeSecondaryColor, mReverse, mRotateDuration, mTransformDuration, mKeepDuration, mTransformInterpolator, mProgressMode, mInAnimationDuration, mInStepPercent, mInColors, mOutAnimationDuration);
}

public Builder padding(int padding){
mPadding = padding;
return this;
}

public Builder initialAngle(float angle){
mInitialAngle = angle;
return this;
}

public Builder progressPercent(float percent){
mProgressPercent = percent;
return this;
}

public Builder secondaryProgressPercent(float percent){
mSecondaryProgressPercent = percent;
return this;
}

public Builder maxSweepAngle(float angle){
mMaxSweepAngle = angle;
return this;
}

public Builder minSweepAngle(float angle){
mMinSweepAngle = angle;
return this;
}

public Builder strokeSize(int strokeSize){
mStrokeSize = strokeSize;
return this;
}

public Builder strokeColors(int... strokeColors){
mStrokeColors = strokeColors;
return this;
}

public Builder strokeSecondaryColor(int color){
mStrokeSecondaryColor = color;
return this;
}

public Builder reverse(boolean reverse){
mReverse = reverse;
return this;
}

public Builder reverse(){
return reverse(true);
}

public Builder rotateDuration(int duration){
mRotateDuration = duration;
return this;
}

public Builder transformDuration(int duration){
mTransformDuration = duration;
return this;
}

public Builder keepDuration(int duration){
mKeepDuration = duration;
return this;
}

public Builder transformInterpolator(Interpolator interpolator){
mTransformInterpolator = interpolator;
return this;
}

public Builder progressMode(int mode){
mProgressMode = mode;
return this;
}

public Builder inAnimDuration(int duration){
mInAnimationDuration = duration;
return this;
}

public Builder inStepPercent(float percent){
mInStepPercent = percent;
return this;
}

public Builder inStepColors(int... colors){
mInColors = colors;
return this;
}

public Builder outAnimDuration(int duration){
mOutAnimationDuration = duration;
return this;
}

}
}

—> Run Your Code.

admin@androidtrainee

 Previous Article How to implement AppNext Ads In Android Application?
Next Article   Android Floating Action Button For Material Design (Android L).

Related Posts

  • Android New Quick Action Animation.

    July 15, 2015
  • Android satellite menu Animation.

    July 15, 2015
  • Android Staggered Grid & List View.

    July 14, 2015

Leave a Reply

Cancel reply

Tags

admob Advertising Networks AerServ Airpush android android ads android Advertising Networks Android App android chart animation Android GridView android L android lollipop androidmapv2 AppBrain AppFlood Appia AppKey Appnext AppOptim Appwiz chart chartview Epom Market google place api GridView Image Loader InMobi LeadBolt location map mapv2 mapv2 api material design Minimob Mobicow MobileCore MobiMicro NativeX Pingjam RevMob StarApplication startapp TapContext touched location Widdit

Count per Day

  • 347Reads yesterday:
  • 463843Total visitors:
  • 63Visitors today:
  • 2436Visitors per month:
  • 0Visitors currently online:
© Copyright 2014. Theme by BloomPixel.
Posting....