1e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling/* 2e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * Copyright (C) 2013 The Android Open Source Project 3e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * 4e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * Licensed under the Apache License, Version 2.0 (the "License"); 5e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * you may not use this file except in compliance with the License. 6e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * You may obtain a copy of the License at 7e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * 8e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * http://www.apache.org/licenses/LICENSE-2.0 9e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * 10e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * Unless required by applicable law or agreed to in writing, software 11e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * distributed under the License is distributed on an "AS IS" BASIS, 12e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * See the License for the specific language governing permissions and 14e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * limitations under the License. 15e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling */ 16e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling 17e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberlingpackage com.android.camera.ui; 18e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling 19e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberlingimport android.content.Context; 20e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberlingimport android.graphics.Canvas; 21e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberlingimport android.graphics.Color; 22e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberlingimport android.graphics.Paint; 23e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberlingimport android.graphics.RectF; 245ce035e98ca289b0b0ca884c4d2bb2fd43d8c187Erin Dahlgrenimport android.view.View; 25e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling 26e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberlingimport com.android.camera2.R; 27e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling 28e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling/** 29e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * Renders a circular progress bar on the screen. 30e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling */ 31e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberlingpublic class ProgressRenderer { 32e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling private final int mProgressRadius; 33e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling private final Paint mProgressBasePaint; 34e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling private final Paint mProgressPaint; 35e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling 36e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling private RectF mArcBounds = new RectF(0, 0, 1, 1); 37e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling private int mProgressAngleDegrees = 270; 38e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling private boolean mVisible = false; 3990f158340db39bca9ee5da4cf1d246adbcb03453Sascha Haeberling private final View mParentView; 4090f158340db39bca9ee5da4cf1d246adbcb03453Sascha Haeberling private final Runnable mInvalidateParentViewRunnable = new Runnable() { 4190f158340db39bca9ee5da4cf1d246adbcb03453Sascha Haeberling @Override 4290f158340db39bca9ee5da4cf1d246adbcb03453Sascha Haeberling public void run() { 4390f158340db39bca9ee5da4cf1d246adbcb03453Sascha Haeberling mParentView.invalidate(); 4490f158340db39bca9ee5da4cf1d246adbcb03453Sascha Haeberling } 4590f158340db39bca9ee5da4cf1d246adbcb03453Sascha Haeberling }; 46b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling 47b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling /** 4849ea51ab31f8e39fd48577b704695cb437f644afSascha Haeberling * After we reach 100%, keep on painting the progress for another x milliseconds 49b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling * before hiding it. 50b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling */ 5149ea51ab31f8e39fd48577b704695cb437f644afSascha Haeberling private static final int SHOW_PROGRESS_X_ADDITIONAL_MS = 100; 5249ea51ab31f8e39fd48577b704695cb437f644afSascha Haeberling 535ce035e98ca289b0b0ca884c4d2bb2fd43d8c187Erin Dahlgren public ProgressRenderer(Context context, View parent) { 545ce035e98ca289b0b0ca884c4d2bb2fd43d8c187Erin Dahlgren mParentView = parent; 55e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling mProgressRadius = context.getResources().getDimensionPixelSize(R.dimen.pie_progress_radius); 56e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling int pieProgressWidth = context.getResources().getDimensionPixelSize( 57e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling R.dimen.pie_progress_width); 58e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling mProgressBasePaint = createProgressPaint(pieProgressWidth, 0.2f); 59e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling mProgressPaint = createProgressPaint(pieProgressWidth, 1.0f); 60e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling } 61e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling 62b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling /** 63e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * Shows a progress indicator. If the progress is '100', the progress 64e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * indicator will be hidden. 6590f158340db39bca9ee5da4cf1d246adbcb03453Sascha Haeberling * <p> 6690f158340db39bca9ee5da4cf1d246adbcb03453Sascha Haeberling * Can be called from any thread. 67e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * 68e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * @param percent the progress in percent (0-100). 69e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling */ 70e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling public void setProgress(int percent) { 71e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling // Clamp the value. 72e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling percent = Math.min(100, Math.max(percent, 0)); 73e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling mProgressAngleDegrees = (int) ((360f / 100) * percent); 74e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling 75b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling // We hide the progress once we drew the 100% state once. 76b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling if (percent < 100) { 77b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling mVisible = true; 78b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling } 7990f158340db39bca9ee5da4cf1d246adbcb03453Sascha Haeberling mParentView.post(mInvalidateParentViewRunnable); 80e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling } 81e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling 82e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling /** 83e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling * Draw the current progress (if < 100%) centered at the given location. 84e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling */ 85e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling public void onDraw(Canvas canvas, int centerX, int centerY) { 86e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling if (!mVisible) { 87e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling return; 88e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling } 89e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling mArcBounds = new RectF(centerX - mProgressRadius, centerY - mProgressRadius, centerX 90e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling + mProgressRadius, 91e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling centerY + mProgressRadius); 92e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling 93e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling canvas.drawCircle(centerX, centerY, mProgressRadius, mProgressBasePaint); 94e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling canvas.drawArc(mArcBounds, -90, mProgressAngleDegrees, false, mProgressPaint); 95b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling 96b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling // After we reached 100%, we paint the progress renderer for another x 9749ea51ab31f8e39fd48577b704695cb437f644afSascha Haeberling // milliseconds until we hide it. 985ce035e98ca289b0b0ca884c4d2bb2fd43d8c187Erin Dahlgren if (mProgressAngleDegrees == 360) { 9949ea51ab31f8e39fd48577b704695cb437f644afSascha Haeberling mVisible = false; 1005ce035e98ca289b0b0ca884c4d2bb2fd43d8c187Erin Dahlgren mParentView.postDelayed( 1015ce035e98ca289b0b0ca884c4d2bb2fd43d8c187Erin Dahlgren new Runnable() { 1025ce035e98ca289b0b0ca884c4d2bb2fd43d8c187Erin Dahlgren @Override 1035ce035e98ca289b0b0ca884c4d2bb2fd43d8c187Erin Dahlgren public void run() { 1045ce035e98ca289b0b0ca884c4d2bb2fd43d8c187Erin Dahlgren mParentView.invalidate(); 1055ce035e98ca289b0b0ca884c4d2bb2fd43d8c187Erin Dahlgren } 1065ce035e98ca289b0b0ca884c4d2bb2fd43d8c187Erin Dahlgren }, SHOW_PROGRESS_X_ADDITIONAL_MS); 107b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling } 108b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling } 109b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling 110b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling /** 111b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling * @return Whether the progress renderer is visible. 112b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling */ 113b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling public boolean isVisible() { 114b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling return mVisible; 115b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling } 116b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling 117b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling private static Paint createProgressPaint(int width, float alpha) { 118b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling Paint paint = new Paint(); 119b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling paint.setAntiAlias(true); 120b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling // 20% alpha. 121b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling paint.setColor(Color.argb((int) (alpha * 255), 255, 255, 255)); 122b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling paint.setStrokeWidth(width); 123b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling paint.setStyle(Paint.Style.STROKE); 124b7b73ec15e05605db6cc2b7f42bbc61d441da1d2Sascha Haeberling return paint; 125e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling } 126e0ecc64979a29e5bbdd1084712b231070b1d57bfSascha Haeberling} 127