Commits

skarumuru  committed f8590cb

smooth progress bar on action bar for version > 3 todo below 3

  • Participants
  • Parent commits 2397857

Comments (0)

Files changed (8)

File project.properties

 # Project target.
 target=android-19
 android.library.reference.1=../appcompat_v7
+android.library.reference.2=../../../Downloads/JakeWharton-NineOldAndroids-9f20fd7/library

File res/layout/smooth_progress_bar.xml

+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:butterbar="http://schemas.android.com/apk/res-auto"
+    android:layout_width="wrap_content"
+    android:layout_gravity="bottom"
+    android:gravity="bottom"
+    android:layout_height="match_parent" >
+
+    <com.w4rlock.backpapermusic.views.ButteryProgressBar
+        android:id="@+id/progress"
+        android:layout_width="match_parent"
+        android:layout_height="2.5dp"
+        android:layout_gravity="bottom"
+        android:visibility="gone"
+        butterbar:barColor="#ff0099cc"
+        butterbar:barHeight="2.5dp" />
+
+</LinearLayout>

File res/values/animation_constants.xml

+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2011 Google Inc.
+     Licensed to The Android Open Source Project.
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <integer name="fadein_cc_bcc_dur">150</integer>
+    <integer name="fade_duration">250</integer>
+    <integer name="dialog_animationDefaultDur">220</integer>
+    <integer name="dialog_animationShortDur">150</integer>
+    <integer name="shrink_animation_duration">200</integer>
+    <integer name="slide_animation_duration">320</integer>
+    <integer name="fade_in_animation_duration">300</integer>
+
+    <!-- Swipe constants -->
+    <integer name="swipe_escape_velocity">100</integer>
+    <integer name="escape_animation_duration">200</integer>
+    <integer name="max_escape_animation_duration">400</integer>
+    <integer name="max_dismiss_velocity">2000</integer>
+    <integer name="snap_animation_duration">350</integer>
+    <dimen name="min_swipe">10dip</dimen>
+    <integer name="dismiss_all_leavebehinds_short_delay">175</integer>
+    <integer name="dismiss_all_leavebehinds_long_delay">350</integer>
+</resources>

File res/values/attrs.xml

+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2011 Google Inc.
+     Licensed to The Android Open Source Project.
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <add-resource name="RecipientEditTextViewStyle" type="style" />
+    <add-resource name="ComposeEditTextView" type="style" />
+    <add-resource name="LargeComposeAreaBody" type="style" />
+    <add-resource name="RecipientComposeFieldSpacer" type="style" />
+    <add-resource name="ComposeHeading" type="style" />
+    <add-resource name="RecipientComposeHeading" type="style" />
+    <add-resource name="ComposeFieldLayout" type="style" />
+    <add-resource name="RecipientComposeFieldLayout" type="style" />
+    <add-resource name="ComposeSubjectStyle" type="style" />
+    <declare-styleable name="FolderItemViewDrawableState">
+        <attr name="state_drag_mode" format="boolean" />
+    </declare-styleable>
+    <declare-styleable name="ButteryProgressBar">
+        <attr name="barColor" format="color" />
+        <attr name="barHeight" format="dimension" />
+        <attr name="detentWidth" format="dimension" />
+    </declare-styleable>
+</resources>

File src/com/w4rlock/backpapermusic/AbsActivity.java

+package com.w4rlock.backpapermusic;
+
+import com.w4rlock.backpapermusic.loaders.Loading;
+
+import android.support.v7.app.ActionBarActivity;
+
+public abstract class AbsActivity extends ActionBarActivity implements Loading
+{
+
+}

File src/com/w4rlock/backpapermusic/MusicActivity.java

 
 import static nl.qbusict.cupboard.CupboardFactory.cupboard;
 import nl.qbusict.cupboard.QueryResultIterable;
+import android.annotation.SuppressLint;
+import android.content.res.TypedArray;
 import android.database.Cursor;
 import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
 
 import com.w4rlock.backpapermusic.database.db.MusicDb;
 import com.w4rlock.backpapermusic.fragments.MusicListFragment;
 import com.w4rlock.backpapermusic.models.Song;
 import com.w4rlock.backpapermusic.util.L;
 
-public class MusicActivity extends ActionBarActivity
+public class MusicActivity extends AbsActivity
 {
 
 	@Override
 		}
 		com.nostra13.universalimageloader.utils.L.disableLogging();
 
-//		L.d("MusicActivity", "Calling Service");
-//		MusicDatabaseSyncerService musicDatabaseSyncerService = new MusicDatabaseSyncerService(getApplicationContext());
-//		musicDatabaseSyncerService.execute();
+		// L.d("MusicActivity", "Calling Service");
+		// MusicDatabaseSyncerService musicDatabaseSyncerService = new
+		// MusicDatabaseSyncerService(getApplicationContext());
+		// musicDatabaseSyncerService.execute();
 
 		// Get the cursor for this query
 		Cursor songs = cupboard().withDatabase(MusicDb.getReadDatabase(getApplicationContext())).query(Song.class).groupBy("dirname").getCursor();
 			// Iterate books
 			for (Song song : itr)
 			{
-				L.d("MusicActivity", song.getDirname()+"/"+song.getAlbum() + "/" + song.getName());
+				L.d("MusicActivity", song.getDirname() + "/" + song.getAlbum() + "/" + song.getName());
 			}
 		} catch (Exception e)
 		{
 			songs.close();
 			itr.close();
 		}
+		showSyncStatusBar();
 	}
 
 	@Override
 		return super.onOptionsItemSelected(item);
 	}
 
+	private View mSyncProgressBar;
+
+	@SuppressLint("InlinedApi")
+	private void ensureProgressBars()
+	{
+		if (mSyncProgressBar == null)
+		{
+			int actionBarHeight;
+			final TypedArray styledAttributes = getApplicationContext().getTheme().obtainStyledAttributes(new int[]
+			{ android.R.attr.actionBarSize });
+			actionBarHeight = (int) styledAttributes.getDimension(0, 0);
+			styledAttributes.recycle();
+
+			final LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
+			View v = inflater.inflate(R.layout.smooth_progress_bar, null, false);
+
+			mSyncProgressBar = v.findViewById(R.id.progress);
+			L.d("progressbar", "" + actionBarHeight);
+			mSyncProgressBar.setMinimumHeight(actionBarHeight);
+			if(getActionBarView() != null){
+				((ViewGroup) getActionBarView()).addView(v);
+			}else{
+				L.d("progressbar", "Null on getting action bar view");
+			}
+		}
+	}
+
+	protected void showSyncStatusBar()
+	{
+		L.d("progressbar", "show sync status bar");
+		ensureProgressBars();
+		mSyncProgressBar.setVisibility(View.VISIBLE);
+	}
+	
+	protected void hideSyncStatusBar()
+	{
+		L.d("progressbar", "show sync status bar");
+		ensureProgressBars();
+		mSyncProgressBar.setVisibility(View.GONE);
+	}
+
+	public View getActionBarView()
+	{
+		Window window = getWindow();
+		View v = window.getDecorView();
+		int resId = getResources().getIdentifier("action_bar_container", "id", "android");
+		return v.findViewById(resId);
+	}
+
+	@Override
+	public void onLoadingStarted()
+	{
+		showSyncStatusBar();
+	}
+
+	@Override
+	public void onLoadingEnded()
+	{
+		hideSyncStatusBar();
+	}
+
+	@Override
+	public void onProgressUpdate(int percent)
+	{
+		
+	}
+
 }

File src/com/w4rlock/backpapermusic/loaders/Loading.java

+package com.w4rlock.backpapermusic.loaders;
+
+public interface Loading
+{
+	public void onLoadingStarted();
+	public void onLoadingEnded();
+	public void onProgressUpdate(int percent);
+}

File src/com/w4rlock/backpapermusic/views/ButteryProgressBar.java

+package com.w4rlock.backpapermusic.views;
+
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.drawable.GradientDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import com.nineoldandroids.animation.ValueAnimator;
+import com.w4rlock.backpapermusic.R;
+
+/**
+ * Procedurally-drawn version of a horizontal indeterminate progress bar. Draws faster and more
+ * frequently (by making use of the animation timer), requires minimal memory overhead, and allows
+ * some configuration via attributes:
+ * <ul>
+ * <li>barColor (color attribute for the bar's solid color)
+ * <li>barHeight (dimension attribute for the height of the solid progress bar)
+ * <li>detentWidth (dimension attribute for the width of each transparent detent in the bar)
+ * </ul>
+ * <p>
+ * This progress bar has no intrinsic height, so you must declare it with one explicitly. (It will
+ * use the given height as the bar's shadow height.)
+ */
+public class ButteryProgressBar extends View {
+
+    private final GradientDrawable mShadow;
+    private final ValueAnimator mAnimator;
+
+    private final Paint mPaint = new Paint();
+
+    private final int mBarColor;
+    private final int mSolidBarHeight;
+    private final int mSolidBarDetentWidth;
+
+    private final float mDensity;
+
+    private int mSegmentCount;
+
+    /**
+     * The baseline width that the other constants below are optimized for.
+     */
+    private static final int BASE_WIDTH_DP = 300;
+    /**
+     * A reasonable animation duration for the given width above. It will be weakly scaled up and
+     * down for wider and narrower widths, respectively-- the goal is to provide a relatively
+     * constant detent velocity.
+     */
+    private static final int BASE_DURATION_MS = 500;
+    /**
+     * A reasonable number of detents for the given width above. It will be weakly scaled up and
+     * down for wider and narrower widths, respectively.
+     */
+    private static final int BASE_SEGMENT_COUNT = 5;
+
+    private static final int DEFAULT_BAR_HEIGHT_DP = 4;
+    private static final int DEFAULT_DETENT_WIDTH_DP = 3;
+    
+    
+    
+    public ButteryProgressBar(Context c) {
+        this(c, null);
+    }
+
+     
+	public ButteryProgressBar(Context c, AttributeSet attrs) {
+        super(c, attrs);
+
+        mDensity = c.getResources().getDisplayMetrics().density;
+
+        final TypedArray ta = c.obtainStyledAttributes(attrs, R.styleable.ButteryProgressBar);
+        try {
+            mBarColor = ta.getColor(R.styleable.ButteryProgressBar_barColor,
+                    c.getResources().getColor(android.R.color.holo_blue_light));
+            mSolidBarHeight = ta.getDimensionPixelSize(
+                    R.styleable.ButteryProgressBar_barHeight,
+                    Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity));
+            mSolidBarDetentWidth = ta.getDimensionPixelSize(
+                    R.styleable.ButteryProgressBar_detentWidth,
+                    Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity));
+        } finally {
+            ta.recycle();
+        }
+
+        mAnimator = new ValueAnimator();
+        mAnimator.setFloatValues(1.0f, 2.0f);
+        mAnimator.setRepeatCount(ValueAnimator.INFINITE);
+        mAnimator.setInterpolator(new ExponentialInterpolator());
+        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                invalidate();
+            }
+
+        });
+
+        mPaint.setColor(mBarColor);
+
+        mShadow = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM,
+                new int[]{(mBarColor & 0x00ffffff) | 0x22000000, 0});
+    }
+
+     
+	@Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (changed) {
+            final int w = getWidth();
+
+            mShadow.setBounds(0, mSolidBarHeight, w, getHeight() - mSolidBarHeight);
+
+            final float widthMultiplier = w / mDensity / BASE_WIDTH_DP;
+            // simple scaling by width is too aggressive, so dampen it first
+            final float durationMult = 0.3f * (widthMultiplier - 1) + 1;
+            final float segmentMult = 0.1f * (widthMultiplier - 1) + 1;
+            mAnimator.setDuration((int) (BASE_DURATION_MS * durationMult));
+            mSegmentCount = (int) (BASE_SEGMENT_COUNT * segmentMult);
+        }
+    }
+
+     
+	@Override
+    protected void onDraw(Canvas canvas) {
+        if (!mAnimator.isStarted()) {
+            return;
+        }
+
+        mShadow.draw(canvas);
+
+        final float val = (Float) mAnimator.getAnimatedValue();
+
+        final int w = getWidth();
+        // Because the left-most segment doesn't start all the way on the left, and because it moves
+        // towards the right as it animates, we need to offset all drawing towards the left. This
+        // ensures that the left-most detent starts at the left origin, and that the left portion
+        // is never blank as the animation progresses towards the right.
+        final int offset = w >> mSegmentCount - 1;
+        // segments are spaced at half-width, quarter, eighth (powers-of-two). to maintain a smooth
+        // transition between segments, we used a power-of-two interpolator.
+        for (int i = 0; i < mSegmentCount; i++) {
+            final float l = val * (w >> (i + 1));
+            final float r = (i == 0) ? w + offset : l * 2;
+            canvas.drawRect(l + mSolidBarDetentWidth - offset, 0, r - offset, mSolidBarHeight,
+                    mPaint);
+        }
+    }
+
+    @Override
+    protected void onVisibilityChanged(View changedView, int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+
+        if (visibility == VISIBLE) {
+            start();
+        } else {
+            stop();
+        }
+    }
+
+    private void start() {
+        if (mAnimator == null) {
+            return;
+        }
+        mAnimator.start();
+    }
+
+     
+	private void stop() {
+        if (mAnimator == null) {
+            return;
+        }
+        mAnimator.cancel();
+    }
+
+    private static class ExponentialInterpolator implements Interpolator {
+
+        @Override
+        public float getInterpolation(float input) {
+            return (float) Math.pow(2.0, input) - 1;
+        }
+
+    }
+
+}