From 5222b6e3e6e121743129384da02dddb371b35455 Mon Sep 17 00:00:00 2001 From: Bradlee Speice Date: Sat, 17 May 2014 01:16:36 -0400 Subject: [PATCH] Various cleanups Move ProgressWheel into the project proper, optimize the DL ListView And also remove android-iconify. Despite using icons (which is awesome) it didn't handle button highlight on click well, and the icons seemed a bit small anyways. --- .gitmodules | 3 - MinimalBible/build.gradle | 4 +- .../res/layout/list_download_items.xml | 20 +- MinimalBible/res/values/attrs.xml | 19 + .../bspeice/minimalbible/ProgressWheel.java | 528 ++++++++++++++++++ .../downloader/BookListAdapter.java | 8 +- settings.gradle | 1 - 7 files changed, 560 insertions(+), 23 deletions(-) create mode 100644 MinimalBible/res/values/attrs.xml create mode 100644 MinimalBible/src/org/bspeice/minimalbible/ProgressWheel.java diff --git a/.gitmodules b/.gitmodules index 613789c..f05ad71 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,3 @@ [submodule "jsword-minimalbible"] path = jsword-minimalbible url = https://github.com/MinimalBible/jsword-minimalbible.git -[submodule "ProgressWheel"] - path = ProgressWheel - url = git@github.com:Todd-Davies/ProgressWheel diff --git a/MinimalBible/build.gradle b/MinimalBible/build.gradle index 82f7083..995e341 100644 --- a/MinimalBible/build.gradle +++ b/MinimalBible/build.gradle @@ -17,7 +17,6 @@ repositories { dependencies { compile project(path: ':jsword-minimalbible', configuration: 'buildJSword') compile project(':appcompat_v7') - compile project(':ProgressWheel') apt "org.androidannotations:androidannotations:3.0+" compile "org.androidannotations:androidannotations-api:3.0+" @@ -35,7 +34,7 @@ dependencies { compile 'com.readystatesoftware.systembartint:systembartint:1.0.3' compile 'de.greenrobot:eventbus:2.2.0' - compile 'com.joanzapata.android:android-iconify:1.0.+' + // compile 'com.joanzapata.android:android-iconify:1.0.+' // Handled by appcompat // compile 'com.google.android:support-v4:r7' @@ -75,6 +74,7 @@ android { exclude 'META-INF/DEPENDENCIES' exclude 'META-INF/LICENSE' exclude 'META-INF/NOTICE' + exclude 'META-INF/services/javax.annotation.processing.Processor' } } diff --git a/MinimalBible/res/layout/list_download_items.xml b/MinimalBible/res/layout/list_download_items.xml index 0dfb263..451e950 100644 --- a/MinimalBible/res/layout/list_download_items.xml +++ b/MinimalBible/res/layout/list_download_items.xml @@ -10,9 +10,7 @@ android:layout_height="wrap_content" android:id="@+id/img_download_icon" android:layout_alignParentLeft="true" - android:layout_marginLeft="0dp" - android:layout_alignParentTop="true" - android:layout_marginTop="0dp" /> + android:layout_alignParentTop="true" /> + android:layout_toLeftOf="@+id/download_ibtn_download" /> @@ -35,18 +34,9 @@ - - \ No newline at end of file diff --git a/MinimalBible/res/values/attrs.xml b/MinimalBible/res/values/attrs.xml new file mode 100644 index 0000000..e8555f4 --- /dev/null +++ b/MinimalBible/res/values/attrs.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MinimalBible/src/org/bspeice/minimalbible/ProgressWheel.java b/MinimalBible/src/org/bspeice/minimalbible/ProgressWheel.java new file mode 100644 index 0000000..409b336 --- /dev/null +++ b/MinimalBible/src/org/bspeice/minimalbible/ProgressWheel.java @@ -0,0 +1,528 @@ +package org.bspeice.minimalbible; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.graphics.RectF; +import android.graphics.Shader; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.view.View; + + +/** + * An indicator of progress, similar to Android's ProgressBar. + * Can be used in 'spin mode' or 'increment mode' + * + * @author Todd Davies + *

+ * Licensed under the Creative Commons Attribution 3.0 license see: + * http://creativecommons.org/licenses/by/3.0/ + */ +public class ProgressWheel extends View { + + //Sizes (with defaults) + private int layout_height = 0; + private int layout_width = 0; + private int fullRadius = 100; + private int circleRadius = 80; + private int barLength = 60; + private int barWidth = 20; + private int rimWidth = 20; + private int textSize = 20; + private float contourSize = 0; + + //Padding (with defaults) + private int paddingTop = 5; + private int paddingBottom = 5; + private int paddingLeft = 5; + private int paddingRight = 5; + + //Colors (with defaults) + private int barColor = 0xAA000000; + private int contourColor = 0xAA000000; + private int circleColor = 0x00000000; + private int rimColor = 0xAADDDDDD; + private int textColor = 0xFF000000; + + //Paints + private Paint barPaint = new Paint(); + private Paint circlePaint = new Paint(); + private Paint rimPaint = new Paint(); + private Paint textPaint = new Paint(); + private Paint contourPaint = new Paint(); + + //Rectangles + @SuppressWarnings("unused") + private RectF rectBounds = new RectF(); + private RectF circleBounds = new RectF(); + private RectF circleOuterContour = new RectF(); + private RectF circleInnerContour = new RectF(); + + //Animation + //The amount of pixels to move the bar by on each draw + private int spinSpeed = 2; + //The number of milliseconds to wait inbetween each draw + private int delayMillis = 0; + private Handler spinHandler = new Handler() { + /** + * This is the code that will increment the progress variable + * and so spin the wheel + */ + @Override + public void handleMessage(Message msg) { + invalidate(); + if (isSpinning) { + progress += spinSpeed; + if (progress > 360) { + progress = 0; + } + spinHandler.sendEmptyMessageDelayed(0, delayMillis); + } + //super.handleMessage(msg); + } + }; + int progress = 0; + boolean isSpinning = false; + + //Other + private String text = ""; + private String[] splitText = {}; + + /** + * The constructor for the ProgressWheel + * + * @param context + * @param attrs + */ + public ProgressWheel(Context context, AttributeSet attrs) { + super(context, attrs); + + parseAttributes(context.obtainStyledAttributes(attrs, + R.styleable.ProgressWheel)); + } + + //---------------------------------- + //Setting up stuff + //---------------------------------- + + /* + * When this is called, make the view square. + * From: http://www.jayway.com/2012/12/12/creating-custom-android-views-part-4-measuring-and-how-to-force-a-view-to-be-square/ + * + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // The first thing that happen is that we call the superclass + // implementation of onMeasure. The reason for that is that measuring + // can be quite a complex process and calling the super method is a + // convenient way to get most of this complexity handled. + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + // We can’t use getWidth() or getHight() here. During the measuring + // pass the view has not gotten its final size yet (this happens first + // at the start of the layout pass) so we have to use getMeasuredWidth() + // and getMeasuredHeight(). + int size = 0; + int width = getMeasuredWidth(); + int height = getMeasuredHeight(); + int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight(); + int heigthWithoutPadding = height - getPaddingTop() - getPaddingBottom(); + + // Finally we have some simple logic that calculates the size of the view + // and calls setMeasuredDimension() to set that size. + // Before we compare the width and height of the view, we remove the padding, + // and when we set the dimension we add it back again. Now the actual content + // of the view will be square, but, depending on the padding, the total dimensions + // of the view might not be. + if (widthWithoutPadding > heigthWithoutPadding) { + size = heigthWithoutPadding; + } else { + size = widthWithoutPadding; + } + + // If you override onMeasure() you have to call setMeasuredDimension(). + // This is how you report back the measured size. If you don’t call + // setMeasuredDimension() the parent will throw an exception and your + // application will crash. + // We are calling the onMeasure() method of the superclass so we don’t + // actually need to call setMeasuredDimension() since that takes care + // of that. However, the purpose with overriding onMeasure() was to + // change the default behaviour and to do that we need to call + // setMeasuredDimension() with our own values. + setMeasuredDimension(size + getPaddingLeft() + getPaddingRight(), size + getPaddingTop() + getPaddingBottom()); + } + + /** + * Use onSizeChanged instead of onAttachedToWindow to get the dimensions of the view, + * because this method is called after measuring the dimensions of MATCH_PARENT & WRAP_CONTENT. + * Use this dimensions to setup the bounds and paints. + */ + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // Share the dimensions + layout_width = w; + layout_height = h; + + setupBounds(); + setupPaints(); + invalidate(); + } + + /** + * Set the properties of the paints we're using to + * draw the progress wheel + */ + private void setupPaints() { + barPaint.setColor(barColor); + barPaint.setAntiAlias(true); + barPaint.setStyle(Style.STROKE); + barPaint.setStrokeWidth(barWidth); + + rimPaint.setColor(rimColor); + rimPaint.setAntiAlias(true); + rimPaint.setStyle(Style.STROKE); + rimPaint.setStrokeWidth(rimWidth); + + circlePaint.setColor(circleColor); + circlePaint.setAntiAlias(true); + circlePaint.setStyle(Style.FILL); + + textPaint.setColor(textColor); + textPaint.setStyle(Style.FILL); + textPaint.setAntiAlias(true); + textPaint.setTextSize(textSize); + + contourPaint.setColor(contourColor); + contourPaint.setAntiAlias(true); + contourPaint.setStyle(Style.STROKE); + contourPaint.setStrokeWidth(contourSize); + } + + /** + * Set the bounds of the component + */ + private void setupBounds() { + // Width should equal to Height, find the min value to steup the circle + int minValue = Math.min(layout_width, layout_height); + + // Calc the Offset if needed + int xOffset = layout_width - minValue; + int yOffset = layout_height - minValue; + + // Add the offset + paddingTop = this.getPaddingTop() + (yOffset / 2); + paddingBottom = this.getPaddingBottom() + (yOffset / 2); + paddingLeft = this.getPaddingLeft() + (xOffset / 2); + paddingRight = this.getPaddingRight() + (xOffset / 2); + + int width = getWidth(); //this.getLayoutParams().width; + int height = getHeight(); //this.getLayoutParams().height; + + rectBounds = new RectF(paddingLeft, + paddingTop, + width - paddingRight, + height - paddingBottom); + + circleBounds = new RectF(paddingLeft + barWidth, + paddingTop + barWidth, + width - paddingRight - barWidth, + height - paddingBottom - barWidth); + circleInnerContour = new RectF(circleBounds.left + (rimWidth / 2.0f) + (contourSize / 2.0f), circleBounds.top + (rimWidth / 2.0f) + (contourSize / 2.0f), circleBounds.right - (rimWidth / 2.0f) - (contourSize / 2.0f), circleBounds.bottom - (rimWidth / 2.0f) - (contourSize / 2.0f)); + circleOuterContour = new RectF(circleBounds.left - (rimWidth / 2.0f) - (contourSize / 2.0f), circleBounds.top - (rimWidth / 2.0f) - (contourSize / 2.0f), circleBounds.right + (rimWidth / 2.0f) + (contourSize / 2.0f), circleBounds.bottom + (rimWidth / 2.0f) + (contourSize / 2.0f)); + + fullRadius = (width - paddingRight - barWidth) / 2; + circleRadius = (fullRadius - barWidth) + 1; + } + + /** + * Parse the attributes passed to the view from the XML + * + * @param a the attributes to parse + */ + private void parseAttributes(TypedArray a) { + barWidth = (int) a.getDimension(R.styleable.ProgressWheel_barWidth, + barWidth); + + rimWidth = (int) a.getDimension(R.styleable.ProgressWheel_rimWidth, + rimWidth); + + spinSpeed = (int) a.getDimension(R.styleable.ProgressWheel_spinSpeed, + spinSpeed); + + delayMillis = a.getInteger(R.styleable.ProgressWheel_delayMillis, + delayMillis); + if (delayMillis < 0) { + delayMillis = 0; + } + + barColor = a.getColor(R.styleable.ProgressWheel_barColor, barColor); + + barLength = (int) a.getDimension(R.styleable.ProgressWheel_barLength, + barLength); + + textSize = (int) a.getDimension(R.styleable.ProgressWheel_textSize, + textSize); + + textColor = (int) a.getColor(R.styleable.ProgressWheel_textColor, + textColor); + + //if the text is empty , so ignore it + if (a.hasValue(R.styleable.ProgressWheel_text)) { + setText(a.getString(R.styleable.ProgressWheel_text)); + } + + rimColor = (int) a.getColor(R.styleable.ProgressWheel_rimColor, + rimColor); + + circleColor = (int) a.getColor(R.styleable.ProgressWheel_circleColor, + circleColor); + + contourColor = a.getColor(R.styleable.ProgressWheel_contourColor, contourColor); + contourSize = a.getDimension(R.styleable.ProgressWheel_contourSize, contourSize); + + + // Recycle + a.recycle(); + } + + //---------------------------------- + //Animation stuff + //---------------------------------- + + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + //Draw the inner circle + canvas.drawArc(circleBounds, 360, 360, false, circlePaint); + //Draw the rim + canvas.drawArc(circleBounds, 360, 360, false, rimPaint); + canvas.drawArc(circleOuterContour, 360, 360, false, contourPaint); + canvas.drawArc(circleInnerContour, 360, 360, false, contourPaint); + //Draw the bar + if (isSpinning) { + canvas.drawArc(circleBounds, progress - 90, barLength, false, + barPaint); + } else { + canvas.drawArc(circleBounds, -90, progress, false, barPaint); + } + //Draw the text (attempts to center it horizontally and vertically) + float textHeight = textPaint.descent() - textPaint.ascent(); + float verticalTextOffset = (textHeight / 2) - textPaint.descent(); + + for (String s : splitText) { + float horizontalTextOffset = textPaint.measureText(s) / 2; + canvas.drawText(s, this.getWidth() / 2 - horizontalTextOffset, + this.getHeight() / 2 + verticalTextOffset, textPaint); + } + } + + /** + * Check if the wheel is currently spinning + */ + + public boolean isSpinning() { + if(isSpinning){ + return true; + } else { + return false; + } + } + + /** + * Reset the count (in increment mode) + */ + public void resetCount() { + progress = 0; + setText("0%"); + invalidate(); + } + + /** + * Turn off spin mode + */ + public void stopSpinning() { + isSpinning = false; + progress = 0; + spinHandler.removeMessages(0); + } + + + /** + * Puts the view on spin mode + */ + public void spin() { + isSpinning = true; + spinHandler.sendEmptyMessage(0); + } + + /** + * Increment the progress by 1 (of 360) + */ + public void incrementProgress() { + isSpinning = false; + progress++; + if (progress > 360) + progress = 0; +// setText(Math.round(((float) progress / 360) * 100) + "%"); + spinHandler.sendEmptyMessage(0); + } + + + /** + * Set the progress to a specific value + */ + public void setProgress(int i) { + isSpinning = false; + progress = i; + spinHandler.sendEmptyMessage(0); + } + + //---------------------------------- + //Getters + setters + //---------------------------------- + + /** + * Set the text in the progress bar + * Doesn't invalidate the view + * + * @param text the text to show ('\n' constitutes a new line) + */ + public void setText(String text) { + this.text = text; + splitText = this.text.split("\n"); + } + + public int getCircleRadius() { + return circleRadius; + } + + public void setCircleRadius(int circleRadius) { + this.circleRadius = circleRadius; + } + + public int getBarLength() { + return barLength; + } + + public void setBarLength(int barLength) { + this.barLength = barLength; + } + + public int getBarWidth() { + return barWidth; + } + + public void setBarWidth(int barWidth) { + this.barWidth = barWidth; + } + + public int getTextSize() { + return textSize; + } + + public void setTextSize(int textSize) { + this.textSize = textSize; + } + + public int getPaddingTop() { + return paddingTop; + } + + public void setPaddingTop(int paddingTop) { + this.paddingTop = paddingTop; + } + + public int getPaddingBottom() { + return paddingBottom; + } + + public void setPaddingBottom(int paddingBottom) { + this.paddingBottom = paddingBottom; + } + + public int getPaddingLeft() { + return paddingLeft; + } + + public void setPaddingLeft(int paddingLeft) { + this.paddingLeft = paddingLeft; + } + + public int getPaddingRight() { + return paddingRight; + } + + public void setPaddingRight(int paddingRight) { + this.paddingRight = paddingRight; + } + + public int getBarColor() { + return barColor; + } + + public void setBarColor(int barColor) { + this.barColor = barColor; + } + + public int getCircleColor() { + return circleColor; + } + + public void setCircleColor(int circleColor) { + this.circleColor = circleColor; + } + + public int getRimColor() { + return rimColor; + } + + public void setRimColor(int rimColor) { + this.rimColor = rimColor; + } + + + public Shader getRimShader() { + return rimPaint.getShader(); + } + + public void setRimShader(Shader shader) { + this.rimPaint.setShader(shader); + } + + public int getTextColor() { + return textColor; + } + + public void setTextColor(int textColor) { + this.textColor = textColor; + } + + public int getSpinSpeed() { + return spinSpeed; + } + + public void setSpinSpeed(int spinSpeed) { + this.spinSpeed = spinSpeed; + } + + public int getRimWidth() { + return rimWidth; + } + + public void setRimWidth(int rimWidth) { + this.rimWidth = rimWidth; + } + + public int getDelayMillis() { + return delayMillis; + } + + public void setDelayMillis(int delayMillis) { + this.delayMillis = delayMillis; + } +} diff --git a/MinimalBible/src/org/bspeice/minimalbible/activities/downloader/BookListAdapter.java b/MinimalBible/src/org/bspeice/minimalbible/activities/downloader/BookListAdapter.java index 0f4ff14..259317a 100644 --- a/MinimalBible/src/org/bspeice/minimalbible/activities/downloader/BookListAdapter.java +++ b/MinimalBible/src/org/bspeice/minimalbible/activities/downloader/BookListAdapter.java @@ -5,10 +5,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; +import android.widget.IconButton; +import android.widget.IconTextView; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; +import com.joanzapata.android.iconify.Iconify; + import org.bspeice.minimalbible.R; import org.crosswire.jsword.book.Book; @@ -63,8 +68,7 @@ public class BookListAdapter extends BaseAdapter { @InjectView(R.id.img_download_icon) ImageView downloadIcon; @InjectView(R.id.download_txt_item_acronym) TextView acronym; @InjectView(R.id.txt_download_item_name) TextView itemName; - @InjectView(R.id.img_download_index_downloaded) ImageView isIndexedDownloaded; - @InjectView(R.id.img_download_item_downloaded) ImageView isDownloaded; + @InjectView(R.id.download_ibtn_download) ImageButton isDownloaded; public BookItemView (Context ctx) { super(ctx); diff --git a/settings.gradle b/settings.gradle index 731db6b..3a495ec 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,3 @@ include ':appcompat_v7' include ':MinimalBible' include ':jsword-minimalbible' -include ':ProgressWheel'