SearchOrbView.java revision 2fb330f7a11a5c87d4ea8b19a97a99f65b81b42e
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 34public class SearchOrbView extends FrameLayout implements View.OnClickListener { 35 private OnClickListener mListener; 36 private View mSearchOrbView; 37 private int mSearchOrbColor, mSearchOrbColorBright; 38 private final float mFocusedZoom; 39 private final float mBrightnessAlpha; 40 private final int mPulseDurationMs; 41 private final int mScaleDownDurationMs; 42 private ValueAnimator mColorAnimator; 43 44 private final ArgbEvaluator mColorEvaluator = new ArgbEvaluator(); 45 46 private final ValueAnimator.AnimatorUpdateListener mUpdateListener = 47 new ValueAnimator.AnimatorUpdateListener() { 48 @Override 49 public void onAnimationUpdate(ValueAnimator animator) { 50 Integer color = (Integer) animator.getAnimatedValue(); 51 setOrbViewColor(color.intValue()); 52 } 53 }; 54 55 public SearchOrbView(Context context) { 56 this(context, null); 57 } 58 59 public SearchOrbView(Context context, AttributeSet attrs) { 60 this(context, attrs, R.style.Widget_Leanback_SearchOrbViewStyle); 61 } 62 63 public SearchOrbView(Context context, AttributeSet attrs, int defStyle) { 64 super(context, attrs, defStyle); 65 66 LayoutInflater inflater = (LayoutInflater) context 67 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 68 View root = inflater.inflate(R.layout.lb_search_orb, this, true); 69 mSearchOrbView = root.findViewById(R.id.search_orb); 70 71 mFocusedZoom = context.getResources().getFraction( 72 R.fraction.lb_search_orb_focused_zoom, 1, 1); 73 mBrightnessAlpha = context.getResources().getFraction( 74 R.fraction.lb_search_orb_brightness_alpha, 1, 1); 75 mPulseDurationMs = context.getResources().getInteger( 76 R.integer.lb_search_orb_pulse_duration_ms); 77 mScaleDownDurationMs = context.getResources().getInteger( 78 R.integer.lb_search_orb_scale_down_duration_ms); 79 80 ImageView icon = (ImageView)root.findViewById(R.id.icon); 81 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.lbSearchOrbView, 0, 82 defStyle); 83 Drawable img = a.getDrawable(R.styleable.lbSearchOrbView_searchOrbIcon); 84 icon.setImageDrawable(img); 85 86 int color = a.getColor(R.styleable.lbSearchOrbView_searchOrbColor, 0); 87 setOrbColor(color); 88 a.recycle(); 89 90 setFocusable(true); 91 setClipChildren(false); 92 setOnClickListener(this); 93 } 94 95 @Override 96 public void onClick(View view) { 97 if (null != mListener) { 98 mListener.onClick(view); 99 } 100 } 101 102 @Override 103 protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { 104 super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); 105 final float zoom = gainFocus ? mFocusedZoom : 1f; 106 final int duration = gainFocus ? mPulseDurationMs : mScaleDownDurationMs; 107 mSearchOrbView.animate().scaleX(zoom).scaleY(zoom).setDuration(duration).start(); 108 enableOrbColorAnimation(gainFocus); 109 } 110 111 private void enableOrbColorAnimation(boolean enable) { 112 if (mColorAnimator != null) { 113 mColorAnimator.end(); 114 mColorAnimator = null; 115 } 116 if (enable) { 117 // TODO: set interpolator (material if available) 118 mColorAnimator = ValueAnimator.ofObject(mColorEvaluator, 119 mSearchOrbColor, mSearchOrbColorBright, mSearchOrbColor); 120 mColorAnimator.setRepeatCount(ValueAnimator.INFINITE); 121 mColorAnimator.setDuration(mPulseDurationMs * 2); 122 mColorAnimator.addUpdateListener(mUpdateListener); 123 mColorAnimator.start(); 124 } 125 } 126 127 private void setOrbViewColor(int color) { 128 if (mSearchOrbView.getBackground() instanceof GradientDrawable) { 129 ((GradientDrawable) mSearchOrbView.getBackground()).setColor(color); 130 } 131 } 132 133 /** 134 * Set the on click listener for the orb 135 * @param listener The listener. 136 */ 137 public void setOnOrbClickedListener(OnClickListener listener) { 138 mListener = listener; 139 if (null != listener) { 140 setVisibility(View.VISIBLE); 141 } else { 142 setVisibility(View.INVISIBLE); 143 } 144 } 145 146 private int getBrightColor(int color) { 147 final float brightnessValue = 0xff * mBrightnessAlpha; 148 int red = (int)(Color.red(color) * (1 - mBrightnessAlpha) + brightnessValue); 149 int green = (int)(Color.green(color) * (1 - mBrightnessAlpha) + brightnessValue); 150 int blue = (int)(Color.blue(color) * (1 - mBrightnessAlpha) + brightnessValue); 151 int alpha = (int)(Color.alpha(color) * (1 - mBrightnessAlpha) + brightnessValue); 152 return Color.argb(alpha, red, green, blue); 153 } 154 155 public void setOrbColor(int color) { 156 mSearchOrbColor = color; 157 mSearchOrbColorBright = getBrightColor(color); 158 159 if (mColorAnimator == null) { 160 setOrbViewColor(color); 161 } else { 162 enableOrbColorAnimation(true); 163 } 164 } 165 166 public int getOrbColor() { 167 return mSearchOrbColor; 168 } 169} 170