SearchOrbView.java revision 2ed0e8a36ac111a3661c56f5dbbe74cfe0696eee
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.graphics.Color; 23import android.graphics.Rect; 24import android.graphics.drawable.GradientDrawable; 25import android.support.v17.leanback.R; 26import android.util.AttributeSet; 27import android.view.LayoutInflater; 28import android.view.View; 29import android.widget.FrameLayout; 30 31public class SearchOrbView extends FrameLayout implements View.OnClickListener { 32 private OnClickListener mListener; 33 private View mSearchOrbView; 34 private int mSearchOrbColor, mSearchOrbColorBright; 35 private final float mFocusedZoom; 36 private final float mBrightnessAlpha; 37 private final int mPulseDurationMs; 38 private final int mScaleDownDurationMs; 39 private ValueAnimator mColorAnimator; 40 41 private final ArgbEvaluator mColorEvaluator = new ArgbEvaluator(); 42 43 private final ValueAnimator.AnimatorUpdateListener mUpdateListener = 44 new ValueAnimator.AnimatorUpdateListener() { 45 @Override 46 public void onAnimationUpdate(ValueAnimator animator) { 47 Integer color = (Integer) animator.getAnimatedValue(); 48 setOrbViewColor(color.intValue()); 49 } 50 }; 51 52 public SearchOrbView(Context context) { 53 this(context, null); 54 } 55 56 public SearchOrbView(Context context, AttributeSet attrs) { 57 this(context, attrs, 0); 58 } 59 60 public SearchOrbView(Context context, AttributeSet attrs, int defStyle) { 61 super(context, attrs, defStyle); 62 63 LayoutInflater inflater = (LayoutInflater) context 64 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 65 View root = inflater.inflate(R.layout.lb_search_orb, this, true); 66 mSearchOrbView = root.findViewById(R.id.search_orb); 67 68 setFocusable(true); 69 setClipChildren(false); 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 setOnClickListener(this); 81 } 82 83 @Override 84 public void onClick(View view) { 85 if (null != mListener) { 86 mListener.onClick(view); 87 } 88 } 89 90 @Override 91 protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { 92 super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); 93 final float zoom = gainFocus ? mFocusedZoom : 1f; 94 final int duration = gainFocus ? mPulseDurationMs : mScaleDownDurationMs; 95 mSearchOrbView.animate().scaleX(zoom).scaleY(zoom).setDuration(duration).start(); 96 enableOrbColorAnimation(gainFocus); 97 } 98 99 private void enableOrbColorAnimation(boolean enable) { 100 if (mColorAnimator != null) { 101 mColorAnimator.end(); 102 mColorAnimator = null; 103 } 104 if (enable) { 105 // TODO: set interpolator (quantum if available) 106 mColorAnimator = ValueAnimator.ofObject(mColorEvaluator, 107 mSearchOrbColor, mSearchOrbColorBright, mSearchOrbColor); 108 mColorAnimator.setRepeatCount(ValueAnimator.INFINITE); 109 mColorAnimator.setDuration(mPulseDurationMs * 2); 110 mColorAnimator.addUpdateListener(mUpdateListener); 111 mColorAnimator.start(); 112 } 113 } 114 115 private void setOrbViewColor(int color) { 116 if (mSearchOrbView.getBackground() instanceof GradientDrawable) { 117 ((GradientDrawable) mSearchOrbView.getBackground()).setColor(color); 118 } 119 } 120 121 /** 122 * Set the on click listener for the orb 123 * @param listener The listener. 124 */ 125 public void setOnOrbClickedListener(OnClickListener listener) { 126 mListener = listener; 127 if (null != listener) { 128 setVisibility(View.VISIBLE); 129 } else { 130 setVisibility(View.INVISIBLE); 131 } 132 } 133 134 private int getBrightColor(int color) { 135 final float brightnessValue = 0xff * mBrightnessAlpha; 136 int red = (int)(Color.red(color) * (1 - mBrightnessAlpha) + brightnessValue); 137 int green = (int)(Color.green(color) * (1 - mBrightnessAlpha) + brightnessValue); 138 int blue = (int)(Color.blue(color) * (1 - mBrightnessAlpha) + brightnessValue); 139 int alpha = (int)(Color.alpha(color) * (1 - mBrightnessAlpha) + brightnessValue); 140 return Color.argb(alpha, red, green, blue); 141 } 142 143 public void setOrbColor(int color) { 144 mSearchOrbColor = color; 145 mSearchOrbColorBright = getBrightColor(color); 146 147 if (mColorAnimator == null) { 148 setOrbViewColor(color); 149 } else { 150 enableOrbColorAnimation(true); 151 } 152 } 153} 154