SearchOrbView.java revision 937f910ceb3364a1b84899c2b5f1ff5384f38f84
1/* 2 * Copyright (C) 2014 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 android.support.v17.leanback.widget; 18 19import android.animation.ArgbEvaluator; 20import android.animation.ValueAnimator; 21import android.content.Context; 22import android.content.res.TypedArray; 23import android.graphics.Color; 24import android.graphics.Rect; 25import android.graphics.drawable.Drawable; 26import android.graphics.drawable.GradientDrawable; 27import android.support.v17.leanback.R; 28import android.util.AttributeSet; 29import android.view.LayoutInflater; 30import android.view.View; 31import android.widget.FrameLayout; 32import android.widget.ImageView; 33 34/** 35 * <p>A widget that draws a search affordance, represented by a round background and an icon.</p> 36 * 37 * Background color and icon can be customized 38 */ 39public class SearchOrbView extends FrameLayout implements View.OnClickListener { 40 private OnClickListener mListener; 41 private View mSearchOrbView; 42 private ImageView mIcon; 43 private Drawable mIconDrawable; 44 private int mSearchOrbColor, mSearchOrbColorBright; 45 private final float mFocusedZoom; 46 private final float mBrightnessAlpha; 47 private final int mPulseDurationMs; 48 private final int mScaleDownDurationMs; 49 private ValueAnimator mColorAnimator; 50 51 private final ArgbEvaluator mColorEvaluator = new ArgbEvaluator(); 52 53 private final ValueAnimator.AnimatorUpdateListener mUpdateListener = 54 new ValueAnimator.AnimatorUpdateListener() { 55 @Override 56 public void onAnimationUpdate(ValueAnimator animator) { 57 Integer color = (Integer) animator.getAnimatedValue(); 58 setOrbViewColor(color.intValue()); 59 } 60 }; 61 62 public SearchOrbView(Context context) { 63 this(context, null); 64 } 65 66 public SearchOrbView(Context context, AttributeSet attrs) { 67 this(context, attrs, R.attr.searchOrbViewStyle); 68 } 69 70 public SearchOrbView(Context context, AttributeSet attrs, int defStyleAttr) { 71 super(context, attrs, defStyleAttr); 72 73 LayoutInflater inflater = (LayoutInflater) context 74 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 75 View root = inflater.inflate(R.layout.lb_search_orb, this, true); 76 mSearchOrbView = root.findViewById(R.id.search_orb); 77 mIcon = (ImageView)root.findViewById(R.id.icon); 78 79 mFocusedZoom = context.getResources().getFraction( 80 R.fraction.lb_search_orb_focused_zoom, 1, 1); 81 mBrightnessAlpha = context.getResources().getFraction( 82 R.fraction.lb_search_orb_brightness_alpha, 1, 1); 83 mPulseDurationMs = context.getResources().getInteger( 84 R.integer.lb_search_orb_pulse_duration_ms); 85 mScaleDownDurationMs = context.getResources().getInteger( 86 R.integer.lb_search_orb_scale_down_duration_ms); 87 88 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.lbSearchOrbView, 89 defStyleAttr, 0); 90 Drawable img = a.getDrawable(R.styleable.lbSearchOrbView_searchOrbIcon); 91 setOrbIcon(img); 92 93 int color = a.getColor(R.styleable.lbSearchOrbView_searchOrbColor, 0); 94 setOrbColor(color); 95 a.recycle(); 96 97 setFocusable(true); 98 setClipChildren(false); 99 setOnClickListener(this); 100 } 101 102 @Override 103 public void onClick(View view) { 104 if (null != mListener) { 105 mListener.onClick(view); 106 } 107 } 108 109 @Override 110 protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { 111 super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); 112 final float zoom = gainFocus ? mFocusedZoom : 1f; 113 final int duration = gainFocus ? mPulseDurationMs : mScaleDownDurationMs; 114 mSearchOrbView.animate().scaleX(zoom).scaleY(zoom).setDuration(duration).start(); 115 enableOrbColorAnimation(gainFocus); 116 } 117 118 /** 119 * Set the orb icon 120 * @param icon the drawable to be used as the icon 121 */ 122 public void setOrbIcon(Drawable icon) { 123 mIconDrawable = icon; 124 mIcon.setImageDrawable(mIconDrawable); 125 } 126 127 /** 128 * Returns the orb icon 129 * @return the drawable used as the icon 130 */ 131 public Drawable getOrbIcon() { 132 return mIconDrawable; 133 } 134 135 /** 136 * Set the on click listener for the orb 137 * @param listener The listener. 138 */ 139 public void setOnOrbClickedListener(OnClickListener listener) { 140 mListener = listener; 141 if (null != listener) { 142 setVisibility(View.VISIBLE); 143 } else { 144 setVisibility(View.INVISIBLE); 145 } 146 } 147 148 /** 149 * Set the background color of the search orb. 150 * @param color the RGBA color 151 */ 152 public void setOrbColor(int color) { 153 mSearchOrbColor = color; 154 mSearchOrbColorBright = getBrightColor(color); 155 156 if (mColorAnimator == null) { 157 setOrbViewColor(color); 158 } else { 159 enableOrbColorAnimation(true); 160 } 161 } 162 163 /** 164 * Returns the orb color 165 * @return the RGBA color 166 */ 167 public int getOrbColor() { 168 return mSearchOrbColor; 169 } 170 171 private int getBrightColor(int color) { 172 final float brightnessValue = 0xff * mBrightnessAlpha; 173 int red = (int)(Color.red(color) * (1 - mBrightnessAlpha) + brightnessValue); 174 int green = (int)(Color.green(color) * (1 - mBrightnessAlpha) + brightnessValue); 175 int blue = (int)(Color.blue(color) * (1 - mBrightnessAlpha) + brightnessValue); 176 int alpha = (int)(Color.alpha(color) * (1 - mBrightnessAlpha) + brightnessValue); 177 return Color.argb(alpha, red, green, blue); 178 } 179 180 private void enableOrbColorAnimation(boolean enable) { 181 if (mColorAnimator != null) { 182 mColorAnimator.end(); 183 mColorAnimator = null; 184 } 185 if (enable) { 186 // TODO: set interpolator (material if available) 187 mColorAnimator = ValueAnimator.ofObject(mColorEvaluator, 188 mSearchOrbColor, mSearchOrbColorBright, mSearchOrbColor); 189 mColorAnimator.setRepeatCount(ValueAnimator.INFINITE); 190 mColorAnimator.setDuration(mPulseDurationMs * 2); 191 mColorAnimator.addUpdateListener(mUpdateListener); 192 mColorAnimator.start(); 193 } 194 } 195 196 private void setOrbViewColor(int color) { 197 if (mSearchOrbView.getBackground() instanceof GradientDrawable) { 198 ((GradientDrawable) mSearchOrbView.getBackground()).setColor(color); 199 } 200 } 201 202} 203