1 package com.moiseum.wolnelektury.view.book.components;
4 * Created by Piotr Ostrowski on 21.11.2017.
7 import android.annotation.SuppressLint;
8 import android.content.Context;
9 import android.content.res.TypedArray;
10 import android.graphics.Bitmap;
11 import android.graphics.BitmapFactory;
12 import android.graphics.Canvas;
13 import android.graphics.Color;
14 import android.graphics.Paint;
15 import android.graphics.PorterDuff;
16 import android.graphics.PorterDuffColorFilter;
17 import android.graphics.Rect;
18 import android.graphics.RectF;
19 import android.graphics.Typeface;
20 import android.util.AttributeSet;
21 import android.view.View;
23 import com.moiseum.wolnelektury.R;
25 import java.util.Locale;
27 public class ProgressDownloadButton extends View {
29 private static final int MAX_PROGRESS_VALUE = 100;
31 public enum ProgressDownloadButtonState {
34 public boolean isEnabled() {
39 public boolean isDownloaded() {
44 public boolean isDeletable() {
49 public void draw(Canvas canvas, ProgressDownloadButtonAttributes attributes, int width, int height) {
50 int posY = getPosY(attributes, height);
51 canvas.drawText(attributes.initialText, attributes.paddingStart, posY, attributes.textPaint);
52 int top = (height - attributes.iconBitmap.getHeight()) / 2;
53 canvas.drawBitmap(attributes.iconBitmap, width - attributes.iconBitmap.getWidth() - attributes.paddingEnd, top, attributes
56 }, STATE_DOWNLOADING {
58 public boolean isEnabled() {
63 public boolean isDownloaded() {
64 throw new IllegalStateException("This method shall not be called within this state");
68 public boolean isDeletable() {
73 public void draw(Canvas canvas, ProgressDownloadButtonAttributes attributes, int width, int height) {
74 int posY = getPosY(attributes, height);
75 String text = String.format(Locale.getDefault(), "%s: %d%%", attributes.loadingText, attributes.currentProgress);
77 // Draw text to overlap.
78 canvas.drawText(text, attributes.paddingStart, posY, attributes.textPaint);
80 // Draw icon to overlap.
81 int top = (height - attributes.iconBitmap.getHeight()) / 2;
82 canvas.drawBitmap(attributes.iconBitmap, width - attributes.iconBitmap.getWidth() - attributes.paddingEnd, top, attributes
86 int currentProgress = attributes.currentProgress;
87 if (currentProgress >= 0 && currentProgress <= MAX_PROGRESS_VALUE) {
88 attributes.baseRect.right = attributes.baseRect.width() * currentProgress / MAX_PROGRESS_VALUE;
89 canvas.clipRect(attributes.baseRect);
92 // Draw current state.
93 canvas.drawRoundRect(attributes.outerRectF, attributes.cornerRadius, attributes.cornerRadius, attributes.textPaint);
94 canvas.drawText(text, attributes.paddingStart, posY, attributes.invertedPaint);
95 canvas.drawBitmap(attributes.iconBitmap, width - attributes.iconBitmap.getWidth() - attributes.paddingEnd, top, attributes
96 .bitmapInvertedPaint);
100 public boolean isEnabled() {
105 public boolean isDownloaded() {
110 public boolean isDeletable() {
115 public void draw(Canvas canvas, ProgressDownloadButtonAttributes attributes, int width, int height) {
116 int posY = getPosY(attributes, height);
117 int top = (height - attributes.iconBitmap.getHeight()) / 2;
118 String text = String.format(Locale.getDefault(), "%1$s: %2$d/%3$d", attributes.downloadedText, attributes
119 .currentReadPosition, attributes.totalReadCount);
121 canvas.drawRoundRect(attributes.outerRectF, attributes.cornerRadius, attributes.cornerRadius, attributes.textPaint);
122 canvas.drawText(text, attributes.paddingStart, posY, attributes.invertedPaint);
123 canvas.drawBitmap(attributes.iconBitmap, width - attributes.iconBitmap.getWidth() - attributes.paddingEnd, top, attributes
124 .bitmapInvertedPaint);
128 private static int getPosY(ProgressDownloadButtonAttributes attributes, int height) {
129 return (int) ((height / 2) - ((attributes.textPaint.descent() + attributes.textPaint.ascent()) / 2));
132 public abstract boolean isEnabled();
134 public abstract boolean isDownloaded();
136 public abstract boolean isDeletable();
138 public abstract void draw(Canvas canvas, ProgressDownloadButtonAttributes attributes, int width, int height);
141 private static class ProgressDownloadButtonAttributes {
142 private String initialText = "";
143 private String downloadedText = "";
144 private String loadingText;
146 private Rect baseRect = new Rect();
147 private RectF outerRectF = new RectF();
148 private RectF innerRectF = new RectF();
150 private int currentProgress = 0;
151 private int currentReadPosition;
152 private int totalReadCount;
154 private Paint textPaint;
155 private Paint invertedPaint;
156 private Paint bitmapPaint;
157 private Paint bitmapInvertedPaint;
159 private Bitmap iconBitmap;
160 private int cornerRadius;
161 private int innerCornerRadius;
162 private int borderSize;
163 private int paddingStart;
164 private int paddingEnd;
168 private ProgressDownloadButtonState currentState = ProgressDownloadButtonState.STATE_INITIAL;
169 private ProgressDownloadButtonAttributes attributes;
171 public ProgressDownloadButton(Context context, AttributeSet attrs, int defStyle) {
172 super(context, attrs, defStyle);
173 initComponents(context, attrs, defStyle, 0);
176 public ProgressDownloadButton(Context context, AttributeSet attrs) {
177 super(context, attrs);
178 initComponents(context, attrs, 0, 0);
181 public ProgressDownloadButton(Context context) {
185 // public InvertedTextProgressbar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
186 // super(context, attrs, defStyleAttr, defStyleRes);
187 // initComponents(context, attrs, defStyleAttr, defStyleRes);
191 * Initializes the text paint. This has a fix size.
193 * @param attrs The XML attributes to use.
195 @SuppressLint("ResourceType")
196 private void initComponents(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
197 attributes = new ProgressDownloadButtonAttributes();
199 TypedArray baseAttributes = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.paddingStart, android.R.attr
201 TypedArray styledAttributes = context.obtainStyledAttributes(attrs, R.styleable.ProgressDownloadButton, defStyleAttr, defStyleRes);
203 attributes.paddingStart = baseAttributes.getDimensionPixelOffset(0, 0);
204 attributes.paddingEnd = baseAttributes.getDimensionPixelOffset(1, 0);
206 Paint textPaint = new Paint();
207 textPaint.setColor(styledAttributes.getColor(R.styleable.ProgressDownloadButton_text_color, Color.BLACK));
208 textPaint.setStyle(Paint.Style.FILL);
209 textPaint.setTextSize(styledAttributes.getDimensionPixelSize(R.styleable.ProgressDownloadButton_text_size, context.getResources()
210 .getDimensionPixelSize(R.dimen.download_button_text_size_default)));
211 textPaint.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL));
212 textPaint.setTextAlign(Paint.Align.LEFT); // Text draw is started in the middle
213 textPaint.setLinearText(true);
214 textPaint.setAntiAlias(true);
216 // Define the inverted text paint.
217 Paint invertedPaint = new Paint(textPaint);
218 invertedPaint.setColor(styledAttributes.getColor(R.styleable.ProgressDownloadButton_text_inverted_color, Color.WHITE));
219 attributes.textPaint = textPaint;
220 attributes.invertedPaint = invertedPaint;
222 // Define paint for drawable
223 Paint bitmapPaint = new Paint();
224 bitmapPaint.setColorFilter(new PorterDuffColorFilter(styledAttributes.getColor(R.styleable.ProgressDownloadButton_text_color,
225 Color.BLACK), PorterDuff.Mode.SRC_ATOP));
226 attributes.bitmapPaint = bitmapPaint;
228 // Define paint for inverted drawable
229 Paint bitmapInvertedPaint = new Paint();
230 bitmapInvertedPaint.setColorFilter(new PorterDuffColorFilter(styledAttributes.getColor(R.styleable
231 .ProgressDownloadButton_text_inverted_color, Color.WHITE), PorterDuff.Mode.SRC_ATOP));
232 attributes.bitmapInvertedPaint = bitmapInvertedPaint;
235 String initialText = styledAttributes.getString(R.styleable.ProgressDownloadButton_text_initial);
236 if (initialText != null) {
237 initialText = initialText.toUpperCase();
238 attributes.initialText = initialText;
240 String downloadedText = styledAttributes.getString(R.styleable.ProgressDownloadButton_text_downloaded);
241 if (downloadedText != null) {
242 downloadedText = downloadedText.toUpperCase();
243 attributes.downloadedText = downloadedText;
245 attributes.loadingText = context.getString(R.string.download_ebook_loading);
248 attributes.iconBitmap = BitmapFactory.decodeResource(getResources(), styledAttributes.getResourceId(R.styleable
249 .ProgressDownloadButton_drawable, android.R.drawable.ic_delete));
251 attributes.borderSize = styledAttributes.getDimensionPixelSize(R.styleable.ProgressDownloadButton_border_size, context
252 .getResources().getDimensionPixelSize(R.dimen.download_button_border_size_default));
253 attributes.cornerRadius = styledAttributes.getDimensionPixelSize(R.styleable.ProgressDownloadButton_corner_radius, context
254 .getResources().getDimensionPixelSize(R.dimen.download_button_corner_radius_default));
255 attributes.innerCornerRadius = attributes.cornerRadius - attributes.borderSize;
257 // Recycle the TypedArray.
258 baseAttributes.recycle();
259 styledAttributes.recycle();
263 protected void onDraw(Canvas canvas) {
264 canvas.getClipBounds(attributes.baseRect);
265 RectF outerRectF = attributes.outerRectF;
266 int borderSize = attributes.borderSize;
267 outerRectF.set(attributes.baseRect);
268 attributes.innerRectF.set(outerRectF.left + borderSize, outerRectF.top + borderSize, outerRectF.right - borderSize, outerRectF
269 .bottom - borderSize);
272 canvas.drawRoundRect(outerRectF, attributes.cornerRadius, attributes.cornerRadius, attributes.textPaint);
273 canvas.drawRoundRect(attributes.innerRectF, attributes.innerCornerRadius, attributes.innerCornerRadius, attributes.invertedPaint);
275 // Draw current state
276 getState().draw(canvas, attributes, getWidth(), getHeight());
279 public void setState(ProgressDownloadButtonState state) {
280 this.currentState = state;
281 this.setEnabled(state.isEnabled());
285 public ProgressDownloadButtonState getState() {
290 * Sets the text that will overlay.
292 * @param text The text to draw.
294 public void setText(String text) {
295 attributes.initialText = text;
299 * Gets the current text to draw.
301 * @return The current text to draw.
303 public String getText() {
304 return attributes.initialText;
307 public int getCurrentProgress() {
308 return attributes.currentProgress;
311 public void setProgress(int progress) {
312 attributes.currentProgress = progress;
316 public void setCurrentReadCount(int position, int count) {
317 attributes.currentReadPosition = position;
318 attributes.totalReadCount = count;