1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.setupwizardlib.template; 18 19import android.content.res.ColorStateList; 20import android.os.Build; 21import android.os.Build.VERSION_CODES; 22import android.support.annotation.Nullable; 23import android.view.View; 24import android.view.ViewStub; 25import android.widget.ProgressBar; 26 27import com.android.setupwizardlib.R; 28import com.android.setupwizardlib.TemplateLayout; 29 30/** 31 * A {@link Mixin} for showing a progress bar. 32 */ 33public class ProgressBarMixin implements Mixin { 34 35 private TemplateLayout mTemplateLayout; 36 37 @Nullable 38 private ColorStateList mColor; 39 40 /** 41 * @param layout The layout this mixin belongs to. 42 */ 43 public ProgressBarMixin(TemplateLayout layout) { 44 mTemplateLayout = layout; 45 } 46 47 /** 48 * @return True if the progress bar is currently shown. 49 */ 50 public boolean isShown() { 51 final View progressBar = mTemplateLayout.findManagedViewById(R.id.suw_layout_progress); 52 return progressBar != null && progressBar.getVisibility() == View.VISIBLE; 53 } 54 55 /** 56 * Sets whether the progress bar is shown. If the progress bar has not been inflated from the 57 * stub, this method will inflate the progress bar. 58 * 59 * @param shown True to show the progress bar, false to hide it. 60 */ 61 public void setShown(boolean shown) { 62 if (shown) { 63 View progressBar = getProgressBar(); 64 if (progressBar != null) { 65 progressBar.setVisibility(View.VISIBLE); 66 } 67 } else { 68 View progressBar = peekProgressBar(); 69 if (progressBar != null) { 70 progressBar.setVisibility(View.GONE); 71 } 72 } 73 } 74 75 /** 76 * Gets the progress bar in the layout. If the progress bar has not been used before, it will be 77 * installed (i.e. inflated from its view stub). 78 * 79 * @return The progress bar of this layout. May be null only if the template used doesn't have a 80 * progress bar built-in. 81 */ 82 private ProgressBar getProgressBar() { 83 final View progressBar = peekProgressBar(); 84 if (progressBar == null) { 85 final ViewStub progressBarStub = 86 (ViewStub) mTemplateLayout.findManagedViewById(R.id.suw_layout_progress_stub); 87 if (progressBarStub != null) { 88 progressBarStub.inflate(); 89 } 90 setColor(mColor); 91 } 92 return peekProgressBar(); 93 } 94 95 /** 96 * Gets the progress bar in the layout only if it has been installed. 97 * {@link #setShown(boolean)} should be called before this to ensure the progress bar 98 * is set up correctly. 99 * 100 * @return The progress bar of this layout, or null if the progress bar is not installed. The 101 * null case can happen either if {@link #setShown(boolean)} with true was 102 * not called before this, or if the template does not contain a progress bar. 103 */ 104 public ProgressBar peekProgressBar() { 105 return (ProgressBar) mTemplateLayout.findManagedViewById(R.id.suw_layout_progress); 106 } 107 108 /** 109 * Sets the color of the indeterminate progress bar. This method is a no-op on SDK < 21. 110 */ 111 public void setColor(@Nullable ColorStateList color) { 112 mColor = color; 113 if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { 114 final ProgressBar bar = peekProgressBar(); 115 if (bar != null) { 116 bar.setIndeterminateTintList(color); 117 if (Build.VERSION.SDK_INT >= VERSION_CODES.M || color != null) { 118 // There is a bug in Lollipop where setting the progress tint color to null 119 // will crash with "java.lang.NullPointerException: Attempt to invoke virtual 120 // method 'int android.graphics.Paint.getAlpha()' on a null object reference" 121 // at android.graphics.drawable.NinePatchDrawable.draw(:250) 122 // The bug doesn't affect ProgressBar on M because it uses ShapeDrawable instead 123 // of NinePatchDrawable. (commit 6a8253fdc9f4574c28b4beeeed90580ffc93734a) 124 bar.setProgressBackgroundTintList(color); 125 } 126 } 127 } 128 } 129 130 /** 131 * @return The color previously set in {@link #setColor(ColorStateList)}, or null if the color 132 * is not set. In case of null, the color of the progress bar will be inherited from the theme. 133 */ 134 @Nullable 135 public ColorStateList getColor() { 136 return mColor; 137 } 138} 139